Beispiel #1
0
 public void ReverseEdges_Throws()
 {
     // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
     // ReSharper disable once AssignNullToNotNullAttribute
     Assert.Throws <ArgumentNullException>(
         () => EdgeExtensions.ReverseEdges <int, Edge <int> >(null));
 }
        public static TryFunc <TVertex, IEnumerable <TEdge> > TreeCyclePoppingRandom <TVertex, TEdge>(
            this
            IVertexListGraph <TVertex, TEdge> visitedGraph,
            TVertex root,
            IMarkovEdgeChain <TVertex, TEdge> edgeChain)
            where TEdge : IEdge <TVertex>
        {
            Contract.Requires(visitedGraph != null);
            Contract.Requires(root != null);
            Contract.Requires(visitedGraph.ContainsVertex(root));
            Contract.Ensures(Contract.Result <TryFunc <TVertex, IEnumerable <TEdge> > >() != null);

            var algo = new CyclePoppingRandomTreeAlgorithm <TVertex, TEdge>(visitedGraph, edgeChain);
            var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>();

            using (predecessorRecorder.Attach(algo))
                algo.Compute(root);

            var predecessors = predecessorRecorder.VertexPredecessors;

            return(delegate(TVertex v, out IEnumerable <TEdge> edges)
            {
                return EdgeExtensions.TryGetPath(predecessors, v, out edges);
            });
        }
        /// <summary>
        /// Computes a depth first tree.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertex.</typeparam>
        /// <typeparam name="TEdge">The type of the edge.</typeparam>
        /// <param name="visitedGraph">The visited graph.</param>
        /// <param name="root">The root.</param>
        /// <returns></returns>
        public static TryFunc <TVertex, IEnumerable <TEdge> > TreeDepthFirstSearch <TVertex, TEdge>(
#if !NET20
            this
#endif
            IVertexListGraph <TVertex, TEdge> visitedGraph,
            TVertex root)
            where TEdge : IEdge <TVertex>
        {
            //Contract.Requires(visitedGraph != null);
            //Contract.Requires(root != null);
            //Contract.Requires(visitedGraph.ContainsVertex(root));
            //Contract.Ensures(//Contract.Result<TryFunc<TVertex, IEnumerable<TEdge>>>() != null);

            var algo = new DepthFirstSearchAlgorithm <TVertex, TEdge>(visitedGraph);
            var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>();

            using (predecessorRecorder.Attach(algo))
                algo.Compute(root);

            var predecessors = predecessorRecorder.VertexPredecessors;

            return(delegate(TVertex v, out IEnumerable <TEdge> edges)
            {
                return EdgeExtensions.TryGetPath(predecessors, v, out edges);
            });
        }
        public static TryFunc <TVertex, IEnumerable <TEdge> > ShortestPathsAStar <TVertex, TEdge>(
#if !NET20
            this
#endif
            IVertexAndEdgeListGraph <TVertex, TEdge> visitedGraph,
            Func <TEdge, double> edgeWeights,
            Func <TVertex, double> costHeuristic,
            TVertex source
            )
            where TEdge : IEdge <TVertex>
        {
            //Contract.Requires(visitedGraph != null);
            //Contract.Requires(edgeWeights != null);
            //Contract.Requires(costHeuristic != null);
            //Contract.Requires(source != null);

            var algorithm           = new AStarShortestPathAlgorithm <TVertex, TEdge>(visitedGraph, edgeWeights, costHeuristic);
            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);
            });
        }
Beispiel #5
0
    }                           // {return entryEdges.Count;}}

    public Frame(Dictionary <Edge, FrameWall> frameWalls)
    {
        foreach (Edge edge in EdgeExtensions.AllEdges())
        {
            if (!frameWalls.ContainsKey(edge))
            {
                throw new ArgumentException("Missing framewall for an edge");
            }
        }
        if (frameWalls[Edge.Left].Length != frameWalls[Edge.Right].Length)
        {
            throw new ArgumentException("Parallel vertical framewalls have different Lengths");
        }
        if (frameWalls[Edge.Bottom].Length != frameWalls[Edge.Top].Length)
        {
            throw new ArgumentException("Parallel horizontal framewalls have different Lengths");
        }
        FrameWalls = frameWalls;

        Width  = frameWalls[Edge.Bottom].Length;
        Height = frameWalls[Edge.Left].Length;

        EntryEdges = new List <Edge>();
        foreach (KeyValuePair <Edge, FrameWall> item in frameWalls)
        {
            if (item.Value.HasEntry)
            {
                EntryEdges.Add(item.Key);
            }
        }
        EntryCount = EntryEdges.Count;
    }
