Example #1
0
        private int CommonPredecessorOfSourceAndTargetOfF(NetworkEdge f)
        {
            //find the common predecessor of f.Source and f.Target
            int fMin, fmax;

            if (lim[f.Source] < lim[f.Target])
            {
                fMin = lim[f.Source];
                fmax = lim[f.Target];
            }
            else
            {
                fMin = lim[f.Target];
                fmax = lim[f.Source];
            }
            //it is the best to walk up from the highest of nodes f
            //but we don't know the depths
            //so just start walking up from the source
            int l = f.Source;


            while ((low[l] <= fMin && fmax <= lim[l]) == false)
            {
                NetworkEdge p = parent[l];

                p.Cut = NetworkEdge.Infinity;

                l = p.Source == l ? p.Target : p.Source;
            }
            return(l);
        }
Example #2
0
        /// <summary>
        /// treeEdge, belonging to the tree, divides the vertices to source and target components
        /// e does not belong to the tree . If e goes from the source component to target component
        /// then the return value is 1,
        /// if e goes from the target component ot the source then the return value is -1
        /// otherwise it is zero
        /// </summary>
        /// <param name="e">a non-tree edge</param>
        /// <param name="treeEdge">a tree edge</param>
        /// <returns></returns>
        int EdgeSourceTargetVal(NetworkEdge e, NetworkEdge treeEdge)
        {
            // if (e.inTree || treeEdge.inTree == false)
            // throw new Exception("wrong params for EdgeSOurceTargetVal");

            return(VertexSourceTargetVal(e.Source, treeEdge) - VertexSourceTargetVal(e.Target, treeEdge));
        }
Example #3
0
        /// <summary>
        /// treeEdge, belonging to the tree, divides the vertices to source and target components
        /// If v belongs to the source component we return 1 oterwise we return 0
        /// </summary>
        /// <param name="v">a v</param>
        /// <param name="treeEdge">a vertex</param>
        /// <returns>an edge from the tree</returns>
        int VertexSourceTargetVal(int v, NetworkEdge treeEdge)
        {
#if DEBUGNW
            if (treeEdge.inTree == false)
            {
                throw new Exception("wrong params for VertexSourceTargetVal");
            }
#endif

            int s = treeEdge.Source;
            int t = treeEdge.Target;
            if (lim[s] > lim[t])//s belongs to the tree root component
            {
                if (lim[v] <= lim[t] && low[t] <= lim[v])
                {
                    return(0);
                }
                else
                {
                    return(1);
                }
            }
            else //t belongs to the tree root component
            if (lim[v] <= lim[s] && low[s] <= lim[v])
            {
                return(1);
            }
            else
            {
                return(0);
            }
        }
Example #4
0
        /// <summary>
        /// If f = (w,x) is the entering edge, the
        /// only edges whose cut values must be adjusted are those in the path
        /// connecting w and x in the tree, excluding e. This path is determined by
        /// following the parent edges back from w and x until the least common ancestor is
        /// reached, i.e., the first node l such that low(l) less or equal lim(w) ,lim(x) less or equal lim(l).
        /// Of course, these postorder parameters must also be adjusted when
        /// exchanging tree edges, but only for nodes below l.
        /// </summary>
        /// <param name="e">exiting edge</param>
        /// <param name="f">entering edge</param>
        void Exchange(NetworkEdge e, NetworkEdge f)
        {
            int l = CommonPredecessorOfSourceAndTargetOfF(f);

            CreatePathForCutUpdates(e, f, l);
            UpdateLimLowLeavesAndParentsUnderNode(l);

            UpdateCuts(e);

            UpdateLayersUnderNode(l);
        }
Example #5
0
        ///// <summary>
        ///// LeaveEnterEdge finds a non-tree edge to replace e.
        ///// This is done by breaking the edge e, which divides
        ///// the tree into the source and the target componentx.
        ///// All edges going from the source component to the
        ///// target are considered, with an edge of minimum
        ///// slack being chosen. This is necessary to maintain feasibility.
        ///// </summary>
        ///// <param name="leavingEdge">a leaving edge</param>
        ///// <param name="enteringEdge">an entering edge</param>
        ///// <returns>returns true if a pair is chosen</returns>
        Tuple <NetworkEdge, NetworkEdge> LeaveEnterEdge()
        {
            NetworkEdge leavingEdge  = null;
            NetworkEdge enteringEdge = null; //to keep the compiler happy
            int         minCut       = 0;

            foreach (NetworkEdge e in graph.Edges)
            {
                if (e.inTree)
                {
                    if (e.Cut < minCut)
                    {
                        minCut      = e.Cut;
                        leavingEdge = e;
                    }
                }
            }

            if (leavingEdge == null)
            {
                return(null);
            }

            //now we are looking for a non-tree edge with a minimal slack belonging to TS
            bool continuation = false;
            int  minSlack     = NetworkEdge.Infinity;

            foreach (NetworkEdge f in graph.Edges)
            {
                int slack = Slack(f);
                if (f.inTree == false && EdgeSourceTargetVal(f, leavingEdge) == -1 &&
                    (slack < minSlack || (slack == minSlack && (continuation = (random.Next(2) == 1))))
                    )
                {
                    minSlack     = slack;
                    enteringEdge = f;
                    if (minSlack == 0 && !continuation)
                    {
                        break;
                    }
                    continuation = false;
                }
            }

#if TEST_MSAGL
            if (enteringEdge == null)
            {
                throw new InvalidOperationException();
            }
#endif
            return(new Tuple <NetworkEdge, NetworkEdge>(leavingEdge, enteringEdge));
        }
