예제 #1
0
        public static TryFunc <TVertex, IEnumerable <TEdge> > ShortestPathsBellmanFord <TVertex, TEdge>(
#if !NET20
            this
#endif
            IVertexAndEdgeListGraph <TVertex, TEdge> visitedGraph,
            Func <TEdge, double> edgeWeights,
            TVertex source
            )
            where TEdge : IEdge <TVertex>
        {
            Contract.Requires(visitedGraph != null);
            Contract.Requires(edgeWeights != null);
            Contract.Requires(source != null);

            var algorithm           = new BellmanFordShortestPathAlgorithm <TVertex, TEdge>(visitedGraph, edgeWeights);
            var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>();

            using (predecessorRecorder.Attach(algorithm))
                algorithm.Compute(source);

            var predecessors = predecessorRecorder.VertexPredecessors;

            return(delegate(TVertex v, out IEnumerable <TEdge> edges)
            {
                return EdgeExtensions.TryGetPath(predecessors, v, out edges);
            });
        }
예제 #2
0
        public void SetRootVertex_Throws()
        {
            var graph     = new AdjacencyGraph <TestVertex, Edge <TestVertex> >();
            var algorithm = new BellmanFordShortestPathAlgorithm <TestVertex, Edge <TestVertex> >(graph, _ => 1.0);

            SetRootVertex_Throws_Test(algorithm);
        }
예제 #3
0
        public void ClearRootVertex()
        {
            var graph     = new AdjacencyGraph <int, Edge <int> >();
            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, _ => 1.0);

            ClearRootVertex_Test(algorithm);
        }
예제 #4
0
        public void TryGetDistance_Throws()
        {
            var graph     = new AdjacencyGraph <TestVertex, Edge <TestVertex> >();
            var algorithm = new BellmanFordShortestPathAlgorithm <TestVertex, Edge <TestVertex> >(graph, edge => 1.0);

            TryGetDistance_Throws_Test(algorithm);
        }
예제 #5
0
        internal static Dictionary <string, double> Ancestor(Graph weightedDirectedGraph)
        {
            var tempGraph        = new Graph();
            var resultDictionary = new Dictionary <string, double>();

            //Create negative weighted directed graph
            tempGraph.AddVertexRange(weightedDirectedGraph.Vertices);
            tempGraph.AddEdgeRange(weightedDirectedGraph.Edges.Select(x => new Edge(x.Name, x.Source, x.Target, -x.Weight)));
            //Solve shortest path of Top -> vertex
            var algorithm = new BellmanFordShortestPathAlgorithm <string, Edge>(tempGraph, e => e.Weight);
            var pred      = new VertexPredecessorRecorderObserver <string, Edge>();

            pred.Attach(algorithm);
            foreach (var vertex in tempGraph.Vertices)
            {
                algorithm.Compute("Top");
                IEnumerable <Edge> path;
                pred.TryGetPath(vertex, out path);
                if (path != null)
                {
                    resultDictionary[vertex] = -path.Sum(a => a.Weight);
                }
            }
            return(resultDictionary);
        }
예제 #6
0
        public void TryGetDistance()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVertex(1);
            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, edge => 1.0);

            TryGetDistance_Test(algorithm);
        }
예제 #7
0
        public static IDictionary <string, double> Get(AdjacencyGraph <string, TaggedEdge <string, string> > graph, string root)
        {
            Func <TaggedEdge <string, string>, double> Weights = e => double.Parse(e.Tag);

            var algorithm = new BellmanFordShortestPathAlgorithm <string, TaggedEdge <string, string> >(graph, Weights);

            algorithm.Compute(root);
            return(algorithm.Distances);
        }
예제 #8
0
        public void ComputeWithRoot()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVertex(0);
            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, _ => 1.0);

            ComputeWithRoot_Test(algorithm);
        }
예제 #9
0
        public static IDictionary <int, double> Get(AdjacencyGraph <int, Edge <int> > graph, int root)
        {
            Func <Edge <int>, double> Weights = e => 1.0;

            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, Weights);

            algorithm.Compute(root);
            return(algorithm.Distances);
        }
예제 #10
0
        public void GetVertexColor_Throws()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVertex(0);
            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, edge => 1.0);

            algorithm.Compute(0);

            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            Assert.Throws <VertexNotFoundException>(() => algorithm.GetVertexColor(1));
        }