Beispiel #6
0
    //my edge
    public FrameRange FrameRangeOff(Edge edge)
    {
        FrameWall wall = FrameWalls[edge];

        if (!wall.HasEntry)
        {
            return(FrameRange.Empty);
        }

        Dictionary <Edge, FrameWallRange> frameWallRanges = new Dictionary <Edge, FrameWallRange>();

        frameWallRanges[edge.Opposite()] = new FrameWallRange(
            new FrameWall(0, wall.Entry, 0),
            new FrameWall(int.MaxValue, wall.Entry, int.MaxValue)
            );
        foreach (Edge missingEdge in EdgeExtensions.AllEdges())
        {
            if (!frameWallRanges.ContainsKey(missingEdge))
            {
                frameWallRanges[missingEdge] = FrameWallRange.All;
            }
        }

        return(new FrameRange(frameWallRanges));
    }
Beispiel #7
0
        public IEnumerable <IEnumerable <TEdge> > HoffmanPavleyRankedShortestPath <TVertex, TEdge>(
            [PexAssumeNotNull] IBidirectionalGraph <TVertex, TEdge> g,
            [PexAssumeNotNull] Dictionary <TEdge, double> edgeWeights,
            TVertex rootVertex,
            TVertex goalVertex,
            int pathCount
            )
            where TEdge : IEdge <TVertex>
        {
            //GraphConsoleSerializer.DisplayGraph((IEdgeListGraph<TVertex, TEdge>)g);

            PexAssert.TrueForAll(g.Edges, edgeWeights.ContainsKey);

            var target = new HoffmanPavleyRankedShortestPathAlgorithm <TVertex, TEdge>(g, e => edgeWeights[e]);

            target.ShortestPathCount = pathCount;
            target.Compute(rootVertex, goalVertex);

            double lastWeight = double.MinValue;

            foreach (var path in target.ComputedShortestPaths)
            {
                Console.WriteLine("path: {0}", Enumerable.Sum(path, e => edgeWeights[e]));
                double weight = Enumerable.Sum(path, e => edgeWeights[e]);
                Assert.IsTrue(lastWeight <= weight, "{0} <= {1}", lastWeight, weight);
                Assert.AreEqual(rootVertex, Enumerable.First(path).Source);
                Assert.AreEqual(goalVertex, Enumerable.Last(path).Target);
                Assert.IsTrue(EdgeExtensions.IsPathWithoutCycles <TVertex, TEdge>(path));

                lastWeight = weight;
            }

            return(target.ComputedShortestPaths);
        }
Beispiel #8
0
        private void EnqueueFirstShortestPath(
            IQueue <DeviationPath> queue,
            IDictionary <TVertex, TEdge> successors,
            IDictionary <TVertex, double> distances,
            TVertex root)
        {
            Contract.Requires(queue != null);
            Contract.Requires(queue.Count == 0);
            Contract.Requires(successors != null);
            Contract.Requires(distances != null);
            Contract.Requires(root != null);

            var path = new List <TEdge>();

            AppendShortestPath(
                path,
                successors,
                root);
            if (path.Count == 0)
            {
                return; // unreachable vertices
            }
            if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path))
            {
                this.AddComputedShortestPath(path);
            }

            // create deviation paths
            this.EnqueueDeviationPaths(
                queue,
                root,
                distances,
                path.ToArray(),
                0);
        }
Beispiel #9
0
        public void TarjanOfflineLeastCommonAncestorAlgorithm <TVertex, TEdge>(
            [PexAssumeNotNull] IVertexListGraph <TVertex, TEdge> g,
            [PexAssumeNotNull] TVertex root,
            [PexAssumeNotNull] SEquatableEdge <TVertex>[] pairs
            )
            where TEdge : IEdge <TVertex>
        {
            var lca          = g.OfflineLeastCommonAncestorTarjan(root, pairs);
            var predecessors = new VertexPredecessorRecorderObserver <TVertex, TEdge>();
            var dfs          = new DepthFirstSearchAlgorithm <TVertex, TEdge>(g);

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

            TVertex ancestor;

            foreach (var pair in pairs)
            {
                if (lca(pair, out ancestor))
                {
                    Assert.IsTrue(EdgeExtensions.IsPredecessor(predecessors.VertexPredecessors, root, pair.Source));
                    Assert.IsTrue(EdgeExtensions.IsPredecessor(predecessors.VertexPredecessors, root, pair.Target));
                }
            }
        }
        public static TryFunc <TVertex, IEnumerable <TEdge> > ShortestPathsDijkstra <TVertex, TEdge>(
#if !NET20
            this
#endif
            IUndirectedGraph <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 UndirectedDijkstraShortestPathAlgorithm <TVertex, TEdge>(visitedGraph, edgeWeights);
            var predecessorRecorder = new UndirectedVertexPredecessorRecorderObserver <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);
            });
        }
