Esempio n. 1
0
        public void AdjacentEdges_Throws()
        {
            var wrappedGraph = new BidirectionalGraph <EquatableTestVertex, Edge <EquatableTestVertex> >();
            var graph        = new UndirectedBidirectionalGraph <EquatableTestVertex, Edge <EquatableTestVertex> >(wrappedGraph);

            AdjacentEdges_Throws_Test(graph);
        }
        public void BinarySerialization_BidirectionalGraph([NotNull] BidirectionalGraph <int, EquatableEdge <int> > graph)
        {
            BidirectionalGraph <int, EquatableEdge <int> > deserializedGraph =
                SerializeDeserialize <int, EquatableEdge <int>, BidirectionalGraph <int, EquatableEdge <int> > >(graph);

            Assert.IsTrue(EquateGraphs.Equate(graph, deserializedGraph));

            var arrayGraph = new ArrayBidirectionalGraph <int, EquatableEdge <int> >(graph);
            ArrayBidirectionalGraph <int, EquatableEdge <int> > deserializedGraph2 =
                SerializeDeserialize <int, EquatableEdge <int>, ArrayBidirectionalGraph <int, EquatableEdge <int> > >(arrayGraph);

            Assert.IsTrue(EquateGraphs.Equate(arrayGraph, deserializedGraph2));

            var reversedGraph = new ReversedBidirectionalGraph <int, EquatableEdge <int> >(graph);
            ReversedBidirectionalGraph <int, EquatableEdge <int> > deserializedGraph3 =
                SerializeDeserialize <int, SReversedEdge <int, EquatableEdge <int> >, ReversedBidirectionalGraph <int, EquatableEdge <int> > >(reversedGraph);

            Assert.IsTrue(EquateGraphs.Equate(reversedGraph, deserializedGraph3));

            var undirectedBidirectionalGraph = new UndirectedBidirectionalGraph <int, EquatableEdge <int> >(graph);
            UndirectedBidirectionalGraph <int, EquatableEdge <int> > deserializedGraph4 =
                SerializeDeserialize <int, EquatableEdge <int>, UndirectedBidirectionalGraph <int, EquatableEdge <int> > >(undirectedBidirectionalGraph);

            Assert.IsTrue(EquateGraphs.Equate(undirectedBidirectionalGraph, deserializedGraph4));
        }