예제 #11
0
        public void GetVertexColor()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVerticesAndEdge(new Edge <int>(1, 2));

            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, _ => 1.0);

            algorithm.Compute(1);

            Assert.AreEqual(GraphColor.Black, algorithm.GetVertexColor(1));
            Assert.AreEqual(GraphColor.Black, algorithm.GetVertexColor(2));
        }
        public void Test_PathTo()
        {
            BellmanFordShortestPathAlgorithm alg = new BellmanFordShortestPathAlgorithm(this.CreateDigraph(), 0);

            AssertUtilities.Sequence(new Edge[4]
            {
                new Edge(0, 1, .5),
                new Edge(1, 5, .3),
                new Edge(5, 6, .5),
                new Edge(6, 4, .1)
            },
                                     alg.PathTo(4));
        }
예제 #13
0
        public void Constructor()
        {
            Func <Edge <int>, double> Weights = _ => 1.0;

            var graph     = new AdjacencyGraph <int, Edge <int> >();
            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, Weights);

            AssertAlgorithmProperties(algorithm, graph, Weights);

            algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(graph, Weights, DistanceRelaxers.CriticalDistance);
            AssertAlgorithmProperties(algorithm, graph, Weights, DistanceRelaxers.CriticalDistance);

            algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(null, graph, Weights, DistanceRelaxers.CriticalDistance);
            AssertAlgorithmProperties(algorithm, graph, Weights, DistanceRelaxers.CriticalDistance);

            #region Local function

            void AssertAlgorithmProperties <TVertex, TEdge>(
                BellmanFordShortestPathAlgorithm <TVertex, TEdge> algo,
                IVertexAndEdgeListGraph <TVertex, TEdge> g,
                Func <TEdge, double> eWeights = null,
                IDistanceRelaxer relaxer      = null)
                where TEdge : IEdge <TVertex>
            {
                AssertAlgorithmState(algo, g);
                Assert.IsNull(algo.VerticesColors);
                Assert.IsFalse(algo.FoundNegativeCycle);
                if (eWeights is null)
                {
                    Assert.IsNotNull(algo.Weights);
                }
                else
                {
                    Assert.AreSame(eWeights, algo.Weights);
                }
                CollectionAssert.IsEmpty(algo.GetDistances());
                if (relaxer is null)
                {
                    Assert.IsNotNull(algo.DistanceRelaxer);
                }
                else
                {
                    Assert.AreSame(relaxer, algo.DistanceRelaxer);
                }
            }

            #endregion
        }
예제 #14
0
        public static BellmanFordShortestPathAlgorithm <T, Edge <T> > CreateAlgorithmAndMaybeDoComputation <T>(
            [NotNull] ContractScenario <T> scenario)
        {
            var graph = new AdjacencyGraph <T, Edge <T> >();

            graph.AddVerticesAndEdgeRange(scenario.EdgesInGraph.Select(e => new Edge <T>(e.Source, e.Target)));
            graph.AddVertexRange(scenario.SingleVerticesInGraph);

            double Weights(Edge <T> e) => 1.0;

            var algorithm = new BellmanFordShortestPathAlgorithm <T, Edge <T> >(graph, Weights);

            if (scenario.DoComputation)
            {
                algorithm.Compute(scenario.Root);
            }
            return(algorithm);
        }
예제 #15
0
        //public void FindPath(string @from = "START", string @to = "END")
        //{
        //    Func<Edge<string>, double> edgeCost = AlgorithmExtensions.GetIndexer(EdgeCost);
        //    // Positive or negative weights
        //    TryFunc<string, System.Collections.Generic.IEnumerable<Edge<string>>> tryGetPath = Graph.ShortestPathsBellmanFord(edgeCost, @from);

        //    IEnumerable<Edge<string>> path;
        //    if (tryGetPath(@to, out path))
        //    {
        //        Console.Write("Path found from {0} to {1}: {0}", @from, @to);
        //        foreach (var e in path) { Console.Write(" > {0}", e.Target); }
        //        Console.WriteLine();
        //    }
        //    else { Console.WriteLine("No path found from {0} to {1}."); }
        //}

        public double GetETA(string start = "A")
        {
            Func <Edge <Vertex>, double> edgeCost = e => this.edgeCostList[e];

            // Bellman algorithm works with either positive or negative weights
            BellmanFordShortestPathAlgorithm <Vertex, Edge <Vertex> > pathCalc = new BellmanFordShortestPathAlgorithm <Vertex, Edge <Vertex> >(this.graph, edgeCost);

            Vertex source = nodeMap[start];
            Vertex target = nodeMap["Z"];

            pathCalc.Compute(source);

            var distances = pathCalc.Distances;

            var distanceToTarget = 0 - distances[target];

            return(distanceToTarget);
        }