Beispiel #11
0
    public override string ToString()
    {
        string str = "";

        foreach (Edge edge in EdgeExtensions.AllEdges())
        {
            str += edge + ": " + FrameWalls[edge] + "\n";
        }
        str = str.Substring(0, str.Length - 1);
        return(str);
    }
 public FrameRange(Dictionary <Edge, FrameWallRange> frameWallRanges)
 {
     foreach (Edge edge in EdgeExtensions.AllEdges())
     {
         if (!frameWallRanges.ContainsKey(edge))
         {
             throw new ArgumentException("Missing framewall range for an edge");
         }
     }
     FrameWallRanges = frameWallRanges;
 }
        private void EnqueueDeviationPaths(
            IQueue <DeviationPath> queue,
            TVertex root,
            IDictionary <TVertex, TEdge> successors,
            IDictionary <TVertex, double> distances,
            TEdge[] path,
            int startEdge
            )
        {
            Contract.Requires(queue != null);
            Contract.Requires(root != null);
            Contract.Requires(successors != null);
            Contract.Requires(distances != null);
            Contract.Requires(path != null);
            Contract.Requires(EdgeExtensions.IsAdjacent <TVertex, TEdge>(path[0], root));
            Contract.Requires(0 <= startEdge && startEdge < path.Length);

            TVertex previousVertex = root;
            double  previousWeight = 0;
            var     pathVertices   = new Dictionary <TVertex, int>(path.Length);

            for (int iedge = 0; iedge < path.Length; ++iedge)
            {
                var edge = path[iedge];
                if (iedge >= startEdge)
                {
                    this.EnqueueDeviationPaths(
                        queue,
                        distances,
                        path,
                        iedge,
                        previousVertex,
                        previousWeight,
                        pathVertices
                        );
                }

                // update counter
                previousVertex  = edge.Target;
                previousWeight += this.edgeWeights(edge);

                // detection of loops
                if (iedge == 0)
                {
                    pathVertices[edge.Source] = 0;
                }
                // we should really allow only one key
                if (pathVertices.ContainsKey(edge.Target))
                {
                    break;
                }
                pathVertices[edge.Target] = 0;
            }
        }
        private void EnqueueDeviationPaths(
            IQueue <DeviationPath> queue,
            IDictionary <TVertex, double> distances,
            TEdge[] path,
            int iedge,
            TVertex previousVertex,
            double previousWeight,
            Dictionary <TVertex, int> pathVertices
            )
        {
            Contract.Requires(queue != null);
            Contract.Requires(distances != null);
            Contract.Requires(path != null);

            var edge = path[iedge];

            foreach (var deviationEdge in this.VisitedGraph.OutEdges(previousVertex))
            {
                // skip self edges,
                // skip equal edges,
                if (deviationEdge.Equals(edge) ||
                    EdgeExtensions.IsSelfEdge <TVertex, TEdge>(deviationEdge))
                {
                    continue;
                }

                // any edge obviously creating a loop
                var atarget = deviationEdge.Target;

                double adistance;
                if (distances.TryGetValue(atarget, out adistance))
                {
                    var deviationWeight =
                        this.DistanceRelaxer.Combine(
                            previousWeight,
                            this.DistanceRelaxer.Combine(
                                this.edgeWeights(deviationEdge),
                                adistance
                                )
                            );

                    var deviation = new DeviationPath(
                        path,
                        iedge,
                        deviationEdge,
                        deviationWeight
                        );
                    queue.Enqueue(deviation);
                }
            }
        }
        public IEnumerable <IEnumerable <TEdge> > AllPaths()
        {
            List <IEnumerable <TEdge> > es = new List <IEnumerable <TEdge> >();

            foreach (var v in this.EndPathVertices)
            {
                IEnumerable <TEdge> path;
                if (EdgeExtensions.TryGetPath(this.vertexPredecessors, v, out path))
                {
                    es.Add(path);
                }
            }
            return(es);
        }
