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); }
/// <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)); }
/// <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); } }
/// <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); }
///// <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)); }
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; }
/// <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); }
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; } }
/// <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); } } }
/// <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; } }