diff --git a/Algorithms/Graphs/DijkstraShortestPaths.cs b/Algorithms/Graphs/DijkstraShortestPaths.cs index c72f7719..1977ab72 100644 --- a/Algorithms/Graphs/DijkstraShortestPaths.cs +++ b/Algorithms/Graphs/DijkstraShortestPaths.cs @@ -27,6 +27,20 @@ public class DijkstraShortestPaths private readonly TGraph _graph; private readonly TVertex _source; + private long GetEdgeWeight(IEdge edge) + { + // TODO: Change Dijkstra algorithm to support edge weights that are not Int64 compatible. + if (edge.IsWeighted) + { + var e = edge as WeightedEdge; + return e.Weight; + } + else + { + return 1; + } + } + public DijkstraShortestPaths(TGraph graph, TVertex source) { if (graph == null) @@ -38,7 +52,7 @@ public DijkstraShortestPaths(TGraph graph, TVertex source) if (!graph.HasVertex(source)) throw new ArgumentException("The source vertex doesn't belong to graph."); - if (graph.Edges.Any(edge => edge.Weight < 0)) + if (graph.Edges.Any(edge => GetEdgeWeight(edge) < 0)) throw new ArgumentException("Negative edge weight detected."); _graph = graph; @@ -62,7 +76,7 @@ private void _dijkstra() foreach (var outgoingEdge in outgoingEdges) { var adjacentIndex = _nodesToIndices[outgoingEdge.Destination]; - var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + outgoingEdge.Weight : Infinity; + var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + GetEdgeWeight(outgoingEdge) : Infinity; if (delta < _distances[adjacentIndex]) { diff --git a/DataStructures/Graphs/CliqueGraph.cs b/DataStructures/Graphs/CliqueGraph.cs index 2d075564..4707c976 100644 --- a/DataStructures/Graphs/CliqueGraph.cs +++ b/DataStructures/Graphs/CliqueGraph.cs @@ -824,7 +824,6 @@ static V Pick(IEnumerable Set) enumerator.Dispose(); return ret; } - } internal class UnordererPair : Tuple, IEquatable> where T : IEquatable diff --git a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs index 68ea3c5e..492f8db8 100644 --- a/DataStructures/Graphs/DirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedDenseGraph.cs @@ -23,18 +23,18 @@ namespace DataStructures.Graphs /// /// This class represents the graph as an adjacency-matrix (two dimensional integer array). /// - public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable + public class DirectedWeightedDenseGraph : DirectedDenseGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_SLOT = 0; + private static readonly W EMPTY_EDGE_SLOT = default(W); private const object EMPTY_VERTEX_SLOT = (object)null; // Store edges and their weights as integers. // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } + protected new W[,] _adjacencyMatrix { get; set; } /// @@ -47,7 +47,7 @@ public DirectedWeightedDenseGraph(uint capacity = 10) _verticesCapacity = (int)capacity; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } @@ -57,13 +57,13 @@ public DirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT); + return (EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination])); } /// /// Helper function. Gets the weight of a directed edge. /// - private long _getEdgeWeight(int source, int destination) + private W _getEdgeWeight(int source, int destination) { return _adjacencyMatrix[source, destination]; } @@ -80,7 +80,7 @@ public override bool IsWeighted /// /// An enumerable collection of all weighted directed edges in graph. /// - public virtual IEnumerable> Edges + public new virtual IEnumerable> Edges { get { @@ -93,7 +93,7 @@ public virtual IEnumerable> Edges /// /// Get all incoming unweighted edges to a vertex. /// - public virtual IEnumerable> IncomingEdges(T vertex) + public new virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -104,7 +104,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(adjacent, source)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight @@ -116,7 +116,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing unweighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public new virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -127,7 +127,7 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight @@ -149,10 +149,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public virtual bool AddEdge(T source, T destination, long weight) + public virtual bool AddEdge(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -199,10 +199,10 @@ public override bool RemoveEdge(T source, T destination) /// /// Updates the edge weight from source to destination. /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + public virtual bool UpdateEdgeWeight(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -271,7 +271,7 @@ public override bool RemoveVertex(T vertex) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { // Get indices of vertices int srcIndex = _vertices.IndexOf(source); @@ -283,13 +283,13 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) throw new Exception("Edge doesn't exist."); - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); } /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -297,12 +297,12 @@ public virtual long GetEdgeWeight(T source, T destination) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public virtual Dictionary NeighboursMap(T vertex) + public virtual Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; - var neighbors = new Dictionary(); + var neighbors = new Dictionary(); int source = _vertices.IndexOf(vertex); // Check existence of vertex @@ -351,11 +351,14 @@ public override void Clear() _edgesCount = 0; _verticesCount = 0; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } } + public class DirectedWeightedDenseGraph : DirectedWeightedDenseGraph, IWeightedGraph where T : IComparable + { + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + } } - diff --git a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs index 66c0ccfe..4222ac39 100644 --- a/DataStructures/Graphs/DirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/DirectedWeightedSparseGraph.cs @@ -13,20 +13,21 @@ using System; using System.Collections.Generic; +using System.Linq; using DataStructures.Common; using DataStructures.Lists; namespace DataStructures.Graphs { - public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable + public class DirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_VALUE = 0; + private static readonly W EMPTY_EDGE_VALUE = default(W); protected virtual int _edgesCount { get; set; } protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } /// @@ -37,19 +38,19 @@ public DirectedWeightedSparseGraph() : this(10) { } public DirectedWeightedSparseGraph(uint initialCapacity) { _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); + _adjacencyList = new Dictionary>>((int)initialCapacity); } /// /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) + protected virtual WeightedEdge _tryGetEdge(T source, T destination) { - WeightedEdge edge = null; + WeightedEdge edge = null; // Predicate - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); // Try to find a match if(_adjacencyList.ContainsKey(source)) @@ -72,7 +73,7 @@ protected virtual bool _doesEdgeExist(T source, T destination) /// Helper function. Gets the weight of a directed edge. /// Presumes edge does already exist. /// - private long _getEdgeWeight(T source, T destination) + private W _getEdgeWeight(T source, T destination) { return _tryGetEdge(source, destination).Weight; } @@ -142,7 +143,7 @@ IEnumerable> IGraph.OutgoingEdges(T vertex) /// /// An enumerable collection of all directed weighted edges in graph. /// - public virtual IEnumerable> Edges + public virtual IEnumerable> Edges { get { @@ -155,16 +156,16 @@ public virtual IEnumerable> Edges /// /// Get all incoming directed weighted edges to a vertex. /// - public virtual IEnumerable> IncomingEdges(T vertex) + public virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); - var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); + var predicate = new Predicate>((edge) => edge.Destination.IsEqualTo(vertex)); foreach(var adjacent in _adjacencyList.Keys) { - WeightedEdge incomingEdge = null; + WeightedEdge incomingEdge = null; if (_adjacencyList[adjacent].TryFindFirst(predicate, out incomingEdge)) yield return incomingEdge; @@ -174,7 +175,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing directed weighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -196,10 +197,10 @@ public bool AddEdge(T source, T destination) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public bool AddEdge(T source, T destination, long weight) + public bool AddEdge(T source, T destination, W weight) { // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -207,7 +208,7 @@ public bool AddEdge(T source, T destination, long weight) return false; // Add edge from source to destination - var edge = new WeightedEdge(source, destination, weight); + var edge = new WeightedEdge(source, destination, weight); _adjacencyList[source].Append(edge); // Increment edges count @@ -241,10 +242,10 @@ public virtual bool RemoveEdge(T source, T destination) return true; } - public bool UpdateEdgeWeight(T source, T destination, long weight) + public bool UpdateEdgeWeight(T source, T destination, W weight) { // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -264,7 +265,7 @@ public bool UpdateEdgeWeight(T source, T destination, long weight) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { if (!HasVertex(source) || !HasVertex(destination)) throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); @@ -282,7 +283,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -310,7 +311,7 @@ public virtual bool AddVertex(T vertex) if (_adjacencyList.Count == 0) _firstInsertedNode = vertex; - _adjacencyList.Add(vertex, new DLinkedList>()); + _adjacencyList.Add(vertex, new DLinkedList>()); return true; } @@ -383,13 +384,13 @@ public virtual DLinkedList Neighbours(T vertex) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public Dictionary NeighboursMap(T vertex) + public Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + var map = new Dictionary(neighbors.Count); foreach (var adjacent in neighbors) map.Add(adjacent.Destination, adjacent.Weight); @@ -538,4 +539,20 @@ public virtual void Clear() } + public class DirectedWeightedSparseGraph : DirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable + { + public new IEnumerable> Edges => base.Edges.Select(edge => edge.ToSimpleEdge()); + + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + + public new IEnumerable> IncomingEdges(T vertex) => base.IncomingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + + public new IEnumerable> OutgoingEdges(T vertex) => base.OutgoingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + + IEnumerable> IGraph.Edges => this.Edges; + + IEnumerable> IGraph.IncomingEdges(T vertex) => this.IncomingEdges(vertex); + + IEnumerable> IGraph.OutgoingEdges(T vertex) => this.OutgoingEdges(vertex); + } } diff --git a/DataStructures/Graphs/IEdge.cs b/DataStructures/Graphs/IEdge.cs index 35371119..ca269042 100644 --- a/DataStructures/Graphs/IEdge.cs +++ b/DataStructures/Graphs/IEdge.cs @@ -24,13 +24,6 @@ public interface IEdge : IComparable> where TVertex : IC /// /// The destination. TVertex Destination { get; set; } - - /// - /// Gets or sets the weight of edge. - /// Unwighted edges can be thought of as edges of the same weight - /// - /// The weight. - Int64 Weight { get; set; } } } diff --git a/DataStructures/Graphs/IGraph.cs b/DataStructures/Graphs/IGraph.cs index 1ae595cc..4b0e0a02 100644 --- a/DataStructures/Graphs/IGraph.cs +++ b/DataStructures/Graphs/IGraph.cs @@ -125,4 +125,3 @@ public interface IGraph where T : IComparable void Clear(); } } - diff --git a/DataStructures/Graphs/IWeightedGraph.cs b/DataStructures/Graphs/IWeightedGraph.cs index 66f3a857..d4877f78 100644 --- a/DataStructures/Graphs/IWeightedGraph.cs +++ b/DataStructures/Graphs/IWeightedGraph.cs @@ -5,32 +5,40 @@ namespace DataStructures.Graphs /// /// This interface should be implemented alongside the IGraph interface. /// - public interface IWeightedGraph where T : IComparable + public interface IWeightedGraph where T : IComparable where W : IComparable { /// /// Connects two vertices together with a weight, in the direction: first->second. /// - bool AddEdge(T source, T destination, long weight); + bool AddEdge(T source, T destination, W weight); /// /// Updates the edge weight from source to destination. /// - bool UpdateEdgeWeight(T source, T destination, long weight); + bool UpdateEdgeWeight(T source, T destination, W weight); /// /// Get edge object from source to destination. /// - WeightedEdge GetEdge(T source, T destination); + WeightedEdge GetEdge(T source, T destination); /// /// Returns the edge weight from source to destination. /// - long GetEdgeWeight(T source, T destination); + W GetEdgeWeight(T source, T destination); /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - System.Collections.Generic.Dictionary NeighboursMap(T vertex); + System.Collections.Generic.Dictionary NeighboursMap(T vertex); + } + + public interface IWeightedGraph : IWeightedGraph where T : IComparable + { + /// + /// Get edge object from source to destination. + /// + new WeightedEdge GetEdge(T source, T destination); } } diff --git a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs index a5086a3f..964fc549 100644 --- a/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedDenseGraph.cs @@ -1,11 +1,11 @@ /*** * The Undirected Weighted Dense Graph Data Structure. - * + * * Definition: * A dense graph is a graph G = (V, E) in which |E| = O(|V|^2). * A weighted graph is a graph where each edge has a weight (zero weights mean there is no edge). - * - * An adjacency-matrix (two dimensional array of longs) weighted graph representation. + * + * An adjacency-matrix (two dimensional array of longs) weighted graph representation. * Inherits and extends the Undirected Dense verion (UndirectedDenseGraph class). * Implements the IWeightedGraph interface. */ @@ -20,17 +20,17 @@ namespace DataStructures.Graphs /// /// This class represents the graph as an adjacency-matrix (two dimensional integer array). /// - public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable + public class UndirectedWeightedDenseGraph : UndirectedDenseGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_SLOT = 0; + private static readonly W EMPTY_EDGE_SLOT = default(W); // Store edges and their weights as integers. // Any edge with a value of zero means it doesn't exist. Otherwise, it exist with a specific weight value. // Default value for positive edges is 1. - protected new long[,] _adjacencyMatrix { get; set; } + protected new W[,] _adjacencyMatrix { get; set; } /// /// CONSTRUCTOR @@ -42,7 +42,7 @@ public UndirectedWeightedDenseGraph(uint capacity = 10) _verticesCapacity = (int)capacity; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(_verticesCapacity, _verticesCapacity, EMPTY_EDGE_SLOT); } @@ -51,15 +51,15 @@ public UndirectedWeightedDenseGraph(uint capacity = 10) /// protected override bool _doesEdgeExist(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT) || (_adjacencyMatrix[destination, source] != EMPTY_EDGE_SLOT); + return (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination])) || (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[destination, source])); } /// /// Helper function. Gets the weight of a undirected edge. /// - private long _getEdgeWeight(int source, int destination) + private W _getEdgeWeight(int source, int destination) { - return (_adjacencyMatrix[source, destination] != EMPTY_EDGE_SLOT ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]); + return (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[source, destination]) ? _adjacencyMatrix[source, destination] : _adjacencyMatrix[destination, source]); } /// @@ -73,7 +73,7 @@ public override bool IsWeighted /// /// An enumerable collection of edges. /// - public virtual IEnumerable> Edges + public new virtual IEnumerable> Edges { get { @@ -88,7 +88,7 @@ public virtual IEnumerable> Edges // Check existence of vertex if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - var neighbor = (T)_vertices[adjacent]; + var neighbor = (T)_vertices[adjacent]; var weight = _getEdgeWeight(source, adjacent); var outgoingEdge = new KeyValuePair((T)vertex, neighbor); @@ -99,7 +99,7 @@ public virtual IEnumerable> Edges continue; seen.Add(outgoingEdge); - yield return (new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight)); + yield return (new WeightedEdge(outgoingEdge.Key, outgoingEdge.Value, weight)); } } }//end-foreach @@ -109,7 +109,7 @@ public virtual IEnumerable> Edges /// /// Get all incoming edges to a vertex /// - public virtual IEnumerable> IncomingEdges(T vertex) + public new virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); @@ -119,7 +119,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( (T)_vertices[adjacent], // from vertex, // to _getEdgeWeight(source, adjacent) // weight @@ -131,7 +131,7 @@ public virtual IEnumerable> IncomingEdges(T vertex) /// /// Get all outgoing weighted edges from vertex /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public new virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new ArgumentOutOfRangeException("One of vertex is not part of the graph."); @@ -141,7 +141,7 @@ public virtual IEnumerable> OutgoingEdges(T vertex) { if (_vertices[adjacent] != null && _doesEdgeExist(source, adjacent)) { - yield return (new WeightedEdge( + yield return (new WeightedEdge( vertex, // from (T)_vertices[adjacent], // to _getEdgeWeight(source, adjacent) // weight @@ -153,10 +153,10 @@ public virtual IEnumerable> OutgoingEdges(T vertex) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public virtual bool AddEdge(T source, T destination, long weight) + public virtual bool AddEdge(T source, T destination, W weight) { // Return if the weight is equals to the empty edge value - if (weight == EMPTY_EDGE_SLOT) + if (EMPTY_EDGE_SLOT.Equals(weight)) return false; // Get indices of vertices @@ -201,7 +201,7 @@ public override bool RemoveEdge(T source, T destination) /// /// Updates the edge weight from source to destination. /// - public virtual bool UpdateEdgeWeight(T source, T destination, long weight) + public virtual bool UpdateEdgeWeight(T source, T destination, W weight) { int srcIndex = _vertices.IndexOf(source); int dstIndex = _vertices.IndexOf(destination); @@ -211,7 +211,7 @@ public virtual bool UpdateEdgeWeight(T source, T destination, long weight) if (!_doesEdgeExist(srcIndex, dstIndex)) return false; - if (_adjacencyMatrix[srcIndex, dstIndex] != EMPTY_EDGE_SLOT) + if (!EMPTY_EDGE_SLOT.Equals(_adjacencyMatrix[srcIndex, dstIndex])) _adjacencyMatrix[srcIndex, dstIndex] = weight; else _adjacencyMatrix[dstIndex, srcIndex] = weight; @@ -261,7 +261,7 @@ public override bool RemoveVertex(T vertex) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { int srcIndex = _vertices.IndexOf(source); int dstIndex = _vertices.IndexOf(destination); @@ -272,13 +272,13 @@ public virtual WeightedEdge GetEdge(T source, T destination) if (!_doesEdgeExist(srcIndex, dstIndex)) return null; - return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); + return (new WeightedEdge(source, destination, _getEdgeWeight(srcIndex, dstIndex))); } /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -286,12 +286,12 @@ public virtual long GetEdgeWeight(T source, T destination) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public virtual Dictionary NeighboursMap(T vertex) + public virtual Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; - var neighbors = new Dictionary(); + var neighbors = new Dictionary(); int source = _vertices.IndexOf(vertex); // Check existence of vertex @@ -340,8 +340,13 @@ public override void Clear() _edgesCount = 0; _verticesCount = 0; _vertices = new ArrayList(_verticesCapacity); - _adjacencyMatrix = new long[_verticesCapacity, _verticesCapacity]; + _adjacencyMatrix = new W[_verticesCapacity, _verticesCapacity]; _adjacencyMatrix.Populate(rows: _verticesCapacity, columns: _verticesCapacity, defaultValue: EMPTY_EDGE_SLOT); } } + + public class UndirectedWeightedDenseGraph : UndirectedWeightedDenseGraph, IWeightedGraph where T : IComparable + { + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination)?.ToSimpleEdge(); + } } diff --git a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs index 20859241..af941571 100644 --- a/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs +++ b/DataStructures/Graphs/UndirectedWeightedSparseGraph.cs @@ -12,20 +12,21 @@ using System; using System.Collections.Generic; +using System.Linq; using DataStructures.Common; using DataStructures.Lists; namespace DataStructures.Graphs { - public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable + public class UndirectedWeightedSparseGraph : IGraph, IWeightedGraph where T : IComparable where W : IComparable { /// /// INSTANCE VARIABLES /// - private const long EMPTY_EDGE_VALUE = 0; + private static readonly W EMPTY_EDGE_VALUE = default(W); protected virtual int _edgesCount { get; set; } protected virtual T _firstInsertedNode { get; set; } - protected virtual Dictionary>> _adjacencyList { get; set; } + protected virtual Dictionary>> _adjacencyList { get; set; } /// @@ -36,20 +37,20 @@ public UndirectedWeightedSparseGraph() : this(10) { } public UndirectedWeightedSparseGraph(uint initialCapacity) { _edgesCount = 0; - _adjacencyList = new Dictionary>>((int)initialCapacity); + _adjacencyList = new Dictionary>>((int)initialCapacity); } /// /// Helper function. Returns edge object from source to destination, if exists; otherwise, null. /// - protected virtual WeightedEdge _tryGetEdge(T source, T destination) + protected virtual WeightedEdge _tryGetEdge(T source, T destination) { var success = false; - WeightedEdge edge = null; + WeightedEdge edge = null; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); if(_adjacencyList.ContainsKey(source)) success = _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge); @@ -73,7 +74,7 @@ protected virtual bool _doesEdgeExist(T source, T destination) /// Helper function. Gets the weight of a undirected edge. /// Presumes edge does already exist. /// - private long _getEdgeWeight(T source, T destination) + private W _getEdgeWeight(T source, T destination) { return _tryGetEdge(source, destination).Weight; } @@ -143,7 +144,7 @@ IEnumerable> IGraph.OutgoingEdges(T vertex) /// /// An enumerable collection of all weighted edges in Graph. /// - public virtual IEnumerable> Edges + public virtual IEnumerable> Edges { get { @@ -169,19 +170,19 @@ public virtual IEnumerable> Edges /// /// Get all incoming weighted edges to a vertex /// - public virtual IEnumerable> IncomingEdges(T vertex) + public virtual IEnumerable> IncomingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); foreach(var edge in _adjacencyList[vertex]) - yield return (new WeightedEdge(edge.Destination, edge.Source, edge.Weight)); + yield return (new WeightedEdge(edge.Destination, edge.Source, edge.Weight)); } /// /// Get all outgoing weighted edges from a vertex. /// - public virtual IEnumerable> OutgoingEdges(T vertex) + public virtual IEnumerable> OutgoingEdges(T vertex) { if (!HasVertex(vertex)) throw new KeyNotFoundException("Vertex doesn't belong to graph."); @@ -203,10 +204,10 @@ public bool AddEdge(T source, T destination) /// /// Connects two vertices together with a weight, in the direction: first->second. /// - public bool AddEdge(T source, T destination, long weight) + public bool AddEdge(T source, T destination, W weight) { // Check existence of nodes, the validity of the weight value, and the non-existence of edge - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -214,8 +215,8 @@ public bool AddEdge(T source, T destination, long weight) return false; // Add edge from source to destination - var sourceDdge = new WeightedEdge(source, destination, weight); - var destinationEdge = new WeightedEdge(destination, source, weight); + var sourceDdge = new WeightedEdge(source, destination, weight); + var destinationEdge = new WeightedEdge(destination, source, weight); _adjacencyList[source].Append(sourceDdge); _adjacencyList[destination].Append(destinationEdge); @@ -235,12 +236,12 @@ public virtual bool RemoveEdge(T source, T destination) if (!HasVertex(source) || !HasVertex(destination)) return false; - WeightedEdge edge1, edge2; + WeightedEdge edge1, edge2; - var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); + var sourceToDestinationPredicate = new Predicate>((item) => item.Source.IsEqualTo(source) && item.Destination.IsEqualTo(destination)); _adjacencyList[source].TryFindFirst(sourceToDestinationPredicate, out edge1); - var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); + var destinationToSourcePredicate = new Predicate>((item) => item.Source.IsEqualTo(destination) && item.Destination.IsEqualTo(source)); _adjacencyList[destination].TryFindFirst(destinationToSourcePredicate, out edge2); // If edge doesn't exist, return false @@ -261,10 +262,10 @@ public virtual bool RemoveEdge(T source, T destination) return true; } - public bool UpdateEdgeWeight(T source, T destination, long weight) + public bool UpdateEdgeWeight(T source, T destination, W weight) { // Check existence of vertices and validity of the weight value - if (weight == EMPTY_EDGE_VALUE) + if (EMPTY_EDGE_VALUE.Equals(weight)) return false; if (!HasVertex(source) || !HasVertex(destination)) return false; @@ -300,7 +301,7 @@ public bool UpdateEdgeWeight(T source, T destination, long weight) /// /// Get edge object from source to destination. /// - public virtual WeightedEdge GetEdge(T source, T destination) + public virtual WeightedEdge GetEdge(T source, T destination) { if (!HasVertex(source) || !HasVertex(destination)) throw new KeyNotFoundException("Either one of the vertices or both of them don't exist."); @@ -318,7 +319,7 @@ public virtual WeightedEdge GetEdge(T source, T destination) /// /// Returns the edge weight from source to destination. /// - public virtual long GetEdgeWeight(T source, T destination) + public virtual W GetEdgeWeight(T source, T destination) { return GetEdge(source, destination).Weight; } @@ -346,7 +347,7 @@ public virtual bool AddVertex(T vertex) if (_adjacencyList.Count == 0) _firstInsertedNode = vertex; - _adjacencyList.Add(vertex, new DLinkedList>()); + _adjacencyList.Add(vertex, new DLinkedList>()); return true; } @@ -414,13 +415,13 @@ public virtual DLinkedList Neighbours(T vertex) /// /// Returns the neighbours of a vertex as a dictionary of nodes-to-weights. /// - public Dictionary NeighboursMap(T vertex) + public Dictionary NeighboursMap(T vertex) { if (!HasVertex(vertex)) return null; var neighbors = _adjacencyList[vertex]; - var map = new Dictionary(neighbors.Count); + var map = new Dictionary(neighbors.Count); foreach (var adjacent in neighbors) map.Add(adjacent.Destination, adjacent.Weight); @@ -567,5 +568,21 @@ public virtual void Clear() _adjacencyList.Clear(); } } + + public class UndirectedWeightedSparseGraph : UndirectedWeightedSparseGraph, IGraph, IWeightedGraph where T : IComparable + { + public new IEnumerable> Edges => base.Edges.Select(edge => edge.ToSimpleEdge()); + + public new WeightedEdge GetEdge(T source, T destination) => base.GetEdge(source, destination).ToSimpleEdge(); + + public new IEnumerable> IncomingEdges(T vertex) => base.IncomingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + + public new IEnumerable> OutgoingEdges(T vertex) => base.OutgoingEdges(vertex).Select(edge => edge.ToSimpleEdge()); + IEnumerable> IGraph.Edges => this.Edges; + + IEnumerable> IGraph.IncomingEdges(T vertex) => this.IncomingEdges(vertex); + + IEnumerable> IGraph.OutgoingEdges(T vertex) => this.OutgoingEdges(vertex); + } } diff --git a/DataStructures/Graphs/UnweightedEdge.cs b/DataStructures/Graphs/UnweightedEdge.cs index 8bffc61f..65e1188e 100644 --- a/DataStructures/Graphs/UnweightedEdge.cs +++ b/DataStructures/Graphs/UnweightedEdge.cs @@ -9,8 +9,6 @@ namespace DataStructures.Graphs /// public class UnweightedEdge : IEdge where TVertex : IComparable { - private const int _edgeWeight = 0; - /// /// Gets or sets the source vertex. /// @@ -23,16 +21,6 @@ public class UnweightedEdge : IEdge where TVertex : IComparabl /// The destination. public TVertex Destination { get; set; } - /// - /// [PRIVATE MEMBER] Gets or sets the weight. - /// - /// The weight. - public Int64 Weight - { - get { throw new NotImplementedException("Unweighted edges don't have weights."); } - set { throw new NotImplementedException("Unweighted edges can't have weights."); } - } - /// /// Gets a value indicating whether this edge is weighted. /// @@ -55,7 +43,7 @@ public UnweightedEdge(TVertex src, TVertex dst) #region IComparable implementation public int CompareTo(IEdge other) { - if (other == null) + if (other == null || !(other is UnweightedEdge)) return -1; bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); diff --git a/DataStructures/Graphs/WeightedEdge.cs b/DataStructures/Graphs/WeightedEdge.cs index f073d50e..de45b9ee 100644 --- a/DataStructures/Graphs/WeightedEdge.cs +++ b/DataStructures/Graphs/WeightedEdge.cs @@ -7,7 +7,9 @@ namespace DataStructures.Graphs /// /// The graph weighted edge class. /// - public class WeightedEdge : IEdge where TVertex : IComparable + public class WeightedEdge : IEdge + where TVertex : IComparable + where TWeight : IComparable { /// /// Gets or sets the source. @@ -25,7 +27,7 @@ public class WeightedEdge : IEdge where TVertex : IComparable< /// Gets or sets the weight of edge. /// /// The weight. - public Int64 Weight { get; set; } + public TWeight Weight { get; set; } /// /// Gets a value indicating whether this edge is weighted. @@ -38,7 +40,7 @@ public bool IsWeighted /// /// CONSTRUCTOR /// - public WeightedEdge(TVertex src, TVertex dst, Int64 weight) + public WeightedEdge(TVertex src, TVertex dst, TWeight weight) { Source = src; Destination = dst; @@ -49,15 +51,37 @@ public WeightedEdge(TVertex src, TVertex dst, Int64 weight) #region IComparable implementation public int CompareTo(IEdge other) { - if (other == null) + if (other == null || !(other is WeightedEdge)) return -1; - + bool areNodesEqual = Source.IsEqualTo(other.Source) && Destination.IsEqualTo(other.Destination); if (!areNodesEqual) return -1; - return Weight.CompareTo(other.Weight); + + var o = other as WeightedEdge; + return Weight.CompareTo(o.Weight); } #endregion } + + public class WeightedEdge : WeightedEdge, IEdge where TVertex : IComparable + { + public WeightedEdge(TVertex src, TVertex dst, long weight) : base(src, dst, weight) + { + } + + public WeightedEdge(WeightedEdge edge) : base(edge.Source, edge.Destination, edge.Weight) + { + } + } + + public static class WeightedEdgeExtension + { + public static WeightedEdge ToSimpleEdge(this WeightedEdge edge) + where TVertex : IComparable + { + return new WeightedEdge(edge.Source, edge.Destination, edge.Weight); + } + } }