Beispiel #16
0
        public bool RemoveEdge(TEdge edge)
        {
            bool removed = this._adjacentEdges[edge.Source].Remove(edge);

            if (removed)
            {
                if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge))
                {
                    this._adjacentEdges[edge.Target].Remove(edge);
                }
                this.EdgeCount--;
                Contract.Assert(this.EdgeCount >= 0);
                this.OnEdgeRemoved(edge);
                return(true);
            }
            else
            {
                return(false);
            }
        }
        protected override void InternalCompute()
        {
            var cancelManager = this.Services.CancelManager;

            TVertex root;

            if (!this.TryGetRootVertex(out root))
            {
                throw new InvalidOperationException("root vertex not set");
            }
            if (this.pairs == null)
            {
                throw new InvalidOperationException("pairs not set");
            }

            var gpair       = GraphExtensions.ToAdjacencyGraph(this.pairs);
            var disjointSet = new ForestDisjointSet <TVertex>();
            var vancestors  = new Dictionary <TVertex, TVertex>();
            var dfs         = new DepthFirstSearchAlgorithm <TVertex, TEdge>(this, this.VisitedGraph, new Dictionary <TVertex, GraphColor>(this.VisitedGraph.VertexCount));

            dfs.InitializeVertex += v => disjointSet.MakeSet(v);
            dfs.DiscoverVertex   += v => vancestors[v] = v;
            dfs.TreeEdge         += edge =>
            {
                disjointSet.Union(edge.Source, edge.Target);
                vancestors[disjointSet.FindSet(edge.Source)] = edge.Source;
            };
            dfs.FinishVertex += v =>
            {
                foreach (var e in gpair.OutEdges(v))
                {
                    if (dfs.VertexColors[e.Target] == GraphColor.Black)
                    {
                        this.ancestors[EdgeExtensions.ToVertexPair <TVertex, SEquatableEdge <TVertex> >(e)] = vancestors[disjointSet.FindSet(e.Target)];
                    }
                }
            };

            // go!
            dfs.Compute(root);
        }
        public void ReverseEdges()
        {
            CollectionAssert.IsEmpty(EdgeExtensions.ReverseEdges <int, Edge <int> >(Enumerable.Empty <Edge <int> >()));

            var edge1 = new Edge <int>(1, 2);

            CollectionAssert.AreEqual(
                new[] { new SReversedEdge <int, Edge <int> >(edge1) },
                EdgeExtensions.ReverseEdges <int, Edge <int> >(new[] { edge1 }));

            var edge2 = new Edge <int>(2, 2);
            var edge3 = new Edge <int>(3, 1);

            CollectionAssert.AreEqual(
                new[]
            {
                new SReversedEdge <int, Edge <int> >(edge1),
                new SReversedEdge <int, Edge <int> >(edge2),
                new SReversedEdge <int, Edge <int> >(edge3)
            },
                EdgeExtensions.ReverseEdges <int, Edge <int> >(new[] { edge1, edge2, edge3 }));
        }
Beispiel #19
0
        public bool AddVerticesAndEdge(TEdge edge)
        {
            var sourceEdges = this.AddAndReturnEdges(edge.Source);
            var targetEdges = this.AddAndReturnEdges(edge.Target);

            if (!this.AllowParallelEdges)
            {
                if (this.ContainsEdgeBetweenVertices(sourceEdges, edge))
                {
                    return(false);
                }
            }

            sourceEdges.Add(edge);
            if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge))
            {
                targetEdges.Add(edge);
            }
            this.EdgeCount++;
            this.OnEdgeAdded(edge);

            return(true);
        }
Beispiel #20
0
        public bool AddEdge(TEdge edge)
        {
            var sourceEdges = _adjacentEdges[edge.Source];

            if (!AllowParallelEdges)
            {
                if (ContainsEdgeBetweenVertices(sourceEdges, edge))
                {
                    return(false);
                }
            }

            sourceEdges.Add(edge);
            if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge))
            {
                var targetEdges = _adjacentEdges[edge.Target];
                targetEdges.Add(edge);
            }
            EdgeCount++;
            OnEdgeAdded(edge);

            return(true);
        }
        protected override void InternalCompute()
        {
            var     cancelManager = this.Services.CancelManager;
            TVertex root;

            if (!this.TryGetRootVertex(out root))
            {
                throw new InvalidOperationException("root vertex not set");
            }
            TVertex goal;

            if (!this.TryGetGoalVertex(out goal))
            {
                throw new InvalidOperationException("goal vertex not set");
            }

            // start by building the minimum tree starting from the goal vertex.
            IDictionary <TVertex, TEdge>  successors;
            IDictionary <TVertex, double> distances;

            this.ComputeMinimumTree(goal, out successors, out distances);

            if (cancelManager.IsCancelling)
            {
                return;
            }

            var queue       = new FibonacciQueue <DeviationPath, double>(dp => dp.Weight);
            var vertexCount = this.VisitedGraph.VertexCount;

            // first shortest path
            this.EnqueueFirstShortestPath(queue, successors, distances, root);

            while (queue.Count > 0 &&
                   this.ComputedShortestPathCount < this.ShortestPathCount)
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                var deviation = queue.Dequeue();

                // turn into path
                var path = new List <TEdge>();
                for (int i = 0; i < deviation.DeviationIndex; ++i)
                {
                    path.Add(deviation.ParentPath[i]);
                }
                path.Add(deviation.DeviationEdge);
                int startEdge = path.Count;
                this.AppendShortestPath(path, successors, deviation.DeviationEdge.Target);

                Contract.Assert(deviation.Weight == Enumerable.Sum(path, e => edgeWeights(e)));
                Contract.Assert(path.Count > 0);

                // add to list if loopless
                if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path))
                {
                    this.AddComputedShortestPath(path);
                }

                // append new deviation paths
                if (path.Count < vertexCount)
                {
                    this.EnqueueDeviationPaths(
                        queue,
                        root,
                        successors,
                        distances,
                        path.ToArray(),
                        startEdge
                        );
                }
            }
        }
