Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify YenShortestPathsAlgorithm to support generic Edge type #84

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 25 additions & 28 deletions src/QuikGraph/Algorithms/ShortestPath/YenShortestPathsAlgorithm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ namespace QuikGraph.Algorithms.ShortestPath
/// with non negative edge cost.
/// </summary>
/// <typeparam name="TVertex">Vertex type.</typeparam>
public class YenShortestPathsAlgorithm<TVertex>
/// <typeparam name="TEdge">Edge type.</typeparam>
public class YenShortestPathsAlgorithm<TVertex, TEdge> where TEdge : IEdge<TVertex>
{
/// <summary>
/// Class representing a sorted path.
/// </summary>
public struct SortedPath : IEnumerable<EquatableTaggedEdge<TVertex, double>>, IEquatable<SortedPath>
public struct SortedPath : IEnumerable<TEdge>, IEquatable<SortedPath>
{
[NotNull, ItemNotNull]
private readonly List<EquatableTaggedEdge<TVertex, double>> _edges;
private readonly List<TEdge> _edges;

/// <summary>
/// Initializes a new instance of the <see cref="SortedPath"/> struct.
/// </summary>
public SortedPath([NotNull, ItemNotNull] IEnumerable<EquatableTaggedEdge<TVertex, double>> edges)
public SortedPath([NotNull, ItemNotNull] IEnumerable<TEdge> edges)
{
_edges = edges.ToList();
}
Expand All @@ -48,7 +49,7 @@ internal TVertex GetVertex(int i)

[Pure]
[NotNull]
internal EquatableTaggedEdge<TVertex, double> GetEdge(int i)
internal TEdge GetEdge(int i)
{
Debug.Assert(i >= 0 && i < _edges.Count);

Expand All @@ -57,7 +58,7 @@ internal EquatableTaggedEdge<TVertex, double> GetEdge(int i)

[Pure]
[NotNull, ItemNotNull]
internal EquatableTaggedEdge<TVertex, double>[] GetEdges(int count)
internal TEdge[] GetEdges(int count)
{
if (count > _edges.Count)
{
Expand Down Expand Up @@ -88,7 +89,7 @@ public override int GetHashCode()
}

/// <inheritdoc />
public IEnumerator<EquatableTaggedEdge<TVertex, double>> GetEnumerator()
public IEnumerator<TEdge> GetEnumerator()
{
return _edges.GetEnumerator();
}
Expand All @@ -104,7 +105,7 @@ IEnumerator IEnumerable.GetEnumerator()
private readonly TVertex _targetVertex;

[NotNull]
private readonly Func<EquatableTaggedEdge<TVertex, double>, double> _weights;
private readonly Func<TEdge, double> _weights;

[NotNull]
private readonly Func<IEnumerable<SortedPath>, IEnumerable<SortedPath>> _filter;
Expand All @@ -113,10 +114,10 @@ IEnumerator IEnumerable.GetEnumerator()
private readonly int _k;

[NotNull]
private readonly IMutableVertexAndEdgeListGraph<TVertex, EquatableTaggedEdge<TVertex, double>> _graph;
private readonly IMutableVertexAndEdgeListGraph<TVertex, TEdge> _graph;

/// <summary>
/// Initializes a new instance of the <see cref="YenShortestPathsAlgorithm{TVertex}"/> class.
/// Initializes a new instance of the <see cref="YenShortestPathsAlgorithm{TVertex,TEdge}"/> class.
/// </summary>
/// <remarks>
/// <see cref="T:System.Double"/> for tag type (edge) which comes from Dijkstra’s algorithm, which is used to get one shortest path.
Expand All @@ -134,11 +135,11 @@ IEnumerator IEnumerable.GetEnumerator()
/// <exception cref="T:System.ArgumentException"><paramref name="target"/> is not part of <paramref name="graph"/>.</exception>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="k"/> is lower than 1.</exception>
public YenShortestPathsAlgorithm(
[NotNull] AdjacencyGraph<TVertex, EquatableTaggedEdge<TVertex, double>> graph,
[NotNull] AdjacencyGraph<TVertex, TEdge> graph,
[NotNull] TVertex source,
[NotNull] TVertex target,
int k,
[CanBeNull] Func<EquatableTaggedEdge<TVertex, double>, double> edgeWeights = null,
[CanBeNull] Func<TEdge, double> edgeWeights,
[CanBeNull] Func<IEnumerable<SortedPath>, IEnumerable<SortedPath>> filter = null)
{
if (graph is null)
Expand All @@ -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;
}

Expand All @@ -169,12 +172,6 @@ private static IEnumerable<SortedPath> DefaultFilter([NotNull] IEnumerable<Sorte
return paths;
}

[Pure]
private static double DefaultGetWeights([NotNull] EquatableTaggedEdge<TVertex, double> edge)
{
return edge.Tag;
}

[Pure]
private double GetPathDistance([ItemNotNull] SortedPath edges)
{
Expand All @@ -196,7 +193,7 @@ private SortedPath GetInitialShortestPath()
[Pure]
[CanBeNull]
private SortedPath? GetShortestPathInGraph(
[NotNull] IVertexListGraph<TVertex, EquatableTaggedEdge<TVertex, double>> graph,
[NotNull] IVertexListGraph<TVertex, TEdge> graph,
[NotNull] TVertex source,
[NotNull] TVertex target)
{
Expand All @@ -205,16 +202,16 @@ private SortedPath GetInitialShortestPath()
Debug.Assert(target != null);

// Compute distances between the start vertex and other
var algorithm = new DijkstraShortestPathAlgorithm<TVertex, EquatableTaggedEdge<TVertex, double>>(graph, _weights);
var recorder = new VertexPredecessorRecorderObserver<TVertex, EquatableTaggedEdge<TVertex, double>>();
var algorithm = new DijkstraShortestPathAlgorithm<TVertex, TEdge>(graph, _weights);
var recorder = new VertexPredecessorRecorderObserver<TVertex, TEdge>();

using (recorder.Attach(algorithm))
{
algorithm.Compute(source);
}

// Get shortest path from start (source) vertex to target
return recorder.TryGetPath(target, out IEnumerable<EquatableTaggedEdge<TVertex, double>> path)
return recorder.TryGetPath(target, out IEnumerable<TEdge> path)
? new SortedPath(path)
: (SortedPath?)null;
}
Expand Down Expand Up @@ -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<TVertex, double>[] 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<TVertex, double> edgeToRemove = path.GetEdge(i);
TEdge edgeToRemove = path.GetEdge(i);
_edgesToRestore.Add(edgeToRemove);
_graph.RemoveEdge(edgeToRemove);
}
Expand Down Expand Up @@ -343,10 +340,10 @@ public IEnumerable<SortedPath> Execute()
}

[NotNull, ItemNotNull]
private readonly List<EquatableTaggedEdge<TVertex, double>> _edgesToRestore =
new List<EquatableTaggedEdge<TVertex, double>>();
private readonly List<TEdge> _edgesToRestore =
new List<TEdge>();

private void OnGraphEdgeRemoved([NotNull] EquatableTaggedEdge<TVertex, double> edge)
private void OnGraphEdgeRemoved([NotNull] TEdge edge)
{
_edgesToRestore.Add(edge);
}
Expand Down
Loading