Esempio n. 3
0
        public void ReLayoutGraph()
        {
            //dane potrzebne w metodach obsługujących macierz
            MatrixMethod.NumberOfVertices = _numberOfVertices;
            MatrixMethod.ProbabilityValue = _probabilityValue;

            Graph             = new Graph(true);              //nowy graf
            _matrix           = MatrixMethod.FillTheMatrix(); //macierz incydencji
            _existingVertices = new List <Vertex>();          //lista przechowująca wierzchołki

            //wygenerowanie odpowiedniej ilości wierzchołków
            for (int i = 0; i < _numberOfVertices; i++)
            {
                _existingVertices.Add(new Vertex((i + 1).ToString(), i));
                Graph.AddVertex(_existingVertices[i]);
            }

            //generowanie krawędzi na podstawie macierzy
            EdgeMethod.GenerateEdges(_matrix, _existingVertices, Graph);

            //suma jest zapisana w ostatniej kolumnie macierzy oraz we właściwości obiektu vertex(VertexDegree)<=potrzebne w naprawie
            VertexMethod.CalculateTheSum(_matrix, _existingVertices);

            //zapisanie wierzołków sąsiadujących ze sobą(potrzebne w naprawie)
            VertexMethod.SetVertexNeighbors(_matrix, _existingVertices);

            UndirectedGraph = new UndirectedBidirectionalGraph <Vertex, Edge>(Graph);//coś jak canvas


            RefreshMatrixUi();//odświeżenie UI
        }
        public void GraphMLSerialization_BidirectionalGraph([NotNull] BidirectionalGraph <int, EquatableEdge <int> > graph)
        {
            AdjacencyGraph <int, EquatableEdge <int> > deserializedGraph =
                SerializeDeserialize <BidirectionalGraph <int, EquatableEdge <int> >, AdjacencyGraph <int, EquatableEdge <int> > >(graph);

            Assert.IsTrue(EquateGraphs.Equate(graph, deserializedGraph));

            var arrayGraph = new ArrayBidirectionalGraph <int, EquatableEdge <int> >(graph);
            AdjacencyGraph <int, EquatableEdge <int> > deserializedGraph2 =
                SerializeDeserialize <ArrayBidirectionalGraph <int, EquatableEdge <int> >, AdjacencyGraph <int, EquatableEdge <int> > >(arrayGraph);

            Assert.IsTrue(EquateGraphs.Equate(arrayGraph, deserializedGraph2));

            var reversedGraph = new ReversedBidirectionalGraph <int, EquatableEdge <int> >(graph);
            BidirectionalGraph <int, EquatableEdge <int> > deserializedGraph3 =
                SerializeDeserialize_Reversed <ReversedBidirectionalGraph <int, EquatableEdge <int> >, BidirectionalGraph <int, EquatableEdge <int> > >(reversedGraph);

            Assert.IsTrue(
                EquateGraphs.Equate(
                    graph,
                    deserializedGraph3,
                    EqualityComparer <int> .Default,
                    LambdaEqualityComparer <EquatableEdge <int> > .Create(
                        (edge1, edge2) => Equals(edge1.Source, edge2.Target) && Equals(edge1.Target, edge2.Source),
                        edge => edge.GetHashCode())));

            var undirectedBidirectionalGraph = new UndirectedBidirectionalGraph <int, EquatableEdge <int> >(graph);
            UndirectedGraph <int, EquatableEdge <int> > deserializedGraph4 =
                SerializeDeserialize <UndirectedBidirectionalGraph <int, EquatableEdge <int> >, UndirectedGraph <int, EquatableEdge <int> > >(undirectedBidirectionalGraph);

            Assert.IsTrue(EquateGraphs.Equate(undirectedBidirectionalGraph, deserializedGraph4));
        }
Esempio n. 5
0
        public void ContainsVertex_Throws()
        {
            var wrappedGraph = new BidirectionalGraph <TestVertex, Edge <TestVertex> >();
            var graph        = new UndirectedBidirectionalGraph <TestVertex, Edge <TestVertex> >(wrappedGraph);

            ContainsVertex_Throws_Test(graph);
        }
Esempio n. 6
0
        public void BinarySerialization_BidirectionalGraph_Complex([NotNull] BidirectionalGraph <EquatableTestVertex, EquatableTestEdge> graph)
        {
            BidirectionalGraph <EquatableTestVertex, EquatableTestEdge> deserializedGraph =
                SerializeDeserialize <EquatableTestVertex, EquatableTestEdge, BidirectionalGraph <EquatableTestVertex, EquatableTestEdge> >(graph);

            Assert.IsTrue(EquateGraphs.Equate(graph, deserializedGraph));

            var arrayGraph = new ArrayBidirectionalGraph <EquatableTestVertex, EquatableTestEdge>(graph);
            ArrayBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> deserializedGraph2 =
                SerializeDeserialize <EquatableTestVertex, EquatableTestEdge, ArrayBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> >(arrayGraph);

            Assert.IsTrue(EquateGraphs.Equate(arrayGraph, deserializedGraph2));

            var reversedGraph = new ReversedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge>(graph);
            ReversedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> deserializedGraph3 =
                SerializeDeserialize <EquatableTestVertex, SReversedEdge <EquatableTestVertex, EquatableTestEdge>, ReversedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> >(reversedGraph);

            Assert.IsTrue(EquateGraphs.Equate(reversedGraph, deserializedGraph3));

            var undirectedBidirectionalGraph = new UndirectedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge>(graph);
            UndirectedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> deserializedGraph4 =
                SerializeDeserialize <EquatableTestVertex, EquatableTestEdge, UndirectedBidirectionalGraph <EquatableTestVertex, EquatableTestEdge> >(undirectedBidirectionalGraph);

            Assert.IsTrue(EquateGraphs.Equate(undirectedBidirectionalGraph, deserializedGraph4));
        }
