diff --git a/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstBidirectionalTopologicalSortAlgorithm.cs b/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstBidirectionalTopologicalSortAlgorithm.cs index a021da400..adbdf3a1f 100644 --- a/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstBidirectionalTopologicalSortAlgorithm.cs +++ b/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstBidirectionalTopologicalSortAlgorithm.cs @@ -2,6 +2,8 @@ using System; #endif using System.Collections.Generic; +using JetBrains.Annotations; +using QuikGraph.Algorithms.Services; #if SUPPORTS_CONTRACTS using System.Diagnostics.Contracts; #endif @@ -9,12 +11,11 @@ namespace QuikGraph.Algorithms.TopologicalSort { - public enum TopologicalSortDirection - { - Forward, - Backward - } - + /// + /// Topological sort algorithm (can be performed on an acyclic bidirectional graph). + /// + /// Vertex type. + /// Edge type. #if SUPPORTS_SERIALIZATION [Serializable] #endif @@ -22,124 +23,152 @@ public sealed class SourceFirstBidirectionalTopologicalSortAlgorithm> where TEdge : IEdge { - private IDictionary predCounts = new Dictionary(); - private BinaryQueue heap; - private IList sortedVertices = new List(); - private TopologicalSortDirection direction = TopologicalSortDirection.Forward; + [NotNull] + private readonly BinaryQueue _heap; + private readonly TopologicalSortDirection _direction; + + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. public SourceFirstBidirectionalTopologicalSortAlgorithm( - IBidirectionalGraph visitedGraph - ) + [NotNull] IBidirectionalGraph visitedGraph) : this(visitedGraph, TopologicalSortDirection.Forward) { } + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + /// Sort direction. public SourceFirstBidirectionalTopologicalSortAlgorithm( - IBidirectionalGraph visitedGraph, - TopologicalSortDirection direction - ) + [NotNull] IBidirectionalGraph visitedGraph, + TopologicalSortDirection direction) : base(visitedGraph) { - this.direction = direction; - this.heap = new BinaryQueue(e => this.predCounts[e]); + _direction = direction; + _heap = new BinaryQueue(vertex => InDegrees[vertex]); } - public ICollection SortedVertices + /// + /// Sorted vertices. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull, ItemNotNull] + public ICollection SortedVertices { get; private set; } = new List(); + + /// + /// Vertices in degrees. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull] + public IDictionary InDegrees { get; } = new Dictionary(); + + /// + /// Fired when a vertex is added to the set of sorted vertices. + /// + public event VertexAction VertexAdded; + + private void OnVertexAdded([NotNull] TVertex vertex) { - get - { - return this.sortedVertices; - } +#if SUPPORTS_CONTRACTS + Contract.Requires(vertex != null); +#endif + + VertexAdded?.Invoke(vertex); } - public BinaryQueue Heap + private void InitializeInDegrees() { - get + foreach (TVertex vertex in VisitedGraph.Vertices) { - return this.heap; + InDegrees.Add(vertex, 0); } - } - public IDictionary InDegrees - { - get + foreach (TEdge edge in VisitedGraph.Edges) { - return this.predCounts; + if (edge.IsSelfEdge()) + continue; + + TVertex successor = _direction == TopologicalSortDirection.Forward + ? edge.Target + : edge.Source; + + ++InDegrees[successor]; } - } - public event VertexAction AddVertex; - private void OnAddVertex(TVertex v) - { - var eh = this.AddVertex; - if (eh != null) - eh(v); + foreach (TVertex vertex in VisitedGraph.Vertices) + { + _heap.Enqueue(vertex); + } } - public void Compute(IList vertices) + /// + /// Runs the topological sort and puts the result in the provided list. + /// + /// Set of sorted vertices. + public void Compute([NotNull, ItemNotNull] IList vertices) { #if SUPPORTS_CONTRACTS Contract.Requires(vertices != null); #endif - this.sortedVertices = vertices; + SortedVertices = vertices; + SortedVertices.Clear(); Compute(); } + #region AlgorithmBase + /// protected override void InternalCompute() { - var cancelManager = this.Services.CancelManager; - this.InitializeInDegrees(); + ICancelManager cancelManager = Services.CancelManager; + InitializeInDegrees(); - while (this.heap.Count != 0) + while (_heap.Count != 0) { - if (cancelManager.IsCancelling) break; + if (cancelManager.IsCancelling) + break; - TVertex v = this.heap.Dequeue(); - if (this.predCounts[v] != 0) + TVertex vertex = _heap.Dequeue(); + if (InDegrees[vertex] != 0) throw new NonAcyclicGraphException(); - this.sortedVertices.Add(v); - this.OnAddVertex(v); + SortedVertices.Add(vertex); + OnVertexAdded(vertex); - // update the count of its successor vertices - var succEdges = (this.direction == TopologicalSortDirection.Forward) ? this.VisitedGraph.OutEdges(v) : this.VisitedGraph.InEdges(v); - foreach (var e in succEdges) + // Update the count of its successor vertices + IEnumerable successorEdges = _direction == TopologicalSortDirection.Forward + ? VisitedGraph.OutEdges(vertex) + : VisitedGraph.InEdges(vertex); + + foreach (TEdge edge in successorEdges) { - if (e.Source.Equals(e.Target)) + if (edge.IsSelfEdge()) continue; - var succ = (direction == TopologicalSortDirection.Forward) ? e.Target : e.Source; - this.predCounts[succ]--; + + TVertex successor = _direction == TopologicalSortDirection.Forward + ? edge.Target + : edge.Source; + + --InDegrees[successor]; #if SUPPORTS_CONTRACTS - Contract.Assert(this.predCounts[succ] >= 0); + Contract.Assert(InDegrees[successor] >= 0); #endif - this.heap.Update(succ); + _heap.Update(successor); } } } - private void InitializeInDegrees() - { - foreach (var v in this.VisitedGraph.Vertices) - { - this.predCounts.Add(v, 0); - } - - foreach (var e in this.VisitedGraph.Edges) - { - if (e.Source.Equals(e.Target)) - continue; - var succ = (direction == TopologicalSortDirection.Forward) ? e.Target : e.Source; - this.predCounts[succ]++; - } - - foreach (var v in this.VisitedGraph.Vertices) - { - this.heap.Enqueue(v); - } - } + #endregion } } diff --git a/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstTopologicalSortAlgorithm.cs b/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstTopologicalSortAlgorithm.cs index 75af5bb5a..8fa12b79c 100644 --- a/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstTopologicalSortAlgorithm.cs +++ b/src/QuikGraph/Algorithms/TopologicalSort/SourceFirstTopologicalSortAlgorithm.cs @@ -2,127 +2,145 @@ using System; #endif using System.Collections.Generic; +using JetBrains.Annotations; +using QuikGraph.Algorithms.Services; +using QuikGraph.Collections; #if SUPPORTS_CONTRACTS using System.Diagnostics.Contracts; #endif -using QuikGraph.Collections; namespace QuikGraph.Algorithms.TopologicalSort { + /// + /// Topological sort algorithm (can be performed on an acyclic graph). + /// + /// Vertex type. + /// Edge type. #if SUPPORTS_SERIALIZATION [Serializable] #endif - public sealed class SourceFirstTopologicalSortAlgorithm : - AlgorithmBase> + public sealed class SourceFirstTopologicalSortAlgorithm : AlgorithmBase> where TEdge : IEdge { - private IDictionary inDegrees = new Dictionary(); - private BinaryQueue heap; - private IList sortedVertices = new List(); + [NotNull] + private readonly BinaryQueue _heap; + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. public SourceFirstTopologicalSortAlgorithm( - IVertexAndEdgeListGraph visitedGraph - ) - :base(visitedGraph) + [NotNull] IVertexAndEdgeListGraph visitedGraph) + : base(visitedGraph) { - this.heap = new BinaryQueue(e => this.inDegrees[e]); + _heap = new BinaryQueue(vertex => InDegrees[vertex]); } - public ICollection SortedVertices + /// + /// Sorted vertices. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull, ItemNotNull] + public ICollection SortedVertices { get; private set; } = new List(); + + /// + /// Vertices in degrees. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull] + public IDictionary InDegrees { get; } = new Dictionary(); + + /// + /// Fired when a vertex is added to the set of sorted vertices. + /// + public event VertexAction VertexAdded; + + private void OnVertexAdded([NotNull] TVertex vertex) { - get - { - return this.sortedVertices; - } +#if SUPPORTS_CONTRACTS + Contract.Requires(vertex != null); +#endif + + VertexAdded?.Invoke(vertex); } - public BinaryQueue Heap + private void InitializeInDegrees() { - get + foreach (TVertex vertex in VisitedGraph.Vertices) { - return this.heap; + InDegrees.Add(vertex, 0); } - } - public IDictionary InDegrees - { - get + foreach (TEdge edge in VisitedGraph.Edges) { - return this.inDegrees; + if (edge.IsSelfEdge()) + continue; + + ++InDegrees[edge.Target]; } - } - public event VertexAction AddVertex; - private void OnAddVertex(TVertex v) - { - var eh = this.AddVertex; - if (eh != null) - eh(v); + foreach (TVertex vertex in VisitedGraph.Vertices) + { + _heap.Enqueue(vertex); + } } - public void Compute(IList vertices) + /// + /// Runs the topological sort and puts the result in the provided list. + /// + /// Set of sorted vertices. + public void Compute([NotNull, ItemNotNull] IList vertices) { #if SUPPORTS_CONTRACTS Contract.Requires(vertices != null); #endif - this.sortedVertices = vertices; + SortedVertices = vertices; + SortedVertices.Clear(); Compute(); } + #region AlgorithmBase + /// protected override void InternalCompute() { - var cancelManager = this.Services.CancelManager; - this.InitializeInDegrees(); + ICancelManager cancelManager = Services.CancelManager; + InitializeInDegrees(); - while (this.heap.Count != 0) + while (_heap.Count != 0) { - if (cancelManager.IsCancelling) break; + if (cancelManager.IsCancelling) + break; - TVertex v = this.heap.Dequeue(); - if (this.inDegrees[v] != 0) + TVertex vertex = _heap.Dequeue(); + if (InDegrees[vertex] != 0) throw new NonAcyclicGraphException(); - this.sortedVertices.Add(v); - this.OnAddVertex(v); + SortedVertices.Add(vertex); + OnVertexAdded(vertex); - // update the count of it's adjacent vertices - foreach (var e in this.VisitedGraph.OutEdges(v)) + // Update the count of its adjacent vertices + foreach (TEdge edge in VisitedGraph.OutEdges(vertex)) { - if (e.Source.Equals(e.Target)) + if (edge.IsSelfEdge()) continue; - this.inDegrees[e.Target]--; + --InDegrees[edge.Target]; #if SUPPORTS_CONTRACTS - Contract.Assert(this.inDegrees[e.Target] >= 0); + Contract.Assert(InDegrees[edge.Target] >= 0); #endif - this.heap.Update(e.Target); + _heap.Update(edge.Target); } } } - private void InitializeInDegrees() - { - foreach (var v in this.VisitedGraph.Vertices) - { - this.inDegrees.Add(v, 0); - } - - foreach (var e in this.VisitedGraph.Edges) - { - if (e.Source.Equals(e.Target)) - continue; - this.inDegrees[e.Target]++; - } - - foreach (var v in this.VisitedGraph.Vertices) - { - this.heap.Enqueue(v); - } - - } + #endregion } } diff --git a/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortAlgorithm.cs b/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortAlgorithm.cs index 29509ced7..be201f2d6 100644 --- a/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortAlgorithm.cs +++ b/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortAlgorithm.cs @@ -2,6 +2,7 @@ using System; #endif using System.Collections.Generic; +using JetBrains.Annotations; #if SUPPORTS_CONTRACTS using System.Diagnostics.Contracts; #endif @@ -9,60 +10,82 @@ namespace QuikGraph.Algorithms.TopologicalSort { + /// + /// Topological sort algorithm (can be performed on an acyclic graph). + /// + /// Vertex type. + /// Edge type. #if SUPPORTS_SERIALIZATION [Serializable] #endif - public sealed class TopologicalSortAlgorithm : - AlgorithmBase> + public sealed class TopologicalSortAlgorithm + : AlgorithmBase> + , IVertexTimeStamperAlgorithm where TEdge : IEdge { - private IList vertices = new List(); - private bool allowCyclicGraph = false; - - public TopologicalSortAlgorithm(IVertexListGraph g) - : this(g, new List()) - { } + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + public TopologicalSortAlgorithm([NotNull] IVertexListGraph visitedGraph) + : this(visitedGraph, new List()) + { + } + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + /// Set of sorted vertices. public TopologicalSortAlgorithm( - IVertexListGraph g, - IList vertices) - : base(g) + [NotNull] IVertexListGraph visitedGraph, + [NotNull, ItemNotNull] IList vertices) + : base(visitedGraph) { #if SUPPORTS_CONTRACTS Contract.Requires(vertices != null); #endif - this.vertices = vertices; + SortedVertices = vertices; } + /// + /// Sorted vertices. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull, ItemNotNull] + public IList SortedVertices { get; private set; } - public IList SortedVertices + private static void OnBackEdge([NotNull] TEdge args) { - get - { - return vertices; - } + throw new NonAcyclicGraphException(); } - public bool AllowCyclicGraph + private void OnVertexFinished([NotNull] TVertex vertex) { - get { return this.allowCyclicGraph; } + SortedVertices.Insert(0, vertex); } - private void BackEdge(TEdge args) + /// + /// Runs the topological sort and puts the result in the provided list. + /// + /// Set of sorted vertices. + public void Compute([NotNull, ItemNotNull] IList vertices) { - if (!this.AllowCyclicGraph) - throw new NonAcyclicGraphException(); - } +#if SUPPORTS_CONTRACTS + Contract.Requires(vertices != null); +#endif - private void VertexFinished(TVertex v) - { - vertices.Insert(0, v); + SortedVertices = vertices; + SortedVertices.Clear(); + Compute(); } - public event VertexAction DiscoverVertex; - public event VertexAction FinishVertex; + #region AlgorithmBase + /// protected override void InternalCompute() { DepthFirstSearchAlgorithm dfs = null; @@ -70,11 +93,10 @@ protected override void InternalCompute() { dfs = new DepthFirstSearchAlgorithm( this, - this.VisitedGraph, - new Dictionary(this.VisitedGraph.VertexCount) - ); - dfs.BackEdge += BackEdge; - dfs.FinishVertex += VertexFinished; + VisitedGraph, + new Dictionary(VisitedGraph.VertexCount)); + dfs.BackEdge += OnBackEdge; + dfs.FinishVertex += OnVertexFinished; dfs.DiscoverVertex += DiscoverVertex; dfs.FinishVertex += FinishVertex; @@ -84,19 +106,24 @@ protected override void InternalCompute() { if (dfs != null) { - dfs.BackEdge -= BackEdge; - dfs.FinishVertex -= VertexFinished; + dfs.BackEdge -= OnBackEdge; + dfs.FinishVertex -= OnVertexFinished; dfs.DiscoverVertex -= DiscoverVertex; dfs.FinishVertex -= FinishVertex; } } } - public void Compute(IList vertices) - { - this.vertices = vertices; - this.vertices.Clear(); - this.Compute(); - } + #endregion + + #region IVertexTimeStamperAlgorithm + + /// + public event VertexAction DiscoverVertex; + + /// + public event VertexAction FinishVertex; + + #endregion } } \ No newline at end of file diff --git a/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortDirection.cs b/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortDirection.cs new file mode 100644 index 000000000..0b3f51e46 --- /dev/null +++ b/src/QuikGraph/Algorithms/TopologicalSort/TopologicalSortDirection.cs @@ -0,0 +1,18 @@ +namespace QuikGraph.Algorithms.TopologicalSort +{ + /// + /// Enumeration of possible topological sort directions. + /// + public enum TopologicalSortDirection + { + /// + /// Forward sort. + /// + Forward, + + /// + /// Backward sort. + /// + Backward + } +} diff --git a/src/QuikGraph/Algorithms/TopologicalSort/UndirectedFirstTopologicalSortAlgorithm.cs b/src/QuikGraph/Algorithms/TopologicalSort/UndirectedFirstTopologicalSortAlgorithm.cs index 7df3e3889..9487150a2 100644 --- a/src/QuikGraph/Algorithms/TopologicalSort/UndirectedFirstTopologicalSortAlgorithm.cs +++ b/src/QuikGraph/Algorithms/TopologicalSort/UndirectedFirstTopologicalSortAlgorithm.cs @@ -3,118 +3,134 @@ #if SUPPORTS_CONTRACTS using System.Diagnostics.Contracts; #endif +using JetBrains.Annotations; +using QuikGraph.Algorithms.Services; using QuikGraph.Collections; namespace QuikGraph.Algorithms.TopologicalSort { + /// + /// Undirected topological sort algorithm. + /// + /// Vertex type. + /// Edge type. #if SUPPORTS_SERIALIZATION [Serializable] #endif - public sealed class UndirectedFirstTopologicalSortAlgorithm : - AlgorithmBase> + public sealed class UndirectedFirstTopologicalSortAlgorithm : AlgorithmBase> where TEdge : IEdge { - private IDictionary degrees = new Dictionary(); - private BinaryQueue heap; - private IList sortedVertices = new List(); - private bool allowCyclicGraph = false; - - public UndirectedFirstTopologicalSortAlgorithm( - IUndirectedGraph visitedGraph - ) + [NotNull] + private readonly BinaryQueue _heap; + + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + public UndirectedFirstTopologicalSortAlgorithm([NotNull] IUndirectedGraph visitedGraph) : base(visitedGraph) { - this.heap = new BinaryQueue(e => this.degrees[e]); + _heap = new BinaryQueue(vertex => Degrees[vertex]); } - public ICollection SortedVertices - { - get - { - return this.sortedVertices; - } - } + /// + /// Sorted vertices. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull, ItemNotNull] + public ICollection SortedVertices { get; private set; } = new List(); - public BinaryQueue Heap - { - get - { - return this.heap; - } - } + /// + /// Vertices degrees. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull] + public IDictionary Degrees { get; } = new Dictionary(); - public IDictionary Degrees - { - get - { - return this.degrees; - } - } + /// + /// Gets or sets the flag that indicates if cyclic graph are supported or not. + /// + public bool AllowCyclicGraph { get; set; } + /// + /// Fired when a vertex is added to the set of sorted vertices. + /// + public event VertexAction VertexAdded; - public bool AllowCyclicGraph + private void OnVertexAdded([NotNull] TVertex vertex) { - get { return this.allowCyclicGraph; } - set { this.allowCyclicGraph = value; } +#if SUPPORTS_CONTRACTS + Contract.Requires(vertex != null); +#endif + + VertexAdded?.Invoke(vertex); } - public event VertexAction AddVertex; - private void OnAddVertex(TVertex v) + private void InitializeInDegrees() { - var eh = AddVertex; - if (eh != null) - eh(v); + foreach (TVertex vertex in VisitedGraph.Vertices) + { + Degrees.Add(vertex, VisitedGraph.AdjacentDegree(vertex)); + _heap.Enqueue(vertex); + } } - public void Compute(IList vertices) + /// + /// Runs the topological sort and puts the result in the provided list. + /// + /// Set of sorted vertices. + public void Compute([NotNull, ItemNotNull] IList vertices) { #if SUPPORTS_CONTRACTS Contract.Requires(vertices != null); #endif - this.sortedVertices = vertices; + SortedVertices = vertices; + SortedVertices.Clear(); Compute(); } + #region AlgorithmBase + /// protected override void InternalCompute() { - this.InitializeInDegrees(); - var cancelManager = this.Services.CancelManager; + ICancelManager cancelManager = Services.CancelManager; + InitializeInDegrees(); - while (this.heap.Count != 0) + while (_heap.Count != 0) { - if (cancelManager.IsCancelling) return; + if (cancelManager.IsCancelling) + return; - TVertex v = this.heap.Dequeue(); - if (this.degrees[v] != 0 && !this.AllowCyclicGraph) + TVertex vertex = _heap.Dequeue(); + if (Degrees[vertex] != 0 && !AllowCyclicGraph) throw new NonAcyclicGraphException(); - this.sortedVertices.Add(v); - this.OnAddVertex(v); + SortedVertices.Add(vertex); + OnVertexAdded(vertex); - // update the count of it's adjacent vertices - foreach (var e in this.VisitedGraph.AdjacentEdges(v)) + // Update the count of its adjacent vertices + foreach (TEdge edge in VisitedGraph.AdjacentEdges(vertex)) { - if (e.Source.Equals(e.Target)) + if (edge.IsSelfEdge()) continue; - this.degrees[e.Target]--; - if (this.degrees[e.Target] < 0 && !this.AllowCyclicGraph) - throw new InvalidOperationException("Degree is negative, and cannot be"); - if (this.heap.Contains(e.Target)) - this.heap.Update(e.Target); + --Degrees[edge.Target]; + + if (Degrees[edge.Target] < 0 && !AllowCyclicGraph) + throw new InvalidOperationException("Degree is negative, and cannot be."); + + if (_heap.Contains(edge.Target)) + _heap.Update(edge.Target); } } } - private void InitializeInDegrees() - { - foreach (var v in this.VisitedGraph.Vertices) - { - this.degrees.Add(v, this.VisitedGraph.AdjacentDegree(v)); - this.heap.Enqueue(v); - } - } + #endregion } } diff --git a/src/QuikGraph/Algorithms/TopologicalSort/UndirectedTopologicalSortAlgorithm.cs b/src/QuikGraph/Algorithms/TopologicalSort/UndirectedTopologicalSortAlgorithm.cs index c4bc79364..dc28878a8 100644 --- a/src/QuikGraph/Algorithms/TopologicalSort/UndirectedTopologicalSortAlgorithm.cs +++ b/src/QuikGraph/Algorithms/TopologicalSort/UndirectedTopologicalSortAlgorithm.cs @@ -3,61 +3,91 @@ #if SUPPORTS_CONTRACTS using System.Diagnostics.Contracts; #endif +using JetBrains.Annotations; using QuikGraph.Algorithms.Search; namespace QuikGraph.Algorithms.TopologicalSort { + /// + /// Undirected topological sort algorithm. + /// + /// Vertex type. + /// Edge type. #if SUPPORTS_SERIALIZATION [Serializable] #endif - public sealed class UndirectedTopologicalSortAlgorithm - : AlgorithmBase> + public sealed class UndirectedTopologicalSortAlgorithm : AlgorithmBase> where TEdge : IEdge { - private IList vertices; - private bool allowCyclicGraph = false; - - public UndirectedTopologicalSortAlgorithm(IUndirectedGraph g) - : this(g, new List()) - { } + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + public UndirectedTopologicalSortAlgorithm([NotNull] IUndirectedGraph visitedGraph) + : this(visitedGraph, new List()) + { + } + /// + /// Initializes a new instance of the class. + /// + /// Graph to visit. + /// Set of sorted vertices. public UndirectedTopologicalSortAlgorithm( - IUndirectedGraph g, - IList vertices) - : base(g) + [NotNull] IUndirectedGraph visitedGraph, + [NotNull, ItemNotNull] IList vertices) + : base(visitedGraph) { #if SUPPORTS_CONTRACTS Contract.Requires(vertices != null); #endif - this.vertices = vertices; + SortedVertices = vertices; } - public IList SortedVertices - { - get - { - return vertices; - } - } + /// + /// Sorted vertices. + /// +#if SUPPORTS_CONTRACTS + [System.Diagnostics.Contracts.Pure] +#endif + [NotNull, ItemNotNull] + public IList SortedVertices { get; private set; } + + /// + /// Gets or sets the flag that indicates if cyclic graph are supported or not. + /// + public bool AllowCyclicGraph { get; set; } - public bool AllowCyclicGraph + private void BackEdge([NotNull] object sender, [NotNull] UndirectedEdgeEventArgs args) { - get { return this.allowCyclicGraph; } - set { this.allowCyclicGraph = value; } + if (!AllowCyclicGraph) + throw new NonAcyclicGraphException(); } - private void BackEdge(object sender, UndirectedEdgeEventArgs a) + private void OnVertexFinished([NotNull] TVertex vertex) { - if (!this.AllowCyclicGraph) - throw new NonAcyclicGraphException(); + SortedVertices.Insert(0, vertex); } - private void FinishVertex(TVertex v) + /// + /// Runs the topological sort and puts the result in the provided list. + /// + /// Set of sorted vertices. + public void Compute([NotNull, ItemNotNull] IList vertices) { - vertices.Insert(0, v); +#if SUPPORTS_CONTRACTS + Contract.Requires(vertices != null); +#endif + + SortedVertices = vertices; + SortedVertices.Clear(); + Compute(); } + #region AlgorithmBase + + /// protected override void InternalCompute() { UndirectedDepthFirstSearchAlgorithm dfs = null; @@ -66,10 +96,9 @@ protected override void InternalCompute() dfs = new UndirectedDepthFirstSearchAlgorithm( this, VisitedGraph, - new Dictionary(this.VisitedGraph.VertexCount) - ); + new Dictionary(VisitedGraph.VertexCount)); dfs.BackEdge += BackEdge; - dfs.FinishVertex += FinishVertex; + dfs.FinishVertex += OnVertexFinished; dfs.Compute(); } @@ -78,16 +107,11 @@ protected override void InternalCompute() if (dfs != null) { dfs.BackEdge -= BackEdge; - dfs.FinishVertex -= FinishVertex; + dfs.FinishVertex -= OnVertexFinished; } } } - public void Compute(IList vertices) - { - this.vertices = vertices; - this.vertices.Clear(); - this.Compute(); - } + #endregion } } diff --git a/tests/QuikGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs b/tests/QuikGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs index 09c060dc7..481fe531d 100644 --- a/tests/QuikGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs +++ b/tests/QuikGraph.Tests/Algorithms/TopologicalSortAlgorithmTest.cs @@ -28,10 +28,9 @@ public void SortCyclic( [Test] public void SortDCT8() { - var g = TestGraphFactory.LoadGraph(GetGraphFilePath("DCT8.graphml")); - var topo = new TopologicalSortAlgorithm>(g); - Assert.IsFalse(topo.AllowCyclicGraph); - topo.Compute(); + var graph = TestGraphFactory.LoadGraph(GetGraphFilePath("DCT8.graphml")); + var topologicalSort = new TopologicalSortAlgorithm>(graph); + topologicalSort.Compute(); } [Test]