private void AddReversedEdges([NotNull, ItemNotNull] IEnumerable <TEdge> notReversedEdges)
        {
            foreach (TEdge edge in notReversedEdges)
            {
                if (ReversedEdges.ContainsKey(edge))
                {
                    continue;
                }

                // Already been added
                if (FindReversedEdge(edge, out TEdge reversedEdge))
                {
                    ReversedEdges[edge] = reversedEdge;
                    continue;
                }

                // Need to create one
                reversedEdge = EdgeFactory(edge.Target, edge.Source);
                if (!VisitedGraph.AddEdge(reversedEdge))
                {
                    throw new InvalidOperationException("Cannot add the reversed edge, this should not arrive...");
                }

                _augmentedEdges.Add(reversedEdge);
                ReversedEdges[edge]         = reversedEdge;
                ReversedEdges[reversedEdge] = edge;

                OnReservedEdgeAdded(reversedEdge);
            }
        }
        /// <summary>
        /// Creates and adds an augmented edge between <paramref name="source"/> and <paramref name="target"/>.
        /// </summary>
        /// <param name="source">Source vertex.</param>
        /// <param name="target">Target vertex.</param>
        protected void AddAugmentedEdge([NotNull] TVertex source, [NotNull] TVertex target)
        {
            Debug.Assert(source != null);
            Debug.Assert(target != null);

            TEdge edge = EdgeFactory(source, target);

            _augmentedEdges.Add(edge);
            VisitedGraph.AddEdge(edge);
            OnEdgeAdded(edge);
        }
        /// <inheritdoc />
        protected override void InternalCompute()
        {
            foreach (DataTable table in DataSet.Tables)
            {
                VisitedGraph.AddVertex(table);
            }

            foreach (DataRelation relation in DataSet.Relations)
            {
                VisitedGraph.AddEdge(new DataRelationEdge(relation));
            }
        }
Example #4
0
        /// <summary>
        /// Creates and adds an augmented edge between <paramref name="source"/> and <paramref name="target"/>.
        /// </summary>
        /// <param name="source">Source vertex.</param>
        /// <param name="target">Target vertex.</param>
        protected void AddAugmentedEdge([NotNull] TVertex source, [NotNull] TVertex target)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            TEdge edge = EdgeFactory(source, target);

            AugmentedEdges.Add(edge);
            VisitedGraph.AddEdge(edge);
            OnEdgeAdded(edge);
        }
        private void GenerateFromTransitionFactory(
            [NotNull] TVertex current,
            [NotNull] ITransitionFactory <TVertex, TEdge> transitionFactory)
        {
            if (current == null)
            {
                throw new ArgumentNullException(nameof(current));
            }
            if (transitionFactory is null)
            {
                throw new ArgumentNullException(nameof(transitionFactory));
            }

            if (!transitionFactory.IsValid(current))
            {
                return;
            }

            foreach (TEdge transition in transitionFactory.Apply(current))
            {
                if (!AddVertexPredicate(transition.Target) ||
                    !AddEdgePredicate(transition))
                {
                    OnEdgeSkipped(transition);
                    continue;
                }

                bool backEdge = VisitedGraph.ContainsVertex(transition.Target);
                if (!backEdge)
                {
                    OnVertexDiscovered(transition.Target);
                }

                VisitedGraph.AddEdge(transition);
                if (backEdge)
                {
                    OnBackEdge(transition);
                }
                else
                {
                    OnTreeEdge(transition);
                }
            }
        }
        private void AddTemporaryEdge(
            TVertex u,
            TVertex v,
            ICollection <TVertex> oddVertices,
            EdgeFactory <TVertex, TEdge> edgeFactory)
        {
            TEdge tempEdge = edgeFactory(u, v);

            if (!VisitedGraph.AddEdge(tempEdge))
            {
                throw new InvalidOperationException("Cannot add temporary edge.");
            }

            // Add to temporary edges
            _temporaryEdges.Add(tempEdge);

            // Remove u,v from oddVertices
            oddVertices.Remove(u);
            oddVertices.Remove(v);
        }
Example #7
0
        private void AddTemporaryEdge(
            [NotNull] TVertex u,
            [NotNull] TVertex v,
            [NotNull, ItemNotNull] List <TVertex> oddVertices,
            [NotNull, InstantHandle] EdgeFactory <TVertex, TEdge> edgeFactory)
        {
            TEdge tempEdge = edgeFactory(u, v);

            if (!VisitedGraph.AddEdge(tempEdge))
            {
                throw new InvalidOperationException();
            }

            // Add to temporary edges
            _temporaryEdges.Add(tempEdge);

            // Remove u,v from oddVertices
            oddVertices.Remove(u);
            oddVertices.Remove(v);
        }
        /// <summary>
        /// Runs the graph balancing algorithm.
        /// </summary>
        /// <exception cref="InvalidOperationException">If the graph is already balanced.</exception>
        public void Balance()
        {
            if (Balanced)
            {
                throw new InvalidOperationException("Graph already balanced.");
            }

            // Step 0
            // Create new balancing source and sink
            BalancingSource = VertexFactory();
            VisitedGraph.AddVertex(BalancingSource);
            OnBalancingSourceAdded();

            BalancingSink = VertexFactory();
            VisitedGraph.AddVertex(BalancingSink);
            OnBalancingSinkAdded();

            // Step 1
            // Link balancing source to the flow source
            BalancingSourceEdge = EdgeFactory(BalancingSource, Source);
            VisitedGraph.AddEdge(BalancingSourceEdge);
            Capacities.Add(BalancingSourceEdge, double.MaxValue);
            _preFlow.Add(BalancingSourceEdge, 0);
            OnEdgeAdded(BalancingSourceEdge);

            // Link the flow sink to the balancing sink
            BalancingSinkEdge = EdgeFactory(Sink, BalancingSink);
            VisitedGraph.AddEdge(BalancingSinkEdge);
            Capacities.Add(BalancingSinkEdge, double.MaxValue);
            _preFlow.Add(BalancingSinkEdge, 0);
            OnEdgeAdded(BalancingSinkEdge);

            // Step 2
            // For each surplus vertex v, add (source -> v)
            foreach (TVertex vertex in VisitedGraph.Vertices.Where(v => !IsSourceOrSink(v)))
            {
                int balancingIndex = GetBalancingIndex(vertex);
                if (balancingIndex == 0)
                {
                    continue;
                }

                if (balancingIndex < 0)
                {
                    // Surplus vertex
                    TEdge edge = EdgeFactory(BalancingSource, vertex);
                    VisitedGraph.AddEdge(edge);

                    _surplusEdges.Add(edge);
                    _surplusVertices.Add(vertex);

                    _preFlow.Add(edge, 0);

                    Capacities.Add(edge, -balancingIndex);

                    OnSurplusVertexAdded(vertex);
                    OnEdgeAdded(edge);
                }
                else
                {
                    // Deficient vertex
                    TEdge edge = EdgeFactory(vertex, BalancingSink);

                    _deficientEdges.Add(edge);
                    _deficientVertices.Add(vertex);

                    _preFlow.Add(edge, 0);

                    Capacities.Add(edge, balancingIndex);

                    OnDeficientVertexAdded(vertex);
                    OnEdgeAdded(edge);
                }
            }

            Balanced = true;

            #region Local function

            bool IsSourceOrSink(TVertex v)
            {
                return(v.Equals(BalancingSource) ||
                       v.Equals(BalancingSink) ||
                       v.Equals(Source) ||
                       v.Equals(Sink));
            }

            #endregion
        }