Esempio n. 7
0
        public void TryGetEdge_Throws()
        {
            var wrappedGraph = new BidirectionalGraph <TestVertex, Edge <TestVertex> >();
            var graph        = new UndirectedBidirectionalGraph <TestVertex, Edge <TestVertex> >(wrappedGraph);

            TryGetEdge_Throws_UndirectedGraph_Test(graph);
        }
Esempio n. 8
0
        public void AdjacentEdge_Throws()
        {
            var wrappedGraph = new BidirectionalGraph <int, Edge <int> >();
            var graph        = new UndirectedBidirectionalGraph <int, Edge <int> >(wrappedGraph);

            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            Assert.Throws <NotSupportedException>(() => graph.AdjacentEdge(1, 0));
        }
Esempio n. 9
0
        public void ContainsEdge_Throws()
        {
            var wrappedGraph = new BidirectionalGraph <TestVertex, Edge <TestVertex> >();
            var graph        = new UndirectedBidirectionalGraph <TestVertex, Edge <TestVertex> >(wrappedGraph);

            ContainsEdge_NullThrows_Test(graph);
            ContainsEdge_SourceTarget_Throws_UndirectedGraph_Test(graph);
        }
        public override void Compute(CancellationToken cancellationToken)
        {
            Sizes = new Dictionary <TVertex, Size>(VertexSizes);
            if (Parameters.Direction == LayoutDirection.LeftToRight || Parameters.Direction == LayoutDirection.RightToLeft)
            {
                //change the sizes
                foreach (var sizePair in Sizes.ToArray())
                {
                    Sizes[sizePair.Key] = new Size(sizePair.Value.Height, sizePair.Value.Width);
                }
            }

            if (Parameters.Direction == LayoutDirection.RightToLeft || Parameters.Direction == LayoutDirection.BottomToTop)
            {
                _direction = -1;
            }
            else
            {
                _direction = 1;
            }

            GenerateSpanningTree(cancellationToken);
            //DoWidthAndHeightOptimization();

            var graph = new UndirectedBidirectionalGraph <TVertex, TEdge>(VisitedGraph);
            var scca  = new QuickGraph.Algorithms.ConnectedComponents.ConnectedComponentsAlgorithm <TVertex, TEdge>(graph);

            scca.Compute();

            // Order connected components by their vertices count
            // Group vertices by connected component (they should be placed together)
            // Order vertices inside each conected component by in degree first, then out dregee
            // (roots should be placed in the first layer and leafs in the last layer)
            var components = from e in scca.Components
                             group e.Key by e.Value into c
                             orderby c.Count() descending
                             select c;

            foreach (var c in components)
            {
                var firstOfComponent = true;
                var vertices         = from v in c
                                       orderby VisitedGraph.InDegree(v), VisitedGraph.OutDegree(v) descending
                select v;

                foreach (var source in vertices)
                {
                    CalculatePosition(source, null, 0, firstOfComponent);

                    if (firstOfComponent)
                    {
                        firstOfComponent = false;
                    }
                }
            }

            AssignPositions(cancellationToken);
        }