Beispiel #22
0
 public XUndirectedGraph(bool allowParallelEdges) : this(allowParallelEdges, EdgeExtensions.GetUndirectedVertexEquality <TVertex, TEdge>())
 {
     AllowParallelEdges = allowParallelEdges;
 }
Beispiel #23
0
 public bool TryGetPath(TVertex vertex, out IEnumerable <TEdge> path)
 {
     return(EdgeExtensions.TryGetPath(this.VertexPredecessors, vertex, out path));
 }
        protected override void InternalCompute()
        {
            TVertex root;

            if (!this.TryGetRootVertex(out root))
            {
                throw new InvalidOperationException("root vertex not set");
            }
            TVertex goal;

            if (!this.TryGetGoalVertex(out goal))
            {
                throw new InvalidOperationException("goal vertex not set");
            }

            // little shortcut
            if (root.Equals(goal))
            {
                this.OnGoalReached();
                return; // found it
            }

            var cancelManager = this.Services.CancelManager;
            var open          = new BinaryHeap <double, TVertex>(this.distanceRelaxer.Compare);
            var operators     = new Dictionary <TEdge, GraphColor>();
            var g             = this.VisitedGraph;

            // (1) Place the initial node on Open, with all its operators marked unused.
            open.Add(0, root);
            foreach (var edge in g.OutEdges(root))
            {
                operators.Add(edge, GraphColor.White);
            }

            while (open.Count > 0)
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                // (3) Else, choose an Open node n of lowest cost for expansion
                var entry = open.RemoveMinimum();
                var cost  = entry.Key;
                var n     = entry.Value;

                // (4) if node n is a goal node, terminate with success
                if (n.Equals(goal))
                {
                    this.OnGoalReached();
                    return;
                }

                // (5) else, expand node n,
                // genarting all successors n' reachable via unused legal operators
                // compute their cost and delete node n
                foreach (var edge in g.OutEdges(n))
                {
                    if (EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge))
                    {
                        continue; // skip self-edges
                    }
                    GraphColor edgeColor;
                    bool       hasColor = operators.TryGetValue(edge, out edgeColor);
                    if (!hasColor || edgeColor == GraphColor.White)
                    {
                        var weight = this.edgeWeights(edge);
                        var ncost  = this.distanceRelaxer.Combine(cost, weight);

                        // (7) foreach neighboring node of n' mark the operator from n to n' as used
                        // (8) for each node n', if there is no copy of n' in open addit
                        // else save on open on the copy of n' with lowest cose. Mark as used all operators
                        // mak as used in any of the copies
                        operators[edge] = GraphColor.Gray;
                        if (open.MinimumUpdate(ncost, edge.Target))
                        {
                            this.OnTreeEdge(edge);
                        }
                    }
                    else if (hasColor)
                    {
                        Contract.Assume(edgeColor == GraphColor.Gray);
                        // edge already seen, remove it
                        operators.Remove(edge);
                    }
                }

#if DEBUG
                this.operatorMaxCount = Math.Max(this.operatorMaxCount, operators.Count);
#endif

                // (6) in a directed graph, generate each predecessor node n via an unused operator
                // and create dummy nodes for each with costs of infinity
                foreach (var edge in g.InEdges(n))
                {
                    GraphColor edgeColor;
                    if (operators.TryGetValue(edge, out edgeColor) &&
                        edgeColor == GraphColor.Gray)
                    {
                        // delete node n
                        operators.Remove(edge);
                    }
                }
            }
        }
