Пример #1
0
        /// <summary>
        /// Add a person to the MPQ-Tree
        /// If this fails the graph is no interval graph
        /// </summary>
        /// <param name="person"></param>
        /// <returns>If false adding the person fails</returns>
        public bool AddVertice(Person person)
        {
            //Can be omitted if person has no neighbors or there are no nodes
            if (person.Neighbors.Count > 0 && root != null)
            {
                //nDown is the lowest node on P with label 1 or infinity
                //If there is a node with the label 0 or 1 let nUp be the highest such node else nUp is nDown
                //nCurrent is the current node between nDown and nUp
                BaseNode nUp = null, nDown, nCurrent;

                //List of the persons in A for a certain node
                Dictionary <BaseNode, List <Person> > ALists = new Dictionary <BaseNode, List <Person> >();

                //Represents a path P from the root to a positively labeled leaf
                Dictionary <BaseNode, BaseNode> rootedPath = new Dictionary <BaseNode, BaseNode>();

                Dictionary <BaseNode, bool> flagMap = new Dictionary <BaseNode, bool>();

                foreach (BaseNode node in nodePointer.Values)
                {
                    flagMap[node] = false;
                }

                //All nodes that have to be check whether they are contained on a path
                Queue <BaseNode> QueueToCheck = new Queue <BaseNode>();

                //Check all neighbors
                foreach (Person neighbor in person.Neighbors)
                {
                    //Ignore persons who are not part of the tree
                    if (neighbor.Position < person.Position)
                    {
                        //The node the current neighbor belongs to
                        BaseNode associatedNode = nodePointer[neighbor];

                        if (associatedNode is Section)
                        {
                            Section associatedSection = associatedNode as Section;

                            //The neighbor must be contained in an outer section
                            if (associatedSection.RightNeighbor == null && associatedSection.LeftNeighbor == null)
                            {
                                return(false);
                            }
                        }

                        //Creates a new A list for the current node
                        if (!ALists.ContainsKey(associatedNode))
                        {
                            ALists.Add(associatedNode, new List <Person>());
                        }

                        //Adds the current neighbor to the A list
                        ALists[associatedNode].Add(neighbor);
                        //Remove the current neighbor from the B list
                        associatedNode.ContainedPersons.Remove(positionPointers[neighbor]);

                        QueueToCheck.Enqueue(associatedNode);
                    }
                }

                //Current person has no neighbors, which are in the tree
                if (QueueToCheck.Count == 0)
                {
                    //We have already a PNode without contained persons as root -> no need to create one
                    if (root is PNode && root.ContainedPersons.Count == 0)
                    {
                        Leaf leaf = new Leaf(this);
                        leaf.AddContainedPerson(person);
                        leaf.Father = root;
                    }

                    //Create a new PNode without contained persons
                    else
                    {
                        PNode newRoot = new PNode(this);
                        newRoot.AddFirstChild(root);
                        newRoot.Father = null;

                        Leaf leaf = new Leaf(this);
                        leaf.Father = newRoot;
                        leaf.AddContainedPerson(person);
                    }

                    return(true);
                }

                BaseNode currentNode;

                //Flag all elements on QueueToCheck
                while (QueueToCheck.Count > 0)
                {
                    currentNode = QueueToCheck.Dequeue();

                    //Node not yet visited
                    flagMap[currentNode] = true;

                    if (currentNode.Father != null)
                    {
                        //Father has to be flagged too
                        QueueToCheck.Enqueue(currentNode.Father);

                        //All nodes must be on a path -> if the current node is not a duplicate it may not be on the rooted path
                        if (!(currentNode is Section))
                        {
                            if (rootedPath.ContainsKey(currentNode.Father) && rootedPath[currentNode.Father] != currentNode)
                            {
                                return(false);
                            }
                        }

                        //Things are different with section: There may be multiple sections of one QNode, but only one of them may be a outer section
                        else if (rootedPath.ContainsKey(currentNode.Father) && currentNode != rootedPath[currentNode.Father])
                        {
                            Section currentSection        = currentNode as Section;
                            Section otherContainedSection = rootedPath[currentNode.Father] as Section;

                            if (currentSection.LeftNeighbor == null || currentSection.RightNeighbor == null)
                            {
                                if (!(otherContainedSection.LeftNeighbor == null || otherContainedSection.RightNeighbor == null))
                                {
                                    rootedPath[currentNode.Father] = currentNode;
                                }
                                else
                                {
                                    return(false); //There is no path
                                }
                            }
                        }

                        //Keep a link from the father to its son
                        rootedPath[currentNode.Father] = currentNode;
                    }
                }

                //The path must start at the root
                currentNode = root;

                //Travers the rooted path downwards to find nUp
                while (rootedPath.ContainsKey(currentNode))
                {
                    //nUp not found yet
                    if (nUp == null)
                    {
                        //B mustn't be empty (-> label is not Infinity)
                        if (currentNode.ContainedPersons.Count > 0)
                        {
                            if (currentNode is Section)
                            {
                                //The path must go through a outer section
                                Section currentSection = currentNode as Section;
                                if (currentSection.LeftNeighbor != null && currentSection.RightNeighbor != null)
                                {
                                    return(false);
                                }

                                //nUp must be a qNode containing the Section fulfilling the condition
                                nUp = currentNode.Father as QNode;
                            }

                            else if (currentNode is PNode)
                            {
                                nUp = currentNode;
                            }
                        }
                    }

                    currentNode = rootedPath[currentNode];
                }

                //If currentNode is a Section get the associated QNode
                if (currentNode is Section)
                {
                    currentNode = currentNode.Father;
                }

                //nDown is the lowest node on the path P
                nDown = currentNode;

                //If there is no node matching the conditions for nUp, nUp is nDown
                if (nUp == null)
                {
                    nUp = nDown;
                }

                //nCurrent must be traversed bottom-up (-> is set to nDown at start)
                nCurrent = nDown;

                //The path between nDown and nUp
                Dictionary <BaseNode, BaseNode> progressionPath = new Dictionary <BaseNode, BaseNode>();

                currentNode = nDown;

                //Build a path from nDown to nUp
                if (nUp == nDown)
                {
                    progressionPath.Add(nDown, null);
                }

                else
                {
                    while (currentNode != null)
                    {
                        progressionPath.Add(currentNode, currentNode.Father);
                        currentNode = currentNode.Father;
                    }
                }

                //Apply templates
                do
                {
                    if (!ALists.ContainsKey(nCurrent))
                    {
                        //AList are generated for Sections -> need to be transformed to QNodes
                        if (nCurrent is QNode)
                        {
                            QNode currentQNode = nCurrent as QNode;

                            if (ALists.ContainsKey(currentQNode.OuterSectionLeft))
                            {
                                ALists[nCurrent] = ALists[currentQNode.OuterSectionLeft];
                                ALists.Remove(currentQNode.OuterSectionLeft);
                            }

                            else if (ALists.ContainsKey(currentQNode.OuterSectionRight))
                            {
                                ALists[nCurrent] = ALists[currentQNode.OuterSectionRight];
                                ALists.Remove(currentQNode.OuterSectionRight);
                            }

                            else
                            {
                                ALists[nCurrent] = new List <Person>();
                            }
                        }

                        else
                        {
                            ALists[nCurrent] = new List <Person>();
                        }
                    }

                    //Templates L1 and L2
                    if (nCurrent is Leaf)
                    {
                        //Template L1
                        if (nUp == nDown)
                        {
                            //B is empty
                            if (nCurrent.ContainedPersons.Count == 0)
                            {
                                nCurrent.AddContainedRange(ALists[nCurrent]);

                                nCurrent.AddContainedPerson(person);
                            }

                            //B is not empty
                            else
                            {
                                PNode pNode = new PNode(this);
                                pNode.Father = nCurrent.Father;

                                Leaf leaf = new Leaf(this);
                                leaf.Father = pNode;

                                leaf.AddContainedPerson(person);

                                pNode.AddLastChild(nCurrent);

                                pNode.AddContainedRange(ALists[nCurrent]);
                            }
                        }

                        //Template L2
                        else
                        {
                            QNode qNode = new QNode(this);
                            qNode.Father = nCurrent.Father;

                            Section section1 = qNode.AddNewLastSection();
                            Section section2 = qNode.AddNewLastSection();

                            section1.AddContainedRange(ALists[nCurrent]);
                            section2.AddContainedRange(ALists[nCurrent]);

                            Leaf leaf = new Leaf(this);
                            leaf.Father = section1;
                            leaf.AddContainedPerson(person);

                            nCurrent.Father = section2;
                        }
                    }

                    //Templates P1, P2 and P3
                    else if (nCurrent is PNode)
                    {
                        //Template P1
                        if (nUp == nDown)
                        {
                            //B is empty
                            if (nCurrent.ContainedPersons.Count == 0)
                            {
                                Leaf leaf = new Leaf(this);
                                leaf.AddContainedPerson(person);
                                leaf.Father = nCurrent;

                                nCurrent.AddContainedRange(ALists[nCurrent]);
                            }

                            //B is not empty
                            else
                            {
                                PNode pNode = new PNode(this);
                                pNode.Father = nCurrent.Father;

                                Leaf leaf = new Leaf(this);
                                leaf.AddContainedPerson(person);

                                leaf.Father     = pNode;
                                nCurrent.Father = pNode;
                            }
                        }

                        //Template P2
                        else if (nCurrent == nDown) //No need to check nDown != nUp (previously checked)
                        {
                            QNode qNode = new QNode(this);
                            qNode.Father = nCurrent.Father;

                            Section section1 = qNode.AddNewLastSection();
                            Section section2 = qNode.AddNewLastSection();

                            Leaf leaf = new Leaf(this);
                            leaf.AddContainedPerson(person);
                            leaf.Father = section1;

                            nCurrent.Father = section2;

                            section1.AddContainedRange(ALists[nCurrent]);
                            section2.AddContainedRange(ALists[nCurrent]);
                        }

                        //Template P3
                        else if (nCurrent != nDown)
                        {
                            PNode currentPNode = nCurrent as PNode;
                            QNode currentQNode = currentPNode.SomeSon as QNode;

                            //No need to edit the father correctly; this will happen in Q3
                            if (currentPNode.Father is Section)
                            {
                                foreach (Person p in currentPNode.Father.ContainedPersons)
                                {
                                    currentPNode.ContainedPersons.AddLast(p);
                                }
                            }

                            if (currentQNode != null && currentQNode.OuterSectionLeft.Son.ContainedPersons.First.Value == person)
                            {
                                QNode newQNode = new QNode(this);
                                newQNode.Father = currentPNode.Father;

                                Section currentSection = currentQNode.OuterSectionLeft.RightNeighbor;
                                while (currentSection != null)
                                {
                                    Section newSection = newQNode.AddNewLastSection();
                                    currentSection.Son.Father = newSection;

                                    IEnumerable <Person> newContainedPersons = ALists[nCurrent].Union(nCurrent.ContainedPersons).Union(currentSection.ContainedPersons);
                                    newSection.AddContainedRange(newContainedPersons);

                                    currentSection = currentSection.RightNeighbor;
                                }

                                Section lastNewSection = newQNode.AddNewLastSection();

                                Section section1 = newQNode.AddNewFirstSection();
                                currentQNode.OuterSectionLeft.Son.Father = section1;

                                section1.AddContainedRange(ALists[nCurrent].Union(currentQNode.OuterSectionLeft.ContainedPersons));

                                PNode newPNode = new PNode(this);
                                newPNode.Father = lastNewSection;

                                lastNewSection.AddContainedRange(ALists[nCurrent].Union(nCurrent.ContainedPersons));

                                foreach (BaseNode node in currentPNode.Children.ToArray())
                                {
                                    if (node != currentQNode)
                                    {
                                        newPNode.AddLastChild(node);
                                    }
                                }
                            }

                            currentPNode.Vanish();
                        }
                    }

                    //Templates Q1, Q2 and Q3
                    else if (nCurrent is QNode)
                    {
                        //Templates Q1 and Q2
                        if (nCurrent == nDown)
                        {
                            QNode currentQNode = currentNode as QNode;

                            //Template Q1
                            if (!ALists[currentQNode].Except(currentQNode.OuterSectionRight.ContainedPersons).Any())
                            {
                                if (nUp == nDown)
                                {
                                    PNode pNode = new PNode(this);
                                    pNode.Father = nCurrent.Father;

                                    Leaf leaf = new Leaf(this);
                                    pNode.AddFirstChild(leaf);
                                    leaf.AddContainedPerson(person);

                                    pNode.AddContainedRange(ALists[nCurrent]);

                                    Section currentSection = currentQNode.OuterSectionLeft;
                                    while (currentSection != null)
                                    {
                                        //Removes a from all sections
                                        currentSection.ContainedPersons = new LinkedList <Person>(currentSection.ContainedPersons.Except(ALists[nCurrent]));

                                        currentSection = currentSection.RightNeighbor;
                                    }

                                    pNode.AddLastChild(currentQNode);
                                }

                                else
                                {
                                    QNode newQNode = new QNode(this);
                                    newQNode.Father = nCurrent.Father;

                                    Section firstSection  = newQNode.AddNewLastSection();
                                    Section secondSection = newQNode.AddNewLastSection();

                                    Leaf leaf = new Leaf(this);
                                    leaf.Father = firstSection;
                                    leaf.AddContainedPerson(person);

                                    firstSection.AddContainedRange(ALists[nCurrent]);
                                    secondSection.AddContainedRange(ALists[nCurrent]);

                                    Section currentSection = currentQNode.OuterSectionLeft;
                                    while (currentSection != null)
                                    {
                                        //Removes a from all sections
                                        currentSection.ContainedPersons = new LinkedList <Person>(currentSection.ContainedPersons.Except(ALists[nCurrent]));

                                        currentSection = currentSection.RightNeighbor;
                                    }

                                    currentQNode.Father = secondSection;
                                }
                            }

                            //Template Q2
                            else
                            {
                                //B is empty
                                if (nCurrent.ContainedPersons.Count == 0)
                                {
                                    PNode pNode = new PNode(this);

                                    pNode.AddFirstChild(currentQNode.OuterSectionLeft.Son);
                                    pNode.Father = currentQNode.OuterSectionLeft;

                                    currentQNode.OuterSectionLeft.AddContainedRange(ALists[nCurrent]);

                                    Leaf leaf = new Leaf(this);
                                    leaf.AddContainedPerson(person);
                                    pNode.AddFirstChild(leaf);
                                }

                                else if (nCurrent.ContainedPersons.Count == 0 || nUp != nDown)
                                {
                                    Section section = currentQNode.AddNewFirstSection();
                                    section.AddContainedRange(ALists[nCurrent]);

                                    Leaf leaf = new Leaf(this);
                                    leaf.Father = section;
                                    leaf.AddContainedPerson(person);
                                }
                            }
                        }

                        //Template Q3
                        else
                        {
                            QNode currentQNode      = nCurrent as QNode;
                            QNode currentLowerQNode = null;

                            Section parentSection;
                            parentSection = currentQNode.OuterSectionLeft as Section;

                            if (currentQNode.OuterSectionLeft.Son is QNode)
                            {
                                parentSection     = currentQNode.OuterSectionLeft;
                                currentLowerQNode = parentSection.Son as QNode;
                            }

                            if (currentLowerQNode != null && currentLowerQNode.OuterSectionLeft.Son.ContainedPersons.First.Value == person)
                            {
                                currentQNode.RemoveSection(parentSection);

                                Section currentSection = currentLowerQNode.OuterSectionRight;
                                while (currentSection.LeftNeighbor != null)
                                {
                                    Section newSection = currentQNode.AddNewFirstSection();
                                    if (currentSection.Son != null)
                                    {
                                        currentSection.Son.Father = newSection;
                                    }

                                    IEnumerable <Person> newContainedPersons = ALists[nCurrent].Union(nCurrent.ContainedPersons).Union(currentSection.ContainedPersons);
                                    newSection.AddContainedRange(newContainedPersons);

                                    currentSection = currentSection.LeftNeighbor;
                                }

                                Section firstNewSection;
                                firstNewSection = currentQNode.AddNewFirstSection();

                                currentLowerQNode.OuterSectionLeft.Son.Father = firstNewSection;

                                firstNewSection.AddContainedRange(currentLowerQNode.OuterSectionLeft.ContainedPersons.Union(ALists[nCurrent]));
                            }
                        }
                    }

                    //Remove the AList of nCurrent -> every AList contained in the end has to be written back
                    ALists.Remove(nCurrent);

                    //Go one node up
                    nCurrent = progressionPath[nCurrent];

                    //If nCurrent now is a Section get the associated QNode
                    if (nCurrent is Section)
                    {
                        Section currentSection = nCurrent as Section;
                        nCurrent = currentSection.Father;
                    }
                }while (nCurrent != null);

                //Add the unused ALists
                foreach (BaseNode baseNode in ALists.Keys)
                {
                    baseNode.AddContainedRange(ALists[baseNode]);
                }

                //Check all manipulated PNodes
                //Helper templates might be necessary
                foreach (PNode pNode in manipulatedPNodes.ToArray())
                {
                    //Template H1
                    if (pNode.ContainedPersons.Count == 0 && pNode.Children.Count == 1 && pNode.Father != pNode)
                    {
                        pNode.Children.First.Value.Father = pNode.Father;
                        pNode.Vanish();
                    }

                    //Template H2
                    else if (pNode.Father is PNode)
                    {
                        PNode fatherPNode = pNode.Father as PNode;
                        if (fatherPNode.ContainedPersons.Count == 0 && pNode.ContainedPersons.Count == 0)
                        {
                            foreach (BaseNode node in pNode.Children.ToArray())
                            {
                                fatherPNode.AddLastChild(node);
                            }

                            pNode.Vanish();
                        }
                    }
                }

                manipulatedPNodes.Clear();
            }

            else
            {
                if (person.Neighbors.Count == 0 && root != null)
                {
                    //We have already a PNode without contained persons as root -> no need to create one
                    if (root is PNode && root.ContainedPersons.Count == 0)
                    {
                        Leaf leaf = new Leaf(this);
                        leaf.AddContainedPerson(person);
                        leaf.Father = root;
                    }

                    //Create a new PNode without contained persons
                    else
                    {
                        PNode newRoot = new PNode(this);
                        newRoot.AddFirstChild(root);
                        newRoot.Father = null;

                        Leaf leaf = new Leaf(this);
                        leaf.Father = newRoot;
                        leaf.AddContainedPerson(person);
                    }
                }

                //Create a new leaf
                else if (root == null)
                {
                    Leaf leaf = new Leaf(this);
                    leaf.Father = root;
                    leaf.AddContainedPerson(person);
                }
            }

            return(true);
        }