//returns the new node containing B, plus a marker vertex representing A(while the old node is transformed into the A part) private DegenerateNode SplitNode(DegenerateNode node, System.Collections.Generic.HashSet<MarkerVertex> A, System.Collections.Generic.HashSet<MarkerVertex> B) { //XXX A set here is not necessary... //since node must be degenerate(otherwise not splittable due to the definition of prime node), there's an easy way to build frontiers: //see paper notes. //assume the original node contains A part, now we remove the B part node.RemoveMarkerVertices(B); var v1 = new MarkerVertex(); var v2 = new MarkerVertex(); DegenerateNode newNode = new DegenerateNode() { Vu = new List<MarkerVertex>(B), }; if (node.isStar)//address the center issue { if (A.Contains(node.center)) { //node center doesn't change newNode.center = v2; } else { newNode.center = node.center; node.center = v1; } } node.Vu.Add(v1); newNode.Vu.Add(v2); v1.opposite = v2; v2.opposite = v1; if (B.Contains(node.rootMarkerVertex))//B is being splitted out, if B has the root marker vertex, newNode should point to the original parent { newNode.rootMarkerVertex = node.rootMarkerVertex; newNode.parent = node.parent; newNode.rootMarkerVertex.node = newNode; node.rootMarkerVertex = v1; v1.node = node; //before assigning parent, check if a clone is necessary if (node.parent is PrimeNode) { var cloned = node.Clone(); node = cloned as DegenerateNode;//thus the old node deprecated } node.parent = newNode; } else//A has root marker vertex, thus old parent unchanged. { newNode.rootMarkerVertex = v2; newNode.parent = node; v2.node = newNode; } //update the parent links of the children in the new node newNode.ForEachChild((v) => { v.parent = newNode; return IterationFlag.Continue; }, subtree: false); return newNode; }
private void VertexInsertion(SplitTree ST, List<int> sigma, int idx) { #region Bootstrapping if (ST.vertices.Count == 0)//initialization { Leaf v = new Leaf { id = sigma[idx], parent = null, }; ST.AddLeaf(v); ST.root = v; } else if (ST.vertices.Count == 1)//only the root, thus we cache the second vertex { Leaf v = new Leaf { id = sigma[idx], parent = null, }; ST.AddLeaf(v); } else if (ST.vertices.Count == 2)//now we're building the first trinity { Leaf v = new Leaf { id = sigma[idx], parent = null }; ST.AddLeaf(v); int missingConnection = -1; //test the missing connection between the cached 3 leave if (!storage[(ST.vertices[0] as Leaf).id].Contains((ST.vertices[1] as Leaf).id)) { missingConnection = 0; } else if (!storage[(ST.vertices[0] as Leaf).id].Contains((ST.vertices[2] as Leaf).id)) { missingConnection = 1; } else if (!storage[(ST.vertices[1] as Leaf).id].Contains((ST.vertices[2] as Leaf).id)) { missingConnection = 2; } MarkerVertex v1 = new MarkerVertex() { opposite = ST.vertices[0] }; MarkerVertex v2 = new MarkerVertex() { opposite = ST.vertices[1] }; MarkerVertex v3 = new MarkerVertex() { opposite = ST.vertices[2] }; (ST.vertices[0] as Leaf).opposite = v1; (ST.vertices[1] as Leaf).opposite = v2; (ST.vertices[2] as Leaf).opposite = v3; MarkerVertex center = null; switch (missingConnection) { case 0: center = v3; break; case 1: center = v2; break; case 2: center = v1; break; default: break; } var deg = new DegenerateNode() { parent = ST.vertices[0], Vu = new List<MarkerVertex> { v1, v2, v3 }, center = center, rootMarkerVertex = v1 }; v1.node = deg; ST.vertices[1].parent = ST.vertices[2].parent = deg; ST.vertices.Add(deg); ST.lastVertex = ST.vertices[2] as Leaf; } #endregion else { TreeEdge e; Vertex u; SplitTree tPrime; var returnType = SplitTree_CaseIdentification(ST, sigma, idx, out e, out u, out tPrime); switch (returnType) { case CaseIdentification_ResultType.SingleLeaf: //This case is not discussed in paper. However, if there's only a single leaf in neighbor set, //then a unique PE edge can be found. //Applying proposition 4.17, case 6 e.u = (u as Leaf).opposite; e.v = u; ST.SplitEdgeToStar(e, sigma[idx]); break; case CaseIdentification_ResultType.TreeEdge://PP or PE { bool unique = true; bool pp; //testing uniqueness, page 24 //check whether pp or pe if (!e.u.Perfect()) { var tmp = e.u; e.u = e.v; e.v = tmp; } pp = e.v.Perfect(); var u_GLT = e.u_GLT; var v_GLT = e.v_GLT; DegenerateNode degNode = null; if (u_GLT is DegenerateNode) degNode = u_GLT as DegenerateNode; if (v_GLT is DegenerateNode) degNode = v_GLT as DegenerateNode; if (degNode != null)//attached to a clique or a star { if ((pp && degNode.isClique) || (!pp/*pe*/ && degNode.isStar && (e.u == degNode.center || degNode.Degree(e.v as MarkerVertex) == 1))) { unique = false; } } if (unique) { //Proposition 4.17 case 5 or 6 if (pp)//PP { ST.SplitEdgeToClique(e, sigma[idx]); } else//PE { ST.SplitEdgeToStar(e, sigma[idx]); } } else { //Proposition 4.15, case 1 or 2 var deg = u_GLT; if (v_GLT is DegenerateNode) deg = v_GLT; ST.AttachToDegenerateNode(deg as DegenerateNode, sigma[idx]); } } break; case CaseIdentification_ResultType.HybridNode: if (u is DegenerateNode) { //Proposition 4.16 var uDeg = u as DegenerateNode; System.Collections.Generic.HashSet<MarkerVertex> PStar = new System.Collections.Generic.HashSet<MarkerVertex>(); System.Collections.Generic.HashSet<MarkerVertex> EStar = new System.Collections.Generic.HashSet<MarkerVertex>(); uDeg.ForEachMarkerVertex((v) => { if (v.perfect && v != uDeg.center) PStar.Add(v); else EStar.Add(v); return IterationFlag.Continue; }); //before we split, determine the new perfect states for the two new markers to be generated bool pp = false; if (uDeg.isStar && uDeg.center.perfect) { pp = true;//see figure 7. pp==true iff star and center is perfect. } var newNode = SplitNode(uDeg, PStar, EStar); ST.vertices.Add(newNode); //e.u \in PStar ; e.v \in EStar (thus containing the original center, if star) //PStar in uDeg; EStar in newNode if (newNode.parent == uDeg) { e.u = newNode.rootMarkerVertex.opposite; e.v = newNode.rootMarkerVertex; } else { e.u = uDeg.rootMarkerVertex; e.v = uDeg.rootMarkerVertex.opposite; } //assign perfect state values if (pp) { e.u.MarkAsPerfect(); e.v.MarkAsPerfect(); } else//PE, and PStar part always has an empty state and EStar part has perfect. { e.u.MarkAsEmpty(); e.v.MarkAsPerfect(); } //check whether pp or pe if (!e.u.Perfect()) { var tmp = e.u; e.u = e.v; e.v = tmp; } if (e.v.Perfect())//PP { ST.SplitEdgeToClique(e, sigma[idx]); } else//PE { ST.SplitEdgeToStar(e, sigma[idx]); } } else { //Proposition 4.15, case 3 ST.AttachToPrimeNode(u as PrimeNode, sigma[idx]); } break; case CaseIdentification_ResultType.FullyMixedSubTree: //Proposition 4.20 Cleaning(ST, tPrime); //ST.Debug(false); var contractionNode = Contraction(ST, tPrime, sigma[idx]); break; } } }
internal override GLTVertex Clone() { DegenerateNode newDegNode = new DegenerateNode() { activeTimestamp = activeTimestamp, center = center, parentLink = parentLink, rootMarkerVertex = rootMarkerVertex, unionFind_parent = unionFind_parent, visitedTimestamp = visitedTimestamp, Vu = Vu, }; rootMarkerVertex.node = newDegNode; ForEachChild((v) => { v.parentLink = newDegNode; v.unionFind_parent = null; return IterationFlag.Continue; }, false); return newDegNode; }
//Proposition 4.15 internal void AttachToDegenerateNode(DegenerateNode deg, int xId) { MarkerVertex v = new MarkerVertex(); Leaf x = new Leaf() { id = xId, opposite = v, parent = deg, }; v.opposite = x; deg.Vu.Add(v);//and done! if clique, all vertices are P, thus fully connecting v. //and if star, v is connected to center, the only perfect marker. AddLeaf(x); }
//Proposition 4.17 internal void SplitEdgeToStar(TreeEdge e, int xId) { //Assume e is P-E GLTVertex oParent = e.u.GetGLTVertex(); GLTVertex oChild = e.v.GetGLTVertex(); bool uIsParent = true; //test and swap if (oChild.parent != oParent) { var tmp = oParent; oParent = oChild; oChild = tmp; uIsParent = false; } ////Fixing multiple-star forking problem //var oChildDeg = oChild as DegenerateNode; //if (oChildDeg != null && oChildDeg.isStar && oChildDeg.center == oChildDeg.rootMarkerVertex) //{ // //note that if child's center is not root, we cannot merge. // AttachToDegenerateNode(oChildDeg, xId); // return; //} MarkerVertex v1 = new MarkerVertex(); MarkerVertex v2 = new MarkerVertex(); MarkerVertex v3 = new MarkerVertex(); //center is E (e.v) => v2 var deg = new DegenerateNode() { active = false, center = v2, parent = oParent, rootMarkerVertex = uIsParent ? v1 : v2, visited = false, Vu = new List<MarkerVertex> { v1, v2, v3 } }; if (uIsParent) v1.node = deg; else v2.node = deg; deg.parent = oParent; if (oParent is PrimeNode == false) { oChild.parent = deg; } else { //(oParent as PrimeNode).ForEachChild(c => // { // if (c.unionFind_parent == oChild) // Console.WriteLine("!!!"); // return IterationFlag.Continue; // }, false); //oChild.parent = deg; var newChild = oChild.Clone();//since oChild is potentially pointed by others' unionFind_parent, we have to clone. if (newChild is Leaf) { LeafMapper[(newChild as Leaf).id] = newChild as Leaf; //a new leaf is cloned. thus e.u / e.v is cloned. check and update. if (e.u is Leaf) e.u = newChild; else e.v = newChild; } newChild.parent = deg; } //linking e.u & e.v to v1 & v2 if (e.u is MarkerVertex) (e.u as MarkerVertex).opposite = v1; else (e.u as Leaf).opposite = v1; if (e.v is MarkerVertex) (e.v as MarkerVertex).opposite = v2; else (e.v as Leaf).opposite = v2; v1.opposite = e.u; v2.opposite = e.v; Leaf x = new Leaf { id = xId, opposite = v3, }; v3.opposite = x; x.parent = deg; //vertices.Add(deg); AddLeaf(x); }