Beispiel #25
0
        protected override void InternalCompute()
        {
            var cancelManager = this.Services.CancelManager;

            // matrix i,j -> path
            this.data.Clear();

            var vertices = this.VisitedGraph.Vertices;
            var edges    = this.VisitedGraph.Edges;

            // prepare the matrix with initial costs
            // walk each edge and add entry in cost dictionary
            foreach (var edge in edges)
            {
                var        ij   = EdgeExtensions.ToVertexPair <TVertex, TEdge>(edge);
                var        cost = this.weights(edge);
                VertexData value;
                if (!data.TryGetValue(ij, out value))
                {
                    data[ij] = new VertexData(cost, edge);
                }
                else if (cost < value.Distance)
                {
                    data[ij] = new VertexData(cost, edge);
                }
            }
            if (cancelManager.IsCancelling)
            {
                return;
            }

            // walk each vertices and make sure cost self-cost 0
            foreach (var v in vertices)
            {
                data[new SEquatableEdge <TVertex>(v, v)] = new VertexData(0, default(TEdge));
            }

            if (cancelManager.IsCancelling)
            {
                return;
            }

            // iterate k, i, j
            foreach (var vk in vertices)
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }
                foreach (var vi in vertices)
                {
                    var        ik = new SEquatableEdge <TVertex>(vi, vk);
                    VertexData pathik;
                    if (data.TryGetValue(ik, out pathik))
                    {
                        foreach (var vj in vertices)
                        {
                            var kj = new SEquatableEdge <TVertex>(vk, vj);

                            VertexData pathkj;
                            if (data.TryGetValue(kj, out pathkj))
                            {
                                double     combined = this.distanceRelaxer.Combine(pathik.Distance, pathkj.Distance);
                                var        ij       = new SEquatableEdge <TVertex>(vi, vj);
                                VertexData pathij;
                                if (data.TryGetValue(ij, out pathij))
                                {
                                    if (this.distanceRelaxer.Compare(combined, pathij.Distance) < 0)
                                    {
                                        data[ij] = new VertexData(combined, vk);
                                    }
                                }
                                else
                                {
                                    data[ij] = new VertexData(combined, vk);
                                }
                            }
                        }
                    }
                }
            }

            // check negative cycles
            foreach (var vi in vertices)
            {
                var        ii = new SEquatableEdge <TVertex>(vi, vi);
                VertexData value;
                if (data.TryGetValue(ii, out value) &&
                    value.Distance < 0)
                {
                    throw new NegativeCycleGraphException();
                }
            }
        }
