BFA Update (still lots of testing to do tho)
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Framework.Collections;
|
||||
|
||||
namespace Framework.Algorithms
|
||||
{
|
||||
public class DepthFirstSearch
|
||||
{
|
||||
private bool[] marked; // marked[v] = is there an s-v path?
|
||||
private int count; // number of vertices connected to s
|
||||
|
||||
/**
|
||||
* Computes the vertices in graph {@code G} that are
|
||||
* connected to the source vertex {@code s}.
|
||||
* @param G the graph
|
||||
* @param s the source vertex
|
||||
* @throws IllegalArgumentException unless {@code 0 <= s < V}
|
||||
*/
|
||||
public DepthFirstSearch(EdgeWeightedDigraph G, uint s, Action<uint> action)
|
||||
{
|
||||
marked = new bool[G.NumberOfVertices];
|
||||
//validateVertex(s);
|
||||
dfs(G, s, action);
|
||||
}
|
||||
|
||||
// depth first search from v
|
||||
private void dfs(EdgeWeightedDigraph G, uint v, Action<uint> action)
|
||||
{
|
||||
count++;
|
||||
marked[v] = true;
|
||||
foreach (var w in G.Adjacent((int)v))
|
||||
{
|
||||
if (!marked[w.To])
|
||||
{
|
||||
action(w.To);
|
||||
dfs(G, w.To, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a path between the source vertex {@code s} and vertex {@code v}?
|
||||
* @param v the vertex
|
||||
* @return {@code true} if there is a path, {@code false} otherwise
|
||||
* @throws IllegalArgumentException unless {@code 0 <= v < V}
|
||||
*/
|
||||
public bool Marked(int v)
|
||||
{
|
||||
//validateVertex(v);
|
||||
return marked[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of vertices connected to the source vertex {@code s}.
|
||||
* @return the number of vertices connected to the source vertex {@code s}
|
||||
*/
|
||||
public int Count()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Framework.Collections;
|
||||
|
||||
namespace Framework.Algorithms
|
||||
{
|
||||
/// <summary>
|
||||
/// The DijkstraShortestPath class represents a data type for solving the single-source shortest paths problem
|
||||
/// in edge-weighted digraphs where the edge weights are non-negative
|
||||
/// </summary>
|
||||
/// <seealso href="http://algs4.cs.princeton.edu/44sp/DijkstraSP.java.html">DijkstraSP class from Princeton University's Java Algorithms</seealso>
|
||||
public class DijkstraShortestPath
|
||||
{
|
||||
private readonly double[] _distanceTo;
|
||||
private readonly DirectedEdge[] _edgeTo;
|
||||
private readonly IndexMinPriorityQueue<double> _priorityQueue;
|
||||
/// <summary>
|
||||
/// Computes a shortest paths tree from the specified sourceVertex to every other vertex in the edge-weighted directed graph
|
||||
/// </summary>
|
||||
/// <param name="graph">The edge-weighted directed graph</param>
|
||||
/// <param name="sourceVertex">The source vertex to compute the shortest paths tree from</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Throws an ArgumentOutOfRangeException if an edge weight is negative</exception>
|
||||
/// <exception cref="ArgumentNullException">Thrown if EdgeWeightedDigraph is null</exception>
|
||||
public DijkstraShortestPath(EdgeWeightedDigraph graph, int sourceVertex)
|
||||
{
|
||||
if (graph == null)
|
||||
{
|
||||
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
|
||||
}
|
||||
|
||||
foreach (DirectedEdge edge in graph.Edges())
|
||||
{
|
||||
if (edge.Weight < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"Edge: '{edge}' has negative weight");
|
||||
}
|
||||
}
|
||||
|
||||
_distanceTo = new double[graph.NumberOfVertices];
|
||||
_edgeTo = new DirectedEdge[graph.NumberOfVertices];
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
_distanceTo[v] = double.PositiveInfinity;
|
||||
}
|
||||
_distanceTo[sourceVertex] = 0.0;
|
||||
|
||||
_priorityQueue = new IndexMinPriorityQueue<double>(graph.NumberOfVertices);
|
||||
_priorityQueue.Insert(sourceVertex, _distanceTo[sourceVertex]);
|
||||
while (!_priorityQueue.IsEmpty())
|
||||
{
|
||||
int v = _priorityQueue.DeleteMin();
|
||||
foreach (DirectedEdge edge in graph.Adjacent(v))
|
||||
{
|
||||
Relax(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Relax(DirectedEdge edge)
|
||||
{
|
||||
uint v = edge.From;
|
||||
uint w = edge.To;
|
||||
if (_distanceTo[w] > _distanceTo[v] + edge.Weight)
|
||||
{
|
||||
_distanceTo[w] = _distanceTo[v] + edge.Weight;
|
||||
_edgeTo[w] = edge;
|
||||
if (_priorityQueue.Contains((int)w))
|
||||
{
|
||||
_priorityQueue.DecreaseKey((int)w, _distanceTo[w]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_priorityQueue.Insert((int)w, _distanceTo[w]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the length of a shortest path from the sourceVertex to the specified destinationVertex
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
|
||||
/// <returns>The length of a shortest path from the sourceVertex to the specified destinationVertex or double.PositiveInfinity if no such path exists</returns>
|
||||
public double DistanceTo(int destinationVertex)
|
||||
{
|
||||
return _distanceTo[destinationVertex];
|
||||
}
|
||||
/// <summary>
|
||||
/// Is there a path from the sourceVertex to the specified destinationVertex?
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to see if there is a path to</param>
|
||||
/// <returns>True if there is a path from the sourceVertex to the specified destinationVertex, false otherwise</returns>
|
||||
public bool HasPathTo(int destinationVertex)
|
||||
{
|
||||
return _distanceTo[destinationVertex] < double.PositiveInfinity;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
|
||||
/// <returns>IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex</returns>
|
||||
public IEnumerable<DirectedEdge> PathTo(int destinationVertex)
|
||||
{
|
||||
if (!HasPathTo(destinationVertex))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var path = new Stack<DirectedEdge>();
|
||||
for (DirectedEdge edge = _edgeTo[destinationVertex]; edge != null; edge = _edgeTo[edge.From])
|
||||
{
|
||||
path.Push(edge);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
// TODO: This method should be private and should be called from the bottom of the constructor
|
||||
/// <summary>
|
||||
/// check optimality conditions:
|
||||
/// </summary>
|
||||
/// <param name="graph">The edge-weighted directed graph</param>
|
||||
/// <param name="sourceVertex">The source vertex to check optimality conditions from</param>
|
||||
/// <returns>True if all optimality conditions are met, false otherwise</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown on null EdgeWeightedDigraph</exception>
|
||||
public bool Check(EdgeWeightedDigraph graph, int sourceVertex)
|
||||
{
|
||||
if (graph == null)
|
||||
{
|
||||
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
|
||||
}
|
||||
|
||||
if (_distanceTo[sourceVertex] != 0.0 || _edgeTo[sourceVertex] != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
if (v == sourceVertex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (_edgeTo[v] == null && _distanceTo[v] != double.PositiveInfinity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
foreach (DirectedEdge edge in graph.Adjacent(v))
|
||||
{
|
||||
uint w = edge.To;
|
||||
if (_distanceTo[v] + edge.Weight < _distanceTo[w])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int w = 0; w < graph.NumberOfVertices; w++)
|
||||
{
|
||||
if (_edgeTo[w] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
DirectedEdge edge = _edgeTo[w];
|
||||
uint v = edge.From;
|
||||
if (w != edge.To)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_distanceTo[v] + edge.Weight != _distanceTo[w])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user