//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;
        }
Example #2
0
 public override void ForEachNeighbor(MarkerVertex source, Func<MarkerVertex, IterationFlag> action)
 {
     //iterate
     foreach (var v in Gu[source])
     {
         if (action(v) == IterationFlag.Break)
             break;
     }
 }
 public override int Degree(MarkerVertex v)
 {
     if (!Vu.Contains(v))
         return 0;
     if (isStar)
     {
         return (v == center) ? Vu.Count - 1 : 1;
     }
     return Vu.Count - 1;
 }
 public override void ForEachNeighbor(MarkerVertex source, Func<MarkerVertex, IterationFlag> action)
 {
     if (center == null || source == center)
     {
         foreach (var v in Vu)
         {
             if (v == source)
                 continue;
             if (action(v) == IterationFlag.Break)
                 break;
         }
     }
     else
     {
         action(center);
     }
 }
Example #5
0
        //the parameter: the new marker vertex, and a list of its neighbors
        internal void AddMarkerVertex(MarkerVertex u, HashSet<MarkerVertex> neighbors)
        {
            int newUniversalCount = Gu.Count;
            universalMarkerVetex = null;//re-calculate
            foreach (var v in neighbors)
            {
                HashSet<MarkerVertex> set = null;
                if (Gu.TryGetValue(v, out set))
                {
                    set.Add(u);
                    if (set.Count == newUniversalCount)
                        universalMarkerVetex = v;
                }
            }
            Gu[u] = neighbors;

            if (neighbors.Count == newUniversalCount)
                universalMarkerVetex = u;
        }
 public void ComputeStates(out List<MarkerVertex> P, out List<MarkerVertex> M, out List<MarkerVertex> E, MarkerVertex exclude = null, bool excludeRootMarkerVertex = false)
 {
     if (statesUpdateTimestamp != MarkerVertex.perfectTime || exclude != _historyExclude || _historyExcludeRootMarkerVertex != excludeRootMarkerVertex)
     {
         _P = new List<MarkerVertex>();
         _M = new List<MarkerVertex>();
         _E = new List<MarkerVertex>();
         ForEachMarkerVertex((v) =>
             {
                 if (v == exclude)
                     return IterationFlag.Continue;
                 if (v == rootMarkerVertex && excludeRootMarkerVertex)
                     return IterationFlag.Continue;
                 var s = ComputeState(v);
                 switch (s)
                 {
                     case State.Empty:
                         _E.Add(v);
                         break;
                     case State.Mixed:
                         _M.Add(v);
                         break;
                     case State.Perfect:
                         _P.Add(v);
                         break;
                 }
                 return IterationFlag.Continue;
             });
         statesUpdateTimestamp = MarkerVertex.perfectTime;
         _historyExclude = exclude;
         _historyExcludeRootMarkerVertex = excludeRootMarkerVertex;
     }
     P = _P;
     M = _M;
     E = _E;
 }
 private State ComputeState(MarkerVertex v)
 {
     if (v.perfect)
         return State.Perfect;//v.perfect means we will meet a perfect descendant subtree in the opposite.
     var oppositeGLTVertex = GetOppositeGLTVertex(v);
     if (oppositeGLTVertex.visited == false)
         return State.Empty;
     //v is empty iff opposite is not visited
     if (oppositeGLTVertex is Leaf)
     {
         if ((oppositeGLTVertex as Leaf).neighbor)
             return State.Perfect;
         else return State.Empty;
     }
     //from now on we assert v is NE
     State state = State.Perfect;
     _neighbors.Clear();
     var oppositeNode = (oppositeGLTVertex as Node);
     (oppositeNode).ForEachNeighbor(v.opposite as MarkerVertex, (u) =>
         {
             _neighbors.Add(u);
             return IterationFlag.Continue;
         });
     (oppositeNode).ForEachMarkerVertex((u) =>
         {
             if (u == v.opposite)
                 return IterationFlag.Continue;
             if (_neighbors.Contains(u))
             {
                 if (oppositeNode.ComputeState(u) != State.Perfect)
                 {
                     state = State.Mixed;
                     return IterationFlag.Break;
                 }
             }
             else
             {
                 if (oppositeNode.ComputeState(u) != State.Empty)
                 {
                     state = State.Mixed;
                     return IterationFlag.Break;
                 }
             }
             return IterationFlag.Continue;
         });
     //since the graph is connected, we can assert state != null here
     if (state == State.Perfect)
         v.perfect = true;
     return state;
 }
 public GLTVertex GetOppositeGLTVertex(MarkerVertex v)
 {
     if (v == rootMarkerVertex)
         return parent;
     return v.GetOppositeGLTVertex();
 }
 /// <summary>
 /// Iterate through all neighbors of a marker vertex, in the label graph of the current node
 /// </summary>
 public virtual void ForEachNeighbor(MarkerVertex source, Func<MarkerVertex, IterationFlag> action)
 {
     throw new Exception();
 }
Example #10
0
 public override int Degree(MarkerVertex v)
 {
     return Gu[v].Count;
 }
Example #11
0
 //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);
 }
Example #12
0
        //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);
        }
