diff --git a/src/QuikGraph/Algorithms/ShortestPath/YenShortestPathsAlgorithm.cs b/src/QuikGraph/Algorithms/ShortestPath/YenShortestPathsAlgorithm.cs
index b2c30b51f..dbff2129f 100644
--- a/src/QuikGraph/Algorithms/ShortestPath/YenShortestPathsAlgorithm.cs
+++ b/src/QuikGraph/Algorithms/ShortestPath/YenShortestPathsAlgorithm.cs
@@ -14,20 +14,21 @@ namespace QuikGraph.Algorithms.ShortestPath
/// with non negative edge cost.
///
/// Vertex type.
- public class YenShortestPathsAlgorithm
+ /// Edge type.
+ public class YenShortestPathsAlgorithm where TEdge : IEdge
{
///
/// Class representing a sorted path.
///
- public struct SortedPath : IEnumerable>, IEquatable
+ public struct SortedPath : IEnumerable, IEquatable
{
[NotNull, ItemNotNull]
- private readonly List> _edges;
+ private readonly List _edges;
///
/// Initializes a new instance of the struct.
///
- public SortedPath([NotNull, ItemNotNull] IEnumerable> edges)
+ public SortedPath([NotNull, ItemNotNull] IEnumerable edges)
{
_edges = edges.ToList();
}
@@ -48,7 +49,7 @@ internal TVertex GetVertex(int i)
[Pure]
[NotNull]
- internal EquatableTaggedEdge GetEdge(int i)
+ internal TEdge GetEdge(int i)
{
Debug.Assert(i >= 0 && i < _edges.Count);
@@ -57,7 +58,7 @@ internal EquatableTaggedEdge GetEdge(int i)
[Pure]
[NotNull, ItemNotNull]
- internal EquatableTaggedEdge[] GetEdges(int count)
+ internal TEdge[] GetEdges(int count)
{
if (count > _edges.Count)
{
@@ -88,7 +89,7 @@ public override int GetHashCode()
}
///
- public IEnumerator> GetEnumerator()
+ public IEnumerator GetEnumerator()
{
return _edges.GetEnumerator();
}
@@ -104,7 +105,7 @@ IEnumerator IEnumerable.GetEnumerator()
private readonly TVertex _targetVertex;
[NotNull]
- private readonly Func, double> _weights;
+ private readonly Func _weights;
[NotNull]
private readonly Func, IEnumerable> _filter;
@@ -113,10 +114,10 @@ IEnumerator IEnumerable.GetEnumerator()
private readonly int _k;
[NotNull]
- private readonly IMutableVertexAndEdgeListGraph> _graph;
+ private readonly IMutableVertexAndEdgeListGraph _graph;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// for tag type (edge) which comes from Dijkstra’s algorithm, which is used to get one shortest path.
@@ -134,11 +135,11 @@ IEnumerator IEnumerable.GetEnumerator()
/// is not part of .
/// is lower than 1.
public YenShortestPathsAlgorithm(
- [NotNull] AdjacencyGraph> graph,
+ [NotNull] AdjacencyGraph graph,
[NotNull] TVertex source,
[NotNull] TVertex target,
int k,
- [CanBeNull] Func, double> edgeWeights = null,
+ [CanBeNull] Func edgeWeights,
[CanBeNull] Func, IEnumerable> filter = null)
{
if (graph is null)
@@ -153,12 +154,14 @@ public YenShortestPathsAlgorithm(
throw new ArgumentException("Target must be in the graph", nameof(source));
if (k < 1)
throw new ArgumentOutOfRangeException(nameof(k), "Value must be positive.");
+ if (edgeWeights == null)
+ throw new ArgumentNullException(nameof(edgeWeights));
_sourceVertex = source;
_targetVertex = target;
_k = k;
_graph = graph.Clone();
- _weights = edgeWeights ?? DefaultGetWeights;
+ _weights = edgeWeights;
_filter = filter ?? DefaultFilter;
}
@@ -169,12 +172,6 @@ private static IEnumerable DefaultFilter([NotNull] IEnumerable edge)
- {
- return edge.Tag;
- }
-
[Pure]
private double GetPathDistance([ItemNotNull] SortedPath edges)
{
@@ -196,7 +193,7 @@ private SortedPath GetInitialShortestPath()
[Pure]
[CanBeNull]
private SortedPath? GetShortestPathInGraph(
- [NotNull] IVertexListGraph> graph,
+ [NotNull] IVertexListGraph graph,
[NotNull] TVertex source,
[NotNull] TVertex target)
{
@@ -205,8 +202,8 @@ private SortedPath GetInitialShortestPath()
Debug.Assert(target != null);
// Compute distances between the start vertex and other
- var algorithm = new DijkstraShortestPathAlgorithm>(graph, _weights);
- var recorder = new VertexPredecessorRecorderObserver>();
+ var algorithm = new DijkstraShortestPathAlgorithm(graph, _weights);
+ var recorder = new VertexPredecessorRecorderObserver();
using (recorder.Attach(algorithm))
{
@@ -214,7 +211,7 @@ private SortedPath GetInitialShortestPath()
}
// Get shortest path from start (source) vertex to target
- return recorder.TryGetPath(target, out IEnumerable> path)
+ return recorder.TryGetPath(target, out IEnumerable path)
? new SortedPath(path)
: (SortedPath?)null;
}
@@ -258,12 +255,12 @@ private bool SearchAndAddKthShortestPath(
TVertex spurVertex = previousPath.GetVertex(i);
// The sequence of nodes from the source to the spur node of the previous k-shortest path
- EquatableTaggedEdge[] rootPath = previousPath.GetEdges(i);
+ TEdge[] rootPath = previousPath.GetEdges(i);
foreach (SortedPath path in shortestPaths.Where(path => rootPath.SequenceEqual(path.GetEdges(i))))
{
// Remove the links that are part of the previous shortest paths which share the same root path
- EquatableTaggedEdge edgeToRemove = path.GetEdge(i);
+ TEdge edgeToRemove = path.GetEdge(i);
_edgesToRestore.Add(edgeToRemove);
_graph.RemoveEdge(edgeToRemove);
}
@@ -343,10 +340,10 @@ public IEnumerable Execute()
}
[NotNull, ItemNotNull]
- private readonly List> _edgesToRestore =
- new List>();
+ private readonly List _edgesToRestore =
+ new List();
- private void OnGraphEdgeRemoved([NotNull] EquatableTaggedEdge edge)
+ private void OnGraphEdgeRemoved([NotNull] TEdge edge)
{
_edgesToRestore.Add(edge);
}
diff --git a/tests/QuikGraph.Tests/Algorithms/ShortestPath/YenShortestPathsAlgorithmTests.cs b/tests/QuikGraph.Tests/Algorithms/ShortestPath/YenShortestPathsAlgorithmTests.cs
index 895df5296..4c18f2731 100644
--- a/tests/QuikGraph.Tests/Algorithms/ShortestPath/YenShortestPathsAlgorithmTests.cs
+++ b/tests/QuikGraph.Tests/Algorithms/ShortestPath/YenShortestPathsAlgorithmTests.cs
@@ -6,7 +6,7 @@
namespace QuikGraph.Tests.Algorithms.ShortestPath
{
///
- /// Tests for .
+ /// Tests for .
///
[TestFixture]
internal sealed class YenShortestPathsAlgorithmTests
@@ -14,21 +14,23 @@ internal sealed class YenShortestPathsAlgorithmTests
[Test]
public void Constructor()
{
- Func, double> Weights = _ => 1.0;
+ Func, double> weights = edge => edge.Tag;
var graph = new AdjacencyGraph>();
graph.AddVertexRange(new[] { 1, 2 });
// ReSharper disable ObjectCreationAsStatement
- Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm(graph, 1, 2, int.MaxValue));
- Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm(graph, 1, 2, 10));
+ Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm>(graph, 1, 2, int.MaxValue, weights));
+ Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm>(graph, 1, 2, 10, weights));
- Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm(graph, 1, 2, int.MaxValue, Weights, paths => paths.Where(path => path.Count() > 2)));
+ Assert.DoesNotThrow(() => new YenShortestPathsAlgorithm>(graph, 1, 2, int.MaxValue, weights, paths => paths.Where(path => path.Count() > 2)));
// ReSharper restore ObjectCreationAsStatement
}
[Test]
public void Constructor_Throws()
{
+ Func, double> weights = edge => edge.Tag;
+
// ReSharper disable ObjectCreationAsStatement
// ReSharper disable AssignNullToNotNullAttribute
var vertex1 = new TestVertex("1");
@@ -36,41 +38,41 @@ public void Constructor_Throws()
var graph = new AdjacencyGraph>();
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, vertex2, int.MaxValue, weights));
graph = new AdjacencyGraph>();
graph.AddVertex(vertex1);
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, vertex2, int.MaxValue, weights));
graph = new AdjacencyGraph>();
graph.AddVertex(vertex2);
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, vertex2, int.MaxValue, weights));
graph = new AdjacencyGraph>();
graph.AddVertexRange(new[] { vertex1, vertex2 });
Assert.Throws(
- () => new YenShortestPathsAlgorithm(null, vertex1, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(null, vertex1, vertex2, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, null, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, null, vertex2, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, null, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, null, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(null, null, vertex2, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(null, null, vertex2, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(null, vertex1, null, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(null, vertex1, null, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, null, null, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(graph, null, null, int.MaxValue, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(null, null, null, int.MaxValue));
+ () => new YenShortestPathsAlgorithm>(null, null, null, int.MaxValue, weights));
// ReSharper restore AssignNullToNotNullAttribute
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, vertex2, 0));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, vertex2, 0, weights));
Assert.Throws(
- () => new YenShortestPathsAlgorithm(graph, vertex1, vertex2, -1));
+ () => new YenShortestPathsAlgorithm>(graph, vertex1, vertex2, -1, weights));
// ReSharper restore ObjectCreationAsStatement
}
@@ -85,11 +87,12 @@ public void SimpleNoPathGraph()
graph.AddVertex('1');
// ReSharper disable ReturnValueOfPureMethodIsNotUsed
- var algorithm = new YenShortestPathsAlgorithm(graph, '1', '1', 10);
+ Func, double> weights = edge => edge.Tag;
+ var algorithm = new YenShortestPathsAlgorithm>(graph, '1', '1', 10, weights);
Assert.Throws(() => algorithm.Execute());
graph.AddVertex('2');
- algorithm = new YenShortestPathsAlgorithm(graph, '1', '2', 10);
+ algorithm = new YenShortestPathsAlgorithm>(graph, '1', '2', 10, weights);
Assert.Throws(() => algorithm.Execute());
// ReSharper restore ReturnValueOfPureMethodIsNotUsed
}
@@ -104,7 +107,8 @@ public void LoopGraph()
var graph = new AdjacencyGraph>(true);
graph.AddVertexRange("1");
- var algorithm = new YenShortestPathsAlgorithm(graph, '1', '1', 10);
+ Func, double> weights = edge => edge.Tag;
+ var algorithm = new YenShortestPathsAlgorithm>(graph, '1', '1', 10, weights);
graph.AddEdge(new EquatableTaggedEdge('1', '1', 7));
// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
Assert.Throws(() => algorithm.Execute());
@@ -127,8 +131,9 @@ public void GraphWithCycle()
};
graph.AddEdgeRange(edges);
- var algorithm = new YenShortestPathsAlgorithm(graph, '1', '5', 10);
- YenShortestPathsAlgorithm.SortedPath[] paths = algorithm.Execute().ToArray();
+ Func, double> weights = edge => edge.Tag;
+ var algorithm = new YenShortestPathsAlgorithm>(graph, '1', '5', 10, weights);
+ YenShortestPathsAlgorithm>.SortedPath[] paths = algorithm.Execute().ToArray();
// Expecting to get 2 paths:
// 1 => 1-2-3-5
@@ -161,8 +166,9 @@ public void GraphWithMultiplePaths()
};
graph.AddEdgeRange(edges);
- var algorithm = new YenShortestPathsAlgorithm(graph, "A", "D", 5);
- YenShortestPathsAlgorithm.SortedPath[] paths = algorithm.Execute().ToArray();
+ Func, double> weights = edge => edge.Tag;
+ var algorithm = new YenShortestPathsAlgorithm>(graph, "A", "D", 5, weights);
+ YenShortestPathsAlgorithm>.SortedPath[] paths = algorithm.Execute().ToArray();
// Expecting to get 3 paths:
// 1 => A-B-D
@@ -205,8 +211,9 @@ public void GraphWithMultiplePaths_KShortest()
graph.AddEdgeRange(edges);
// K = 5
- var algorithmK5 = new YenShortestPathsAlgorithm(graph, 'C', 'H', 5);
- YenShortestPathsAlgorithm.SortedPath[] paths = algorithmK5.Execute().ToArray();
+ Func, double> weights = edge => edge.Tag;
+ var algorithmK5 = new YenShortestPathsAlgorithm>(graph, 'C', 'H', 5, weights);
+ YenShortestPathsAlgorithm>.SortedPath[] paths = algorithmK5.Execute().ToArray();
// Expecting to get 5 paths:
// 1 => C-E-F-H
@@ -220,7 +227,7 @@ public void GraphWithMultiplePaths_KShortest()
// K = 50
- var algorithmK50 = new YenShortestPathsAlgorithm(graph, 'C', 'H', 50);
+ var algorithmK50 = new YenShortestPathsAlgorithm>(graph, 'C', 'H', 50, weights);
paths = algorithmK50.Execute().ToArray();
// Expecting to get 7 paths:
@@ -250,7 +257,7 @@ public void GraphWithMultiplePaths_KShortest()
#region Local function
- void CheckFiveFirstPaths(YenShortestPathsAlgorithm.SortedPath[] ps)
+ void CheckFiveFirstPaths(YenShortestPathsAlgorithm>.SortedPath[] ps)
{
// 1
EquatableTaggedEdge[] path0 = ps[0].ToArray();
@@ -287,23 +294,16 @@ void CheckFiveFirstPaths(YenShortestPathsAlgorithm.SortedPath[] ps)
[Test]
public void MultipleRunMethods()
{
+ Func, double> weights = edge => edge.Tag;
AdjacencyGraph> graph = GenerateGraph(
out EquatableTaggedEdge[] graphEdges);
- // Default weight function and default filter function case
- var algorithm = new YenShortestPathsAlgorithm(graph, '1', '5', 10);
- RunYenAndCheck(algorithm);
-
- // Custom weight function and default filter function case
- algorithm = new YenShortestPathsAlgorithm(graph, '1', '5', 10, e => e.Tag);
- RunYenAndCheck(algorithm);
-
- // Default weight function and custom filter function case
- algorithm = new YenShortestPathsAlgorithm(graph, '1', '5', 10, null, e => e);
+ // Default filter function case
+ var algorithm = new YenShortestPathsAlgorithm>(graph, '1', '5', 10, weights);
RunYenAndCheck(algorithm);
- // Custom weight function and custom filter function case
- algorithm = new YenShortestPathsAlgorithm(graph, '1', '5', 10, e => e.Tag, e => e);
+ // Custom filter function case
+ algorithm = new YenShortestPathsAlgorithm>(graph, '1', '5', 10, weights, e => e);
RunYenAndCheck(algorithm);
#region Local functions
@@ -331,12 +331,12 @@ AdjacencyGraph> GenerateGraph(
return g;
}
- void RunYenAndCheck(YenShortestPathsAlgorithm yen)
+ void RunYenAndCheck(YenShortestPathsAlgorithm> yen)
{
// Generate simple graph
// like this https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
// but with directed edges input graph
- YenShortestPathsAlgorithm.SortedPath[] paths = yen.Execute().ToArray();
+ YenShortestPathsAlgorithm>.SortedPath[] paths = yen.Execute().ToArray();
// Expecting to get 3 paths:
// 1 => 1-3-4-5
@@ -374,10 +374,10 @@ public void SortedPathHashCode()
new EquatableTaggedEdge(2, 3, 1.0),
new EquatableTaggedEdge(3, 4, 1.0)
};
- var path1 = new YenShortestPathsAlgorithm.SortedPath(edges);
- var path2 = new YenShortestPathsAlgorithm.SortedPath(edges);
+ var path1 = new YenShortestPathsAlgorithm>.SortedPath(edges);
+ var path2 = new YenShortestPathsAlgorithm>.SortedPath(edges);
- var path3 = new YenShortestPathsAlgorithm.SortedPath(new[]
+ var path3 = new YenShortestPathsAlgorithm>.SortedPath(new[]
{
new EquatableTaggedEdge(1, 2, 1.0),
new EquatableTaggedEdge(2, 3, 1.0),
@@ -400,11 +400,11 @@ public void SortedPathEnumeration()
new EquatableTaggedEdge(3, 4, 1.0)
};
- var path = new YenShortestPathsAlgorithm.SortedPath(edges);
+ var path = new YenShortestPathsAlgorithm>.SortedPath(edges);
CollectionAssert.AreEqual(edges, path);
CollectionAssert.IsEmpty(
- new YenShortestPathsAlgorithm.SortedPath(
+ new YenShortestPathsAlgorithm>.SortedPath(
Enumerable.Empty>()));
}
}