Esempio n. 11
0
        private void GetDistancesAndWeights(out double[,] d, out double[,] w)
        {
            d = new double[VisitedGraph.VertexCount, VisitedGraph.VertexCount];
            w = new double[VisitedGraph.VertexCount, VisitedGraph.VertexCount];

            double maxCost    = 0.0001;
            var    undirected = new UndirectedBidirectionalGraph <TVertex, TEdge>(VisitedGraph);
            int    i          = 0;

            foreach (TVertex source in undirected.Vertices)
            {
                var spa = new UndirectedDijkstraShortestPathAlgorithm <TVertex, TEdge>(undirected, edge => edge is IWeightedEdge <TVertex>?Parameters.WeightAdjustment - (((IWeightedEdge <TVertex>)edge).Weight) : 1.0);
                spa.Compute(source);
                int j = 0;
                foreach (TVertex target in undirected.Vertices)
                {
                    double cost;
                    if (spa.TryGetDistance(target, out cost))
                    {
                        d[i, j] = cost;
                        if (cost > maxCost)
                        {
                            maxCost = cost;
                        }
                    }
                    else
                    {
                        d[i, j] = double.NaN;
                    }
                    j++;
                }
                i++;
            }

            double idealEdgeLength  = (Math.Min(Parameters.Width, Parameters.Height) / maxCost) * Parameters.LengthFactor;
            double disconnectedCost = maxCost * Parameters.DisconnectedMultiplier;

            for (i = 0; i < VisitedGraph.VertexCount; i++)
            {
                for (int j = 0; j < VisitedGraph.VertexCount; j++)
                {
                    if (double.IsNaN(d[i, j]))
                    {
                        d[i, j] = disconnectedCost;
                    }
                    else
                    {
                        d[i, j] *= idealEdgeLength;
                    }
                    w[i, j] = Math.Pow(Math.Max(d[i, j], 0.0001), -Parameters.Alpha);
                }
            }
        }
        public void ContainsEdge_UndirectedEdge()
        {
            var graph = new BidirectionalGraph <int, IEdge <int> >();

            var e12 = new EquatableUndirectedEdge <int>(1, 2);
            var f12 = new EquatableUndirectedEdge <int>(1, 2);

            graph.AddVerticesAndEdge(e12);

            BidirectionalContainsEdgeAssertions(graph, e12, f12, null, null);

            var undirectedGraph = new UndirectedBidirectionalGraph <int, IEdge <int> >(graph);

            ContainsEdgeAssertions(undirectedGraph, e12, f12, null, null);
        }
        public void ContainsEdgeTest1()
        {
            var bd = new BidirectionalGraph<int, IEdge<int>>();

            var e12 = new SEquatableUndirectedEdge<int>(1, 2);
            var f12 = new SEquatableUndirectedEdge<int>(1, 2);

            bd.AddVerticesAndEdge(e12);

            ContainsEdgeAssertions(bd, e12, f12, null, null);

            var u = new UndirectedBidirectionalGraph<int, IEdge<int>>(bd);

            UndirectedGraphTest.ContainsEdgeAssertions(u, e12, f12, null, null);
        }
Esempio n. 14
0
        //resetowanie danych
        public void ResetData()
        {
            Graph           = new Graph(true);
            UndirectedGraph = new UndirectedBidirectionalGraph <Vertex, Edge>(Graph);

            _matrix           = null;
            _UIMatrix         = null;
            _existingVertices = null;
            DataView          = null;
            DataTable         = null;

            NotifyPropertyChanged("Graph");
            NotifyPropertyChanged("UndirectedGraph");
            NotifyPropertyChanged("DataView");
        }
        public void ContainsEdgeTest1()
        {
            var bd = new BidirectionalGraph <int, IEdge <int> >();

            var e12 = new SEquatableUndirectedEdge <int>(1, 2);
            var f12 = new SEquatableUndirectedEdge <int>(1, 2);

            bd.AddVerticesAndEdge(e12);

            ContainsEdgeAssertions(bd, e12, f12, null, null);

            var u = new UndirectedBidirectionalGraph <int, IEdge <int> >(bd);

            UndirectedGraphTest.ContainsEdgeAssertions(u, e12, f12, null, null);
        }