Example #13
0
 //Proposition 4.15
 internal void AttachToPrimeNode(PrimeNode primeNode, int xId)
 {
     MarkerVertex v = new MarkerVertex();
     Leaf x = new Leaf()
     {
         id = xId,
         opposite = v,
         parent = primeNode,
     };
     v.opposite = x;
     HashSet<MarkerVertex> list = new HashSet<MarkerVertex>();
     primeNode.ForEachMarkerVertex((u) =>
         {
             if (u.perfect)
                 list.Add(u);
             return IterationFlag.Continue;
         });
     primeNode.AddMarkerVertex(v, list);
     primeNode.lastMarkerVertex = v;
     AddLeaf(x);
 }
        private PrimeNode Contraction(SplitTree ST, SplitTree tPrime, int xId)
        {
            //during the contraction, the active flags won't be used any more. thus available as temporary delete flags
            //when a deleted node has non-empty parentLink and empty unionFind_parent, it is a degenerate to prime conversion and the parentLink points to the converted prime node.
            //when a deleted node has non-empty unionFind_parent, it is a fake node (only playing a role of child representative)
            ST.ResetActiveFlags();
            List<DegenerateNode> Phase1List = new List<DegenerateNode>();
            List<Node> Phase2List = new List<Node>();
            List<Node> nonLeafChildren = new List<Node>();
            Node phase3 = null;//since phase 3 is recursive, we need only a start point.
            #region Phase 0 Initial sweep
            foreach (var v in tPrime.vertices)
            {
                var d = v as DegenerateNode;
                var n = v as Node;
                if (d != null && d.isStar && d.rootMarkerVertex == d.center)
                    Phase1List.Add(d);
                if (n != null && n.Degree(n.rootMarkerVertex) == 1)
                    Phase2List.Add(n);
                if (n != null)
                    phase3 = n;//in case Phase1List and Phase2List are both empty, at least we have a start point for phase 3
            }
            #endregion
            #region Phase 1 node-joins
            foreach (var star in Phase1List)
            {
                if (star.active)//deleted
                    continue;
                phase3 = star;
                nonLeafChildren.Clear();
                phase3.ForEachChild((v) =>
                    {
                        if (v is Node)
                        {
                            nonLeafChildren.Add(v as Node);
                        }
                        return IterationFlag.Continue;
                    }, subtree: true);
                foreach (var c in nonLeafChildren)
                {
                    phase3 = NodeJoin(ST, phase3, c);
                    //c.parentLink = dummy;
                }
                phase3.visited = true;//add the joint node back into T'
            }
            #endregion
            #region Phase 2 node-joins
            foreach (var node in Phase2List)
            {
                if (node.active)//actually I mean "deleted"
                    continue;
                phase3 = node;
                var p = phase3.parent;
                if (p.visited && p is Node)
                {
                    phase3 = NodeJoin(ST, p as Node, phase3);//make sure phase3 now points to the new parent(which is prime)
                }
            }
            #endregion
            #region Phase 3 node-joins
            Debug.Assert(phase3 != null, "Phase 3 node is null, which means that there's nothing left in the fully-mixed subtree T'");
            while (true)
            {
                while (true)
                {
                    nonLeafChildren.Clear();
                    phase3.ForEachChild((v) =>
                        {
                            if (v is Node)
                            {
                                nonLeafChildren.Add(v as Node);
                            }
                            return IterationFlag.Continue;
                        }, subtree: true);
                    if (nonLeafChildren.Count == 0)
                        break;
                    foreach (var c in nonLeafChildren)
                    {
                        phase3 = NodeJoin(ST, phase3, c);
                    }
                }
                var p = phase3.parent;
                if (p == null || p is Leaf || p.visited == false)
                {
                    break;
                }
                else
                    phase3 = p as Node;
            }
            #endregion
            //rebuild ST from dummy flags. Note that this step is very important before using Find() and parent accessor again, because there might be a node with unionFind_parent == dummyFake, and dummyFake has unionFind_parent == null
            //List<GLTVertex> newSTList = new List<GLTVertex>();
            //foreach (var vertex in ST.vertices)
            //{
            //    if (!vertex.active)
            //        newSTList.Add(vertex);//a normal vertex
            //    else if (vertex.parentLink != null && vertex.unionFind_parent == null)
            //        newSTList.Add(vertex.parentLink);//a converted vertex
            //    //otherwise, either a fake node, or a truely-removed one, we don't add them back to ST any more.
            //    //if (vertex.parentLink != deleteDummy && vertex.unionFind_parent != fakeDummy)//neither deleted nor fake
            //    //    newSTList.Add(vertex);
            //    //else if (vertex.parentLink == deleteDummy && vertex.unionFind_parent != null)//replaced
            //    //    newSTList.Add(vertex.unionFind_parent);
            //    //else if (vertex.unionFind_parent == fakeDummy)
            //    //    vertex.unionFind_parent = vertex;//point the unionFind_parent back
            //}
            //ST.vertices = newSTList;

            HashSet<MarkerVertex> Pset = new HashSet<MarkerVertex>();
            phase3.ForEachMarkerVertex((v) =>
                {
                    if (v.perfect)
                        Pset.Add(v);
                    return IterationFlag.Continue;
                });
            Leaf newLeaf = new Leaf()
            {
                id = xId,
                parent = phase3,
            };
            MarkerVertex newMarker = new MarkerVertex()
            {
                opposite = newLeaf,
            };
            newLeaf.opposite = newMarker;
            (phase3 as PrimeNode).AddMarkerVertex(newMarker, Pset);
            (phase3 as PrimeNode).lastMarkerVertex = newMarker;
            ST.AddLeaf(newLeaf);
            return phase3 as PrimeNode;
        }
 public abstract int Degree(MarkerVertex v);
        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;
                }
            }
        }
Example #17
0
 internal void RemoveMarkerVertex(MarkerVertex q)
 {
     if (q == universalMarkerVetex)
         universalMarkerVetex = null;
     int universalCount = Gu.Count - 2;
     var neighbors = Gu[q];
     foreach (var v in neighbors)
     {
         var set = Gu[v];
         set.Remove(q);
         if (set.Count == universalCount)
             universalMarkerVetex = v;
     }
     Gu.Remove(q);
 }