Example #6
0
        private void CreatePathForCutUpdates(NetworkEdge e, NetworkEdge f, int l)
        {
            //we mark the path by setting the cut value to infinity

            int v = f.Target;

            while (v != l)
            {
                NetworkEdge p = parent[v];
                p.Cut = NetworkEdge.Infinity;
                v     = p.Source == v ? p.Target : p.Source;
            }

            f.Cut = NetworkEdge.Infinity; //have to do it because f will be in the path between end points of e in the new tree

            //remove e from the tree and put f inside of it
            e.inTree = false; f.inTree = true;
        }
Example #7
0
        /// <summary>
        /// e is a tree edge for which the cut has been calculted already.
        /// EdgeContribution gives an amount that edge e brings to the cut of parent[w].
        /// The contribution is the cut value minus the weight of e. Let S be the component of e source.
        /// We should also substruct W(ie) for every ie going from S to w and add W(ie) going from w to S.
        /// These numbers appear in e.Cut but with opposite signs.
        /// </summary>
        /// <param name="e">tree edge</param>
        /// <param name="w">parent[w] is in the process of the cut calculation</param>
        /// <returns></returns>
        int EdgeContribution(NetworkEdge e, int w)
        {
            int ret = e.Cut - e.Weight;

            foreach (NetworkEdge ie in IncidentEdges(w))
            {
                if (ie.inTree == false)
                {
                    int sign = EdgeSourceTargetVal(ie, e);
                    if (sign == -1)
                    {
                        ret += ie.Weight;
                    }
                    else if (sign == 1)
                    {
                        ret -= ie.Weight;
                    }
                }
            }
            return(ret);
        }
Example #8
0
        private void UpdateCuts(NetworkEdge e)
        {
            //going up from the leaves of the branch following parents
            Stack <int> front    = new Stack <int>();
            Stack <int> newFront = new Stack <int>();


            //We start cut updates from the vertices of e. It will work only if in the new tree
            // the  parents of the vertices of e are end edges on the path connecting the two vertices.
            //Let  e be (w,x) and let f be (u,v). Let T be the tree containing e but no f,
            //and T0 be the tree without with e but containg f. Let us consider the path with no edge repetitions from u to v in T.
            //It has to contain e since there is a path from u to v in T containing e, because v lies in the component of w in T
            //and u lies in the component of x in T, if there is a path without e then we have a cycle in T.
            // Now if we romove e from this path and add f to it we get a path without edge repetitions connecting w to x.
            // The edge adjacent in this path to w is parent[w] in T0, and the edge of the path adjacent to x is
            //parent[x] in T0. If it is not true then we can get a cycle by constructing another path from w to x going up through the
            //parents to the common ancessor of w and x.

            front.Push(e.Source);
            front.Push(e.Target);

            while (front.Count > 0)
            {
                while (front.Count > 0)
                {
                    int w = front.Pop();

                    ProgressStep();
                    NetworkEdge cutEdge = parent[w]; //have to find the cut of cutEdge

                    if (cutEdge == null)
                    {
                        continue;
                    }

                    if (cutEdge.Cut != NetworkEdge.Infinity)
                    {
                        continue; //the value of this cut has not been changed
                    }
                    int cut = 0;
                    foreach (NetworkEdge ce in IncidentEdges(w))
                    {
                        if (ce.inTree == false)
                        {
                            int e0Val = EdgeSourceTargetVal(ce, cutEdge);
                            if (e0Val != 0)
                            {
                                cut += e0Val * ce.Weight;
                            }
                        }
                        else   //e0 is a tree edge
                        {
                            if (ce == cutEdge)
                            {
                                cut += ce.Weight;
                            }
                            else
                            {
                                int impact           = cutEdge.Source == ce.Target || cutEdge.Target == ce.Source ? 1 : -1;
                                int edgeContribution = EdgeContribution(ce, w);
                                cut += edgeContribution * impact;
                            }
                        }
                    }

                    cutEdge.Cut = cut;
                    int u = cutEdge.Source == w ? cutEdge.Target : cutEdge.Source;
                    if (AllLowCutsHaveBeenDone(u))
                    {
                        newFront.Push(u);
                    }
                }
                //swap newFrontAndFront
                Stack <int> t = front;
                front    = newFront;
                newFront = t;
            }
        }