Esempio n. 16
0
        public static double[,] GetDistances <TVertex, TEdge, TGraph>(
            [NotNull] this TGraph graph)
        where TEdge : IEdge <TVertex>
        where TGraph : IBidirectionalGraph <TVertex, TEdge>
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            var distances = new double[graph.VertexCount, graph.VertexCount];

            for (int k = 0; k < graph.VertexCount; ++k)
            {
                for (int j = 0; j < graph.VertexCount; ++j)
                {
                    distances[k, j] = double.PositiveInfinity;
                }
            }

            var undirected = new UndirectedBidirectionalGraph <TVertex, TEdge>(graph);
            // Compute the distances from every vertex: O(n(n^2 + e)) complexity
            int i = 0;

            foreach (TVertex source in graph.Vertices)
            {
                // Compute the distances from the 'source'
                // Each edge is taken into account as 1 (unweighted)
                var dijkstra = new UndirectedDijkstraShortestPathAlgorithm <TVertex, TEdge>(
                    undirected,
                    edge => 1.0,
                    DistanceRelaxers.ShortestDistance);
                dijkstra.Compute(source);

                int j = 0;
                foreach (TVertex vertex in undirected.Vertices)
                {
                    double distance = dijkstra.Distances[vertex];
                    distances[i, j] = Math.Min(distances[i, j], distance);
                    distances[i, j] = Math.Min(distances[i, j], distances[j, i]);
                    distances[j, i] = Math.Min(distances[i, j], distances[j, i]);
                    ++j;
                }
                ++i;
            }

            return(distances);
        }
Esempio n. 17
0
        /// <param name="g">The graph.</param>
        /// <returns>Returns with the distance between the vertices (distance: number of the edges).</returns>
        public static double[,] GetDistances <Vertex, Edge, Graph>(Graph g)
        where Edge : IEdge <Vertex>
        where Graph : IBidirectionalGraph <Vertex, Edge>
        {
            var distances = new double[g.VertexCount, g.VertexCount];

            for (int k = 0; k < g.VertexCount; k++)
            {
                for (int j = 0; j < g.VertexCount; j++)
                {
                    distances[k, j] = double.PositiveInfinity;
                }
            }

            var undirected = new UndirectedBidirectionalGraph <Vertex, Edge>(g);
            //minden élet egy hosszal veszünk figyelembe - unweighted
            var weights = new Dictionary <Edge, double>();

            foreach (Edge edge in undirected.Edges)
            {
                weights[edge] = 1;
            }

            //compute the distances from every vertex: O(n(n^2 + e)) complexity
            int i = 0;

            foreach (Vertex source in g.Vertices)
            {
                //compute the distances from the 'source'
                var spaDijkstra =
                    new UndirectedDijkstraShortestPathAlgorithm <Vertex, Edge>(undirected, (edge) => weights[edge], DistanceRelaxers.ShortestDistance);
                spaDijkstra.Compute(source);

                int j = 0;
                foreach (Vertex v in undirected.Vertices)
                {
                    double d = spaDijkstra.Distances[v];
                    distances[i, j] = Math.Min(distances[i, j], d);
                    distances[i, j] = Math.Min(distances[i, j], distances[j, i]);
                    distances[j, i] = Math.Min(distances[i, j], distances[j, i]);
                    j++;
                }

                i++;
            }

            return(distances);
        }
		public GraphHelperTest()
		{
			#region create directedGraph
			directedGraph = new BidirectionalGraph<string, Edge<string>>( );

			directedGraph.AddVertex( one ); directedGraph.AddVertex( two ); directedGraph.AddVertex( three ); directedGraph.AddVertex( four );
			directedGraph.AddEdge( new Edge<string>( one, four ) );
			directedGraph.AddEdge( new Edge<string>( one, three ) );
			directedGraph.AddEdge( new Edge<string>( four, two ) );
			directedGraph.AddEdge( new Edge<string>( one, two ) );
			#endregion

			#region create undirected graph
			undirectedGraph = new UndirectedBidirectionalGraph<string, Edge<string>>( directedGraph );
			#endregion
		}
Esempio n. 19
0
        public GraphHelperTest()
        {
            #region create directedGraph
            directedGraph = new BidirectionalGraph <string, Edge <string> >( );

            directedGraph.AddVertex(one); directedGraph.AddVertex(two); directedGraph.AddVertex(three); directedGraph.AddVertex(four);
            directedGraph.AddEdge(new Edge <string>(one, four));
            directedGraph.AddEdge(new Edge <string>(one, three));
            directedGraph.AddEdge(new Edge <string>(four, two));
            directedGraph.AddEdge(new Edge <string>(one, two));
            #endregion

            #region create undirected graph
            undirectedGraph = new UndirectedBidirectionalGraph <string, Edge <string> >(directedGraph);
            #endregion
        }