예제 #16
0
 private static void Verify <TVertex, TEdge>(
     [NotNull] BellmanFordShortestPathAlgorithm <TVertex, TEdge> algorithm,
     [NotNull] VertexPredecessorRecorderObserver <TVertex, TEdge> predecessors)
     where TEdge : IEdge <TVertex>
 {
     // Verify the result
     foreach (TVertex vertex in algorithm.VisitedGraph.Vertices)
     {
         if (!predecessors.VerticesPredecessors.TryGetValue(vertex, out TEdge predecessor))
         {
             continue;
         }
         if (predecessor.Source.Equals(vertex))
         {
             continue;
         }
         Assert.AreEqual(
             algorithm.TryGetDistance(vertex, out double currentDistance),
             algorithm.TryGetDistance(predecessor.Source, out double predecessorDistance));
         Assert.GreaterOrEqual(currentDistance, predecessorDistance);
     }
 }
예제 #17
0
        private static void RunBellmanFordAndCheck <TVertex, TEdge>(
            [NotNull] IVertexAndEdgeListGraph <TVertex, TEdge> graph,
            [NotNull] TVertex root)
            where TEdge : IEdge <TVertex>
        {
            var distances = new Dictionary <TEdge, double>();

            foreach (TEdge edge in graph.Edges)
            {
                distances[edge] = graph.OutDegree(edge.Source) + 1;
            }

            var algorithm = new BellmanFordShortestPathAlgorithm <TVertex, TEdge>(
                graph,
                e => distances[e]);

            algorithm.InitializeVertex += vertex =>
            {
                Assert.AreEqual(GraphColor.White, algorithm.VerticesColors[vertex]);
            };

            var predecessors = new VertexPredecessorRecorderObserver <TVertex, TEdge>();

            using (predecessors.Attach(algorithm))
                algorithm.Compute(root);

            Assert.AreEqual(graph.VertexCount, algorithm.VerticesColors.Count);
            foreach (TVertex vertex in graph.Vertices)
            {
                Assert.AreEqual(GraphColor.Black, algorithm.VerticesColors[vertex]);
            }

            Assert.IsFalse(algorithm.FoundNegativeCycle);
            CollectionAssert.IsNotEmpty(algorithm.GetDistances());
            Assert.AreEqual(graph.VertexCount, algorithm.GetDistances().Count());

            Verify(algorithm, predecessors);
        }
예제 #18
0
        public void BellmanFord_NegativeCycle()
        {
            // Without negative cycle
            var edge12 = new Edge <int>(1, 2);
            var edge23 = new Edge <int>(2, 3);
            var edge34 = new Edge <int>(3, 4);

            var negativeWeightGraph = new AdjacencyGraph <int, Edge <int> >();

            negativeWeightGraph.AddVerticesAndEdgeRange(new[]
            {
                edge12, edge23, edge34
            });

            var algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(
                negativeWeightGraph,
                e =>
            {
                if (e == edge12)
                {
                    return(12.0);
                }
                if (e == edge23)
                {
                    return(-23.0);
                }
                if (e == edge34)
                {
                    return(-34.0);
                }
                return(1.0);
            });

            Assert.DoesNotThrow(() => algorithm.Compute(1));
            Assert.IsFalse(algorithm.FoundNegativeCycle);

            // With negative cycle
            var edge41 = new Edge <int>(4, 1);

            var negativeCycleGraph = new AdjacencyGraph <int, Edge <int> >();

            negativeCycleGraph.AddVerticesAndEdgeRange(new[]
            {
                edge12, edge23, edge34, edge41
            });

            algorithm = new BellmanFordShortestPathAlgorithm <int, Edge <int> >(
                negativeCycleGraph,
                e =>
            {
                if (e == edge12)
                {
                    return(12.0);
                }
                if (e == edge23)
                {
                    return(-23.0);
                }
                if (e == edge34)
                {
                    return(-34.0);
                }
                if (e == edge41)
                {
                    return(41.0);
                }
                return(1.0);
            });
            Assert.DoesNotThrow(() => algorithm.Compute(1));
            Assert.IsTrue(algorithm.FoundNegativeCycle);
        }
        public void Test_NotHasPathTo()
        {
            BellmanFordShortestPathAlgorithm alg = new BellmanFordShortestPathAlgorithm(this.CreateDigraph(), 0);

            Assert.False(alg.HasPathTo(7));
        }
        public void Test_DistanceTo()
        {
            BellmanFordShortestPathAlgorithm alg = new BellmanFordShortestPathAlgorithm(this.CreateDigraph(), 0);

            Assert.Equal(1.4, Math.Round(alg.DistanceTo(4), 1));
        }