Beispiel #26
0
        /// <summary>
        /// Edits the items in the database.
        /// </summary>
        /// <param name="serviceProvider">The application service provider.</param>
        /// <param name="token">The cancellation token for the task.</param>
        public async Task EditAsync(IServiceProvider serviceProvider, CancellationToken token)
        {
            // Check if there weren't any valid items found.
            if (Items == null)
            {
                // Throw an exception.
                throw new TaskException("No valid items could be found with the provided data.");
            }
            // Check if the exception item should be shown.
            var showExceptionItem = Items.Count() > 1;
            // Get the total number of batches.
            var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize);

            // Go over each batch.
            for (var index = 0; index < count; index++)
            {
                // Check if the cancellation was requested.
                if (token.IsCancellationRequested)
                {
                    // Break.
                    break;
                }
                // Get the items in the current batch.
                var batchItems = Items
                                 .Skip(index * ApplicationDbContext.BatchSize)
                                 .Take(ApplicationDbContext.BatchSize);
                // Get the IDs of the items in the current batch.
                var batchIds = batchItems
                               .Where(item => !string.IsNullOrEmpty(item.Id))
                               .Select(item => item.Id);
                // Get the IDs of the related entities that appear in the current batch.
                var batchDatabaseIds = batchItems
                                       .Where(item => item.DatabaseEdges != null)
                                       .Select(item => item.DatabaseEdges)
                                       .SelectMany(item => item)
                                       .Where(item => item.Database != null)
                                       .Select(item => item.Database)
                                       .Where(item => !string.IsNullOrEmpty(item.Id))
                                       .Select(item => item.Id)
                                       .Distinct();
                var batchDatabaseEdgeFieldIds = batchItems
                                                .Where(item => item.DatabaseEdgeFieldEdges != null)
                                                .Select(item => item.DatabaseEdgeFieldEdges)
                                                .SelectMany(item => item)
                                                .Where(item => item.DatabaseEdgeField != null)
                                                .Select(item => item.DatabaseEdgeField)
                                                .Where(item => !string.IsNullOrEmpty(item.Id))
                                                .Select(item => item.Id)
                                                .Distinct();
                var batchNodeIds = batchItems
                                   .Where(item => item.EdgeNodes != null)
                                   .Select(item => item.EdgeNodes)
                                   .SelectMany(item => item)
                                   .Where(item => item.Node != null)
                                   .Select(item => item.Node)
                                   .Where(item => !string.IsNullOrEmpty(item.Id))
                                   .Select(item => item.Id)
                                   .Distinct();
                // Define the list of items to get.
                var edges              = new List <Edge>();
                var databases          = new List <Database>();
                var databaseEdgeFields = new List <DatabaseEdgeField>();
                var nodes              = new List <Node>();
                // Use a new scope.
                using (var scope = serviceProvider.CreateScope())
                {
                    // Use a new context instance.
                    using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>();
                    // Get the items with the provided IDs.
                    var items = context.Edges
                                .Where(item => !item.DatabaseEdges.Any(item1 => item1.Database.DatabaseType.Name == "Generic"))
                                .Where(item => batchIds.Contains(item.Id));
                    // Check if there were no items found.
                    if (items == null || !items.Any())
                    {
                        // Continue.
                        continue;
                    }
                    // Get the items found.
                    edges = items
                            .ToList();
                    // Get the related entities that appear in the current batch.
                    databaseEdgeFields = context.DatabaseEdgeFields
                                         .Where(item => item.Database.DatabaseType.Name != "Generic")
                                         .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id))
                                         .ToList();
                    databases = context.Databases
                                .Where(item => item.DatabaseType.Name != "Generic")
                                .Where(item => batchDatabaseIds.Contains(item.Id))
                                .Concat(context.DatabaseEdgeFields
                                        .Where(item => item.Database.DatabaseType.Name != "Generic")
                                        .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id))
                                        .Select(item => item.Database))
                                .Distinct()
                                .ToList();
                    nodes = context.Nodes
                            .Where(item => !item.DatabaseNodes.Any(item1 => item1.Database.DatabaseType.Name == "Generic"))
                            .Where(item => batchNodeIds.Contains(item.Id))
                            .ToList();
                }
                // Get the IDs of the items.
                var edgeIds = edges
                              .Select(item => item.Id);
                // Save the items to edit.
                var edgesToEdit = new List <Edge>();
                // Go over each of the valid items.
                foreach (var batchItem in batchItems)
                {
                    // Get the corresponding item.
                    var edge = edges
                               .FirstOrDefault(item => batchItem.Id == item.Id);
                    // Check if there was no item found.
                    if (edge == null)
                    {
                        // Continue.
                        continue;
                    }
                    // Check if there were no edge nodes provided.
                    if (batchItem.EdgeNodes == null || !batchItem.EdgeNodes.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no edge nodes provided.", showExceptionItem, batchItem);
                    }
                    // Get the edge nodes.
                    var edgeNodes = batchItem.EdgeNodes
                                    .Where(item => item.Node != null)
                                    .Where(item => !string.IsNullOrEmpty(item.Node.Id))
                                    .Where(item => item.Type == "Source" || item.Type == "Target")
                                    .Select(item => (item.Node.Id, item.Type))
                                    .Distinct()
                                    .Where(item => nodes.Any(item1 => item1.Id == item.Item1))
                                    .Select(item => new EdgeNode
                    {
                        NodeId = item.Item1,
                        Type   = EnumerationExtensions.GetEnumerationValue <EdgeNodeType>(item.Item2)
                    });
                    // Check if there were no edge nodes found.
                    if (edgeNodes == null || !edgeNodes.Any(item => item.Type == EdgeNodeType.Source) || !edgeNodes.Any(item => item.Type == EdgeNodeType.Target))
                    {
                        // Throw an exception.
                        throw new TaskException("There were no edge nodes found.", showExceptionItem, batchItem);
                    }
                    // Check if there were no database edges or database edge field edges provided.
                    if ((batchItem.DatabaseEdges == null || !batchItem.DatabaseEdges.Any()) && (batchItem.DatabaseEdgeFieldEdges == null || !batchItem.DatabaseEdgeFieldEdges.Any()))
                    {
                        // Throw an exception.
                        throw new TaskException("There were no database edges or database edge field edges provided.", showExceptionItem, batchItem);
                    }
                    // Get the database edge field edges.
                    var databaseEdgeFieldEdges = batchItem.DatabaseEdgeFieldEdges != null?
                                                 batchItem.DatabaseEdgeFieldEdges
                                                 .Where(item => item.DatabaseEdgeField != null)
                                                 .Where(item => !string.IsNullOrEmpty(item.DatabaseEdgeField.Id))
                                                 .Where(item => !string.IsNullOrEmpty(item.Value))
                                                 .Select(item => (item.DatabaseEdgeField.Id, item.Value))
                                                 .Distinct()
                                                 .Where(item => databaseEdgeFields.Any(item1 => item1.Id == item.Item1))
                                                 .Select(item => new DatabaseEdgeFieldEdge
                    {
                        DatabaseEdgeFieldId = item.Item1,
                        Value = item.Item2
                    }) :
                                                     Enumerable.Empty <DatabaseEdgeFieldEdge>();

                    // Get the database edges.
                    var databaseEdgeFieldIds = databaseEdgeFieldEdges
                                               .Select(item => item.DatabaseEdgeFieldId)
                                               .Distinct();
                    var currentDatabaseEdgeFields = databaseEdgeFields
                                                    .Where(item => databaseEdgeFieldIds.Contains(item.Id));
                    var databaseEdges = batchItem.DatabaseEdges != null?
                                        batchItem.DatabaseEdges
                                        .Where(item => item.Database != null)
                                        .Where(item => !string.IsNullOrEmpty(item.Database.Id))
                                        .Select(item => item.Database.Id)
                                        .Concat(currentDatabaseEdgeFields
                                                .Select(item => item.Database.Id))
                                        .Distinct()
                                        .Where(item => databases.Any(item1 => item1.Id == item))
                                        .Select(item => new DatabaseEdge
                    {
                        DatabaseId = item,
                    }) :
                                            Enumerable.Empty <DatabaseEdge>();

                    // Check if there were no database edges found.
                    if (databaseEdges == null || !databaseEdges.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no database edges found.", showExceptionItem, batchItem);
                    }
                    // Update the edge.
                    edge.Name        = string.Concat(nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Source).NodeId).Name, " - ", nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Target).NodeId).Name);
                    edge.Description = batchItem.Description;
                    edge.EdgeNodes   = new List <EdgeNode>
                    {
                        edgeNodes.First(item => item.Type == EdgeNodeType.Source),
                        edgeNodes.First(item => item.Type == EdgeNodeType.Target)
                    };
                    edge.DatabaseEdgeFieldEdges = databaseEdgeFieldEdges.ToList();
                    edge.DatabaseEdges          = databaseEdges.ToList();
                    // Add the edge to the list.
                    edgesToEdit.Add(edge);
                }
                // Delete the dependent entities.
                await EdgeExtensions.DeleteDependentAnalysesAsync(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteDependentNetworksAsync(edgeIds, serviceProvider, token);

                // Delete the related entities.
                await EdgeExtensions.DeleteRelatedEntitiesAsync <EdgeNode>(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdgeFieldEdge>(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdge>(edgeIds, serviceProvider, token);

                // Update the items.
                await IEnumerableExtensions.EditAsync(edgesToEdit, serviceProvider, token);
            }
        }
Beispiel #27
0
        /// <summary>
        /// Deletes the items from the database.
        /// </summary>
        /// <param name="serviceProvider">The application service provider.</param>
        /// <param name="token">The cancellation token for the task.</param>
        public async Task DeleteAsync(IServiceProvider serviceProvider, CancellationToken token)
        {
            // Check if there weren't any valid items found.
            if (Items == null)
            {
                // Throw an exception.
                throw new TaskException("No valid items could be found with the provided data.");
            }
            // Get the total number of batches.
            var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize);

            // Go over each batch.
            for (var index = 0; index < count; index++)
            {
                // Check if the cancellation was requested.
                if (token.IsCancellationRequested)
                {
                    // Break.
                    break;
                }
                // Get the items in the current batch.
                var batchItems = Items
                                 .Skip(index * ApplicationDbContext.BatchSize)
                                 .Take(ApplicationDbContext.BatchSize);
                // Get the IDs of the items in the current batch.
                var batchIds = batchItems.Select(item => item.Id);
                // Define the list of items to get.
                var edges = new List <Edge>();
                // Use a new scope.
                using (var scope = serviceProvider.CreateScope())
                {
                    // Use a new context instance.
                    using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>();
                    // Get the items with the provided IDs.
                    var items = context.Edges
                                .Where(item => batchIds.Contains(item.Id));
                    // Check if there were no items found.
                    if (items == null || !items.Any())
                    {
                        // Continue.
                        continue;
                    }
                    // Get the items found.
                    edges = items
                            .ToList();
                }
                // Get the IDs of the items.
                var edgeIds = edges
                              .Select(item => item.Id);
                // Delete the dependent entities.
                await EdgeExtensions.DeleteDependentAnalysesAsync(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteDependentNetworksAsync(edgeIds, serviceProvider, token);

                // Delete the related entities.
                await EdgeExtensions.DeleteRelatedEntitiesAsync <EdgeNode>(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdgeFieldEdge>(edgeIds, serviceProvider, token);

                await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdge>(edgeIds, serviceProvider, token);

                // Delete the items.
                await IEnumerableExtensions.DeleteAsync(edges, serviceProvider, token);
            }
        }