Esempio n. 20
0
        /// <param name="g">The graph.</param>
        /// <returns>Returns with the distance between the vertices (distance: number of the edges).</returns>
        private static double[,] GetDistances <TVertex, TEdge, TGraph>(TGraph g)
        where TEdge : IEdge <TVertex>
        where TGraph : IBidirectionalGraph <TVertex, TEdge>
        {
            var distances = new double[g.VertexCount, g.VertexCount];

            for (var k = 0; k < g.VertexCount; k++)
            {
                for (var j = 0; j < g.VertexCount; j++)
                {
                    distances[k, j] = double.PositiveInfinity;
                }
            }

            var undirected = new UndirectedBidirectionalGraph <TVertex, TEdge>(g);
            //minden йlet egy hosszal veszьnk figyelembe - unweighted
            var weights = new Dictionary <TEdge, double>();

            foreach (var edge in undirected.Edges)
            {
                weights[edge] = 1;
            }

            //compute the distances from every vertex: O(n(n^2 + e)) complexity
            var i = 0;

            foreach (var source in g.Vertices)
            {
                //compute the distances from the 'source'
                var spaDijkstra =
                    new UndirectedDijkstraShortestPathAlgorithm <TVertex, TEdge>(undirected, edge => weights[edge], QuickGraph.Algorithms.DistanceRelaxers.ShortestDistance);
                spaDijkstra.Compute(source);

                var j = 0;
                foreach (var v in undirected.Vertices)
                {
                    var d = spaDijkstra.Distances[v];
                    distances[i, j] = Math.Min(distances[i, j], d);
                    distances[i, j] = Math.Min(distances[i, j], distances[j, i]);
                    distances[j, i] = Math.Min(distances[i, j], distances[j, i]);
                    j++;
                }
                i++;
            }

            return(distances);
        }
        public void ContainsEdgeTest2()
        {
            var bd = new BidirectionalGraph <int, IEdge <int> >();

            var e12 = new EquatableEdge <int>(1, 2);
            var f12 = new EquatableEdge <int>(1, 2);
            var e21 = new EquatableEdge <int>(2, 1);
            var f21 = new EquatableEdge <int>(2, 1);

            bd.AddVerticesAndEdge(e12);

            ContainsEdgeAssertions(bd, e12, f12, e21, f21);

            var u = new UndirectedBidirectionalGraph <int, IEdge <int> >(bd);

            UndirectedGraphTest.ContainsEdgeAssertions(u, e12, f12, e21, f21);
        }
Esempio n. 22
0
        public void Construction()
        {
            var wrappedGraph = new BidirectionalGraph <int, Edge <int> >(true);
            var graph        = new UndirectedBidirectionalGraph <int, Edge <int> >(wrappedGraph);

            AssertGraphProperties(graph);

            wrappedGraph = new BidirectionalGraph <int, Edge <int> >(false);
            graph        = new UndirectedBidirectionalGraph <int, Edge <int> >(wrappedGraph);
            AssertGraphProperties(graph, false);

            #region Local function

            void AssertGraphProperties <TVertex, TEdge>(UndirectedBidirectionalGraph <TVertex, TEdge> g, bool parallelEdges = true)
                where TEdge : IEdge <TVertex>
            {
                Assert.IsFalse(g.IsDirected);
                Assert.AreEqual(parallelEdges, g.AllowParallelEdges);
                Assert.IsNotNull(g.OriginalGraph);
                AssertEmptyGraph(g);
            }

            #endregion
        }
        public void ContainsEdgeTest2()
        {
            var bd = new BidirectionalGraph<int, IEdge<int>>();

            var e12 = new EquatableEdge<int>(1, 2);
            var f12 = new EquatableEdge<int>(1, 2);
            var e21 = new EquatableEdge<int>(2, 1);
            var f21 = new EquatableEdge<int>(2, 1);

            bd.AddVerticesAndEdge(e12);

            ContainsEdgeAssertions(bd, e12, f12, e21, f21);

            var u = new UndirectedBidirectionalGraph<int, IEdge<int>>(bd);

            UndirectedGraphTest.ContainsEdgeAssertions(u, e12, f12, e21, f21);
        }