Example #9
0
        /// <summary>
        /// initializes lim and low in the subtree
        /// </summary>
        /// <param name="curLim">the root of the subtree</param>
        /// <param name="v">the low[v]</param>
        private void InitLowLimParentAndLeavesOnSubtree(int curLim, int v)
        {
            Stack <StackStruct> stack   = new Stack <StackStruct>();
            IEnumerator         outEnum = this.graph.OutEdges(v).GetEnumerator();
            IEnumerator         inEnum  = this.graph.InEdges(v).GetEnumerator();

            stack.Push(new StackStruct(v, outEnum, inEnum));//vroot is 0 here
            low[v] = curLim;

            while (stack.Count > 0)
            {
                StackStruct ss = stack.Pop();
                v       = ss.v;
                outEnum = ss.outEnum;
                inEnum  = ss.inEnum;

                //for sure we will have a descendant with the lowest number curLim since curLim may only grow
                //from the current value

                ProgressStep();
                bool done;
                do
                {
                    done = true;
                    while (outEnum.MoveNext())
                    {
                        NetworkEdge e = outEnum.Current as NetworkEdge;
                        if (!e.inTree || low[e.Target] > 0)
                        {
                            continue;
                        }
                        stack.Push(new StackStruct(v, outEnum, inEnum));
                        v         = e.Target;
                        parent[v] = e;
                        low[v]    = curLim;
                        outEnum   = this.graph.OutEdges(v).GetEnumerator();
                        inEnum    = this.graph.InEdges(v).GetEnumerator();
                    }
                    while (inEnum.MoveNext())
                    {
                        NetworkEdge e = inEnum.Current as NetworkEdge;
                        if (!e.inTree || low[e.Source] > 0)
                        {
                            continue;
                        }
                        stack.Push(new StackStruct(v, outEnum, inEnum));
                        v         = e.Source;
                        low[v]    = curLim;
                        parent[v] = e;
                        outEnum   = this.graph.OutEdges(v).GetEnumerator();
                        inEnum    = this.graph.InEdges(v).GetEnumerator();
                        done      = false;
                        break;
                    }
                } while (!done);

                //finally done with v
                lim[v] = curLim++;
                if (lim[v] == low[v])
                {
                    leaves.Add(v);
                }
            }
        }
Example #10
0
        /// <summary>
        /// The init_cutvalues function computes the cut values of the tree edges.
        /// For each tree edge, this is computed by marking the nodes as belonging to the source or
        /// target component, and then performing the sum of the signed weights of all
        /// edges whose source and target are in different components, the sign being negative for those edges
        /// going from the source to the target component.
        /// To reduce this cost, we note that the cut values can be computed using information local to an edge
        /// if the search is ordered from the leaves of the feasible tree inward. It is trivial to compute the
        /// cut value of a tree edge with one of its endpoints a leaf in the tree,
        /// since either the source or the target component consists of a single node.
        /// Now, assuming the cut values are known for all the edges incident on a given
        /// node except one, the cut value of the remaining edge is the sum of the known cut
        /// values plus a term dependent only on the edges incident to the given node.
        /// </summary>
        void InitCutValues()
        {
            InitLimLowAndParent();

            //going up from the leaves following parents
            Stack <int> front = new Stack <int>();

            foreach (int i in leaves)
            {
                front.Push(i);
            }
            Stack <int> newFront = new Stack <int>();

            while (front.Count > 0)
            {
                while (front.Count > 0)
                {
                    int         w       = front.Pop();
                    NetworkEdge cutEdge = parent[w]; //have to find the cut of e
                    if (cutEdge == null)
                    {
                        continue;
                    }
                    int cut = 0;
                    foreach (NetworkEdge e in IncidentEdges(w))
                    {
                        if (e.inTree == false)
                        {
                            int e0Val = EdgeSourceTargetVal(e, cutEdge);
                            if (e0Val != 0)
                            {
                                cut += e0Val * e.Weight;
                            }
                        }
                        else   //e0 is a tree edge
                        {
                            if (e == cutEdge)
                            {
                                cut += e.Weight;
                            }
                            else
                            {
                                int impact           = cutEdge.Source == e.Target || cutEdge.Target == e.Source ? 1 : -1;
                                int edgeContribution = EdgeContribution(e, w);
                                cut += edgeContribution * impact;
                            }
                        }
                    }

                    cutEdge.Cut = cut;
                    int v = cutEdge.Source == w ? cutEdge.Target : cutEdge.Source;
                    if (AllLowCutsHaveBeenDone(v))
                    {
                        newFront.Push(v);
                    }
                }
                //swap newFrontAndFront
                Stack <int> t = front;
                front    = newFront;
                newFront = t;
            }
        }