Esempio n. 24
0
        public int CalcMinDistToTarget(int[,] erosion)
        {
            var board = BuildBoard(erosion);
            var rooms = new Room[Size.Width, Size.Height];

            var graph = new BidirectionalGraph <Handle, Edge <Handle> >();

            for (var y = 0; y < Size.Height; ++y)
            {
                for (var x = 0; x < Size.Width; ++x)
                {
                    var room = new Room();
                    var pos  = new Point(x, y);
                    if (board[x, y] == '.')
                    {
                        graph.AddVertex(room.Climbing = new Handle {
                            Pos = pos, Equip = Equip.Climbing
                        });
                        graph.AddVertex(room.Torch = new Handle {
                            Pos = pos, Equip = Equip.Torch
                        });
                        graph.AddEdge(new Edge <Handle>(room.Climbing, room.Torch));
                    }
                    else if (board[x, y] == '=')
                    {
                        graph.AddVertex(room.Climbing = new Handle {
                            Pos = pos, Equip = Equip.Climbing
                        });
                        graph.AddVertex(room.Neither = new Handle {
                            Pos = pos, Equip = Equip.Neither
                        });
                        graph.AddEdge(new Edge <Handle>(room.Climbing, room.Neither));
                    }
                    else
                    {
                        graph.AddVertex(room.Torch = new Handle {
                            Pos = pos, Equip = Equip.Torch
                        });
                        graph.AddVertex(room.Neither = new Handle {
                            Pos = pos, Equip = Equip.Neither
                        });
                        graph.AddEdge(new Edge <Handle>(room.Torch, room.Neither));
                    }

                    rooms[x, y] = room;

                    if (x > 0)
                    {
                        var left = rooms[x - 1, y];
                        if (room.Climbing != null && left.Climbing != null)
                        {
                            graph.AddEdge(new Edge <Handle>(left.Climbing, room.Climbing));
                        }
                        if (room.Torch != null && left.Torch != null)
                        {
                            graph.AddEdge(new Edge <Handle>(left.Torch, room.Torch));
                        }
                        if (room.Neither != null && left.Neither != null)
                        {
                            graph.AddEdge(new Edge <Handle>(left.Neither, room.Neither));
                        }
                    }

                    if (y > 0)
                    {
                        var up = rooms[x, y - 1];
                        if (room.Climbing != null && up.Climbing != null)
                        {
                            graph.AddEdge(new Edge <Handle>(up.Climbing, room.Climbing));
                        }
                        if (room.Torch != null && up.Torch != null)
                        {
                            graph.AddEdge(new Edge <Handle>(up.Torch, room.Torch));
                        }
                        if (room.Neither != null && up.Neither != null)
                        {
                            graph.AddEdge(new Edge <Handle>(up.Neither, room.Neither));
                        }
                    }
                }
            }

            var sourceVertex = rooms[0, 0].Torch;
            var targetVertex = rooms[TargetPos.X, TargetPos.Y].Torch;

            double EdgeWeight(Edge <Handle> edge) => edge.Source.Equip == edge.Target.Equip ? 1 : 7;

            var undirected = new UndirectedBidirectionalGraph <Handle, Edge <Handle> >(graph);

            undirected.ShortestPathsDijkstra(EdgeWeight, sourceVertex)(targetVertex, out var path);

            var iter = sourceVertex;
            var cost = 0;

            foreach (var p in path)
            {
                cost += (int)EdgeWeight(p);
                iter  = p.GetOtherVertex(iter);
                //$"{iter.Pos.X},{iter.Pos.Y}: {iter.Equip}".Dump();
            }

            return(cost);
        }