Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MaxSequencePQTree.h
Go to the documentation of this file.
1
35#pragma once
36
38#include <ogdf/basic/List.h>
39#include <ogdf/basic/PQTree.h>
40#include <ogdf/basic/Queue.h>
41#include <ogdf/basic/SList.h>
42#include <ogdf/basic/basic.h>
47
48namespace ogdf {
49template<class T, class X, class Y>
50class PQLeafKey;
51
103template<class T, class Y>
104class MaxSequencePQTree : public PQTree<T, whaInfo*, Y> {
105public:
106 using PQTree<T, whaInfo*, Y>::emptyNode;
107
109
111 while (!eliminatedNodes.empty()) {
112 PQNode<T, whaInfo*, Y>* nodePtr = eliminatedNodes.popFrontRet();
113 CleanNode(nodePtr);
114 delete nodePtr;
115 }
116 }
117
124 virtual void CleanNode(PQNode<T, whaInfo*, Y>* nodePtr);
125
127
135
137
182
209 SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys);
210
211protected:
212 using PQTree<T, whaInfo*, Y>::fullChildren;
213 using PQTree<T, whaInfo*, Y>::partialChildren;
214
229 virtual bool Bubble(SListPure<PQLeafKey<T, whaInfo*, Y>*>& leafKeys);
230
252
260
269
270private:
293 SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys);
294
306
321
335 whaType deleteType);
336
339
346
365 void aNumQnode(PQNode<T, whaInfo*, Y>* nodePtr, int sumAllW);
366
372 void hNumQnode(PQNode<T, whaInfo*, Y>* nodePtr, int sumAllW);
373
384
390};
391
392template<class T, class Y>
394 // Queue for storing all pertinent nodes that still have
395 // to be processed.
396 Queue<PQNode<T, whaInfo*, Y>*> processNodes;
397
398 /*
399 Enter the [[Full]] leaves into the queue [[processNodes]].
400 In a first step the pertinent leaves have to be identified in the tree
401 and entered on to the queue [[processNodes]]. The identification of
402 the leaves can be done with the help of a pointer stored in every
403 [[PQLeafKey]] (see \ref{PQLeafKey}) in constant time for every element.
404 */
406 for (it = leafKeys.begin(); it.valid(); ++it) {
407 PQNode<T, whaInfo*, Y>* checkLeaf = (*it)->nodePointer();
408 processNodes.append(checkLeaf);
409 cleanUp.pushBack(checkLeaf);
410 if (!checkLeaf->getNodeInfo()) { // if leaf does not have an information class for storing the [wha]-number allocate one.
411 whaInfo* newInfo = new whaInfo;
413 checkLeaf->setNodeInfo(infoPtr);
414 infoPtr->setNodePointer(checkLeaf);
415 }
416 checkLeaf->getNodeInfo()->userStructInfo()->m_notVisitedCount = 1;
418 }
419
420 /*
421 For every node in [[processNodes]], its father is detected using the
422 function [[GetParent]] \ref{GetParent}. The father is placed onto the
423 queue as well, if [[_nodePtr]] is its first child, that is popped from
424 the queue. In that case, the father is marked as [[Queued]] to
425 prevent the node from queue more than once. In any case, the number
426 of pertinent children of the father is updated. This is an important
427 number for computing the maximal pertinent sequence.
428 */
429 while (!processNodes.empty()) {
430 PQNode<T, whaInfo*, Y>* nodePtr = processNodes.pop();
431 nodePtr->parent(GetParent(nodePtr));
432 if (nodePtr->parent() && !nodePtr->parent()->getNodeInfo())
433 // if the parent does not have an information
434 // class for storing the [wha]-number
435 // allocate one.
436 {
437 whaInfo* newInfo = new whaInfo;
439 nodePtr->parent()->setNodeInfo(infoPtr);
440 infoPtr->setNodePointer(nodePtr->parent());
441 }
442 if (nodePtr != this->m_root) {
443 if (nodePtr->parent()->mark() == PQNodeRoot::PQNodeMark::Unmarked) {
444 processNodes.append(nodePtr->parent());
445 cleanUp.pushBack(nodePtr->parent());
446 nodePtr->parent()->mark(PQNodeRoot::PQNodeMark::Queued);
447 }
448 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount++;
449 int childCount = nodePtr->parent()->pertChildCount();
450 nodePtr->parent()->pertChildCount(++childCount);
451 }
452 }
453
454
455 /*
456 This chunk belongs to the function [[Bubble]]. After doing some
457 cleaning up and resetting the flags that have been left at the
458 pertinent nodes during the first bubble up, this chunk computes the
459 maximal pertinent sequence by calling the function [[determineMinRemoveSequence]].
460 It then removes
461 all leaves from the tree that have been marked as [[Eliminated]] and
462 possibly some internal nodes of the $PQ$-tree and stores pointers of
463 type [[leafKey]] for the pertinent leaves in the maximal sequence in the
464 array [[survivedElements]].
465 */
466
468 for (itn = cleanUp.begin(); itn.valid(); ++itn) {
470 }
471
472 return true;
473}
474
475template<class T, class Y>
477 if (nodePtr->getNodeInfo()) {
478 delete nodePtr->getNodeInfo()->userStructInfo();
479 delete nodePtr->getNodeInfo();
480 }
481}
482
483template<class T, class Y>
486 emptyNode(nodePtr);
488 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::PertRoot) {
489 emptyNode(nodePtr);
490 } else {
491 // Node has an invalid status?
493 emptyNode(nodePtr);
494 }
495}
496
497template<class T, class Y>
499 PQNode<T, whaInfo*, Y>* nodePtr = nullptr;
500
501 while (!cleanUp.empty()) {
502 nodePtr = cleanUp.popFrontRet();
503 nodePtr->pertChildCount(0);
505 && nodePtr->type() == PQNodeRoot::PQNodeType::Leaf) {
506 CleanNode(nodePtr);
507 delete nodePtr;
508 }
509
510 else {
511 // node must have an Information if contained in cleanUp
512 OGDF_ASSERT(nodePtr->getNodeInfo() != nullptr);
513
514 nodePtr->getNodeInfo()->userStructInfo()->m_notVisitedCount = 0;
515 nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount = 0;
516 }
517 }
518
520 for (it = this->m_pertinentNodes->begin(); it.valid(); ++it) {
521 nodePtr = *it;
524 eliminatedNodes.pushBack(nodePtr);
525 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::Full) {
527 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::WhaDelete) {
529 } else if (nodePtr->getNodeInfo()) {
530 nodePtr->getNodeInfo()->userStructInfo()->defaultValues();
531 }
532 }
534}
535
536template<class T, class Y>
539 SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys) {
540 PQNode<T, whaInfo*, Y>* nodePtr = nullptr; // dummy
541
542 //Number of leaves that have to be deleted
543 int countDeletedLeaves = 0;
544 //Number of pertinent leaves
545 int maxPertLeafCount = 0;
546
547 // A queue storing the nodes whose $[w,h,a]$-number has to be computed next.
548 // A node is stored in [[processNodes]], if for all of its children the
549 // [w,h,a]-number has been computed.
550 Queue<PQNode<T, whaInfo*, Y>*> processNodes;
551
552 // A stack storing all nodes where a $[w,h,a]$-number
553 // has been computed. This is necessary for a valid cleanup.
555
556 // Compute a valid parent pointer for every pertinent node.
557 Bubble(leafKeys);
558
559 // Get all pertinent leaves and stores them on [[processNodes]]
560 // and [[_archiv]].
562 for (it = leafKeys.begin(); it.valid(); ++it) {
563 PQNode<T, whaInfo*, Y>* checkLeaf = (*it)->nodePointer();
564 checkLeaf->getNodeInfo()->userStructInfo()->m_pertLeafCount = 1;
565 checkLeaf->getNodeInfo()->userStructInfo()->m_notVisitedCount--;
566 processNodes.append(checkLeaf);
567 archiv.push(checkLeaf);
568
569 maxPertLeafCount++;
570 }
571
572 while (!processNodes.empty()) {
573 nodePtr = processNodes.pop();
574 // Compute the $[w,h,a]$ number of [[nodePtr]]. Computing this number is
575 // trivial for leaves and full nodes. When considering a partial node, the
576 // computation has to distinguish between $P$- and $Q$-nodes.
577 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
578 // In case that the actual node, depicted by the pointer
579 // [[nodePtr]] is not the root, the counts of the pertinent
580 // children of [[nodePtr]]'s parent are
581 // updated. In case that all pertinent children of the parent of
582 // [[nodePtr]] have a valid $[w,h,a]$-number, it is possible to compute
583 // the $[w,h,a]$-number of parent. Hence the parent is placed onto
584 // [[processNodes]]and [[_archiv]].
585 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_pertLeafCount =
586 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_pertLeafCount
587 + nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount;
588 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount--;
589 if (!nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount) {
590 processNodes.append(nodePtr->parent());
591 archiv.push(nodePtr->parent());
592 }
593 }
594 if (nodePtr->type() == PQNodeRoot::PQNodeType::Leaf) {
595 // Compute the $[w,h,a]$-number of a leaf. The computation is trivial.
597 nodePtr->getNodeInfo()->userStructInfo()->m_w = 1;
598 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
599 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
600 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
601 fullChildren(nodePtr->parent())->pushFront(nodePtr);
602 }
603 } else {
604 // [[nodePtr]] is a $P$- or $Q$-node
605 // The $[w,h,a]$ number of $P$- or $Q$-nodes is computed identically.
606 // This is done calling the function [[sumPertChild]].
607 nodePtr->getNodeInfo()->userStructInfo()->m_w = sumPertChild(nodePtr);
608
609 if (fullChildren(nodePtr)->size() == nodePtr->childCount()) {
610 // computes the $h$- and $a$-numbers of a full node. The computation
611 // is trivial. It also updates the list of full nodes of the parent
612 // of [[nodePtr]].
614 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
615 fullChildren(nodePtr->parent())->pushFront(nodePtr);
616 }
617 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
618 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
619 } else {
620 // computes the $[w,h,a]$-number of a partial node. The computation is
621 // nontrivial for both $P$- and $Q$-nodes and is performed in the
622 // function [[haNumPnode]] for $P$-nodes and in the
623 // function [[haNumQnode]] for $Q$-nodes.
624 // This chunk also updates the partial children stack of the parent.
626 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
627 partialChildren(nodePtr->parent())->pushFront(nodePtr);
628 }
629
630 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
631 haNumPnode(nodePtr);
632 } else {
633 haNumQnode(nodePtr);
634 }
635 }
636 }
637 }
638
639 // Determine the root of the pertinent subtree, which the last processed node
640 //[[nodePtr]] and finds the minimum of the $h$- and $a$-number of
641 //[[m_pertinentRoot]]. In case that the minimum is equal to $0$, the
642 //[[m_pertinentRoot]] stays of type $B$. Otherwise the type is selected
643 //according to the minimum.
644 OGDF_ASSERT(nodePtr != nullptr);
645 this->m_pertinentRoot = nodePtr;
646 if (this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h
647 < this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a) {
648 countDeletedLeaves = this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h;
649 } else {
650 countDeletedLeaves = this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a;
651 }
652
653 if (countDeletedLeaves > 0) {
654 if (this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h
655 < this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a) {
656 this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
657 } else {
658 this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
659 }
660 }
661
662 findMinWHASequence(archiv, eliminatedKeys);
663
664 return countDeletedLeaves;
665}
666
667template<class T, class Y>
669 SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys) {
670 //a pointer to the first child of type $h$ of [[nodePtr]].
671 PQNode<T, whaInfo*, Y>* hChild1 = nullptr;
672
673 //a pointer to the second child of type $h$ of [[nodePtr]].
674 PQNode<T, whaInfo*, Y>* hChild2 = nullptr;
675
676 //a pointer to the child of type $a$ of [[nodePtr]].
677 PQNode<T, whaInfo*, Y>* aChild = nullptr;
678
679 // pertinent sibling of hChild1
680 PQNode<T, whaInfo*, Y>* hChild2Sib = nullptr;
681
682 while (!archiv.empty()) {
683 //counts the number of children of [[nodePtr]].
684 int childCount = 0;
685
686 //a pointer to a pertinent node of the $PQ$-tree that is currently examined.
687 PQNode<T, whaInfo*, Y>* nodePtr = archiv.popRet();
688
689 /*
690 Check if [[nodePtr]] is a full node whose delete type is either of
691 type $h$ or type $a$. Since there are no empty leaves in its
692 frontier, the node must therefore keep all its pertinent leaves
693 in its frontier and is depicted to be of type $b$.
694 */
695 if (nodePtr->status() == PQNodeRoot::PQNodeStatus::Full
696 && (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::H
697 || nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::A)) {
698 nodePtr->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
699 this->m_pertinentNodes->pushFront(nodePtr);
700 }
701
702 /*
703 Check if [[nodePtr]] is a leaf whose delete type is either of type $w$ or
704 $b$. In case it is of type $w$, the leaf has to be removed from the
705 tree to gain reducibility of the set $S$.
706 */
707 else if (nodePtr->type() == PQNodeRoot::PQNodeType::Leaf) {
708 if (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::W) {
709 eliminatedKeys.pushBack(nodePtr->getKey());
710 } else {
711 this->m_pertinentNodes->pushFront(nodePtr);
712 }
713 }
714
715 /*
716 Manage the case of [[nodePtr]] being either a partial $P$-node, a partial
717 $Q$-node, or a full $P$- or $Q$-node, where in the latter case the
718 delete type of [[nodePtr]] is of type $b$.
719 */
720 else {
721 switch (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType) {
722 case whaType::B:
723 this->m_pertinentNodes->pushFront(nodePtr);
724 break;
725
726 case whaType::W:
727 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent, whaType::W);
728 nodePtr->pertChildCount(0);
729 this->m_pertinentNodes->pushFront(nodePtr);
730 break;
731
732 case whaType::H:
733 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
734 /*
735 [[nodePtr]] is a $P$-node of type $h$. Mark all full
736 children of [[nodePtr]] to be of type $b$ (by doing nothing, since
737 the default is type $b$). It furthermore marks all partial children to
738 be of type $w$ except for the child stored in [[hChild1]] of the
739 information class of type [[whaInfo*]] of [[nodePtr]]. This child is
740 marked to be of type $h$.
741 */
742 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Partial, whaType::W);
743 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Full, whaType::B);
744 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild1) {
745 hChild1 =
746 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild1;
747 hChild1->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
748 if (hChild1->getNodeInfo()->userStructInfo()->m_h
749 < hChild1->getNodeInfo()->userStructInfo()->m_w) {
750 childCount = 1;
751 }
752 }
753 nodePtr->pertChildCount(nodePtr->pertChildCount() + childCount
754 - partialChildren(nodePtr)->size());
755 } else {
756 /*
757 [[nodePtr]] is a $Q$-node. Mark all pertinent children
758 to be of type $w$, except for the full children between the
759 [[hChild1]] and the endmost child of [[nodePtr]]. These full
760 children are marked $b$ while [[hChild1]] is marked to be of type
761 $h$. Setting the type of children to $b$ or $h$ is hidden in the
762 function call [[setHchild]] \label{setHChild}.
763 */
764 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent, whaType::W);
765 hChild1 =
766 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild1;
767 nodePtr->pertChildCount(setHchild(hChild1));
768 }
769 this->m_pertinentNodes->pushFront(nodePtr);
770 break;
771
772 case whaType::A:
773 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
774 /*
775 [[nodePtr]] is a $P$-node of type $a$.
776 Distinguish two main cases, based on the existence of a
777 child of [[nodePtr]] stored in [[aChild]] of the information
778 class of type [[_whaInfo]] of [[nodePtr]].
779 \begin{enumerate}
780 \item
781 If [[aChild]] is not empty, the chunk marks all full
782 and partial children of [[nodePtr]] to be of type $w$ and
783 marks the child [[aChild]] to be of type $a$.
784 \item
785 If [[aChild]] is empty, the chunk
786 marks all full children of [[nodePtr]] to be of type $b$
787 (by doing nothing, since the default is type $b$).
788 It furthermore marks all partial children to be of type $w$
789 except for the children stored in [[hChild1]] and
790 [[hChild2]] of the information class of type [[whaInfo*]] of
791 [[nodePtr]] which are marked to be of type $h$. Observe that
792 we have to distinguish the cases where both, [[_hChild]] and
793 [[hChild2]] are available, just [[_h_Child1]] is available or
794 none of the nodes exist.
795 \end{enumerate}
796 */
797 if (nodePtr->getNodeInfo()->userStructInfo()->m_aChild) {
798 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
799 whaType::W);
800 aChild = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_aChild;
801 aChild->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
802 nodePtr->pertChildCount(1);
803 } else {
804 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Full, whaType::B);
805 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Partial, whaType::W);
806 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild1) {
807 hChild1 = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
808 ->userStructInfo()
809 ->m_hChild1;
810 hChild1->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
811 if (hChild1->getNodeInfo()->userStructInfo()->m_h
812 < hChild1->getNodeInfo()->userStructInfo()->m_w) {
813 childCount = 1;
814 }
815 }
816 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild2) {
817 hChild2 = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
818 ->userStructInfo()
819 ->m_hChild2;
820 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
821 if (hChild2->getNodeInfo()->userStructInfo()->m_h
822 < hChild2->getNodeInfo()->userStructInfo()->m_w) {
823 childCount++;
824 }
825 }
826 nodePtr->pertChildCount(nodePtr->pertChildCount() + childCount
827 - partialChildren(nodePtr)->size());
828 }
829 } else {
830 /*
831 [[nodePtr]] is a $Q$-node of type $a$.
832 Distinguish two main cases, based on the existence of a child of
833 [[nodePtr]] stored in [[aChild]] of the information class of type
834 [[_whaInfo]] of [[nodePtr]].
835 \begin{enumerate}
836 \item
837 If [[aChild]] is not empty, the chunk marks all full
838 and partial children of [[nodePtr]] to be of type $w$ and marks the
839 child [[aChild]] to be of type $a$.
840 \item
841 If [[aChild]] is empty, the chunk
842 marks all full and partial children of [[nodePtr]] to be of type $w$
843 except for the ones in the largest consecutive sequence of pertinent
844 children. This sequence
845 is depicted by the children [[hChild1]] and [[hChild2]] which may be
846 either full or partial. The children between [[hChild1]] and
847 [[hChild2]] are full and are marked $b$, while [[hChild1]] and
848 [[hChild2]] are marked $b$ or $h$, according to their status.
849 Setting the type of the nodes is hidden in calling the function
850 [[setAchildren]] (see \ref{setAchildren}).
851 \end{enumerate}
852 */
853 if (nodePtr->getNodeInfo()->userStructInfo()->m_aChild) {
854 aChild = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_aChild;
855 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
856 whaType::W);
857 aChild->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
858 nodePtr->pertChildCount(1);
859 } else {
860 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
861 whaType::W);
862 hChild2 =
863 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild2;
864 hChild2Sib = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
865 ->userStructInfo()
866 ->m_hChild2Sib;
867 nodePtr->pertChildCount(setAchildren(hChild2, hChild2Sib));
868 }
869 }
870 this->m_pertinentNodes->pushFront(nodePtr);
871 break;
872 }
873 }
874
875 /*
876 After successfully determining the type of the children of [[nodePtr]],
877 this chunk cleans up the information needed during the
878 computation at the [[nodePtr]].
879 */
880 fullChildren(nodePtr)->clear();
881 partialChildren(nodePtr)->clear();
883 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = nullptr;
884 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = nullptr;
885 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
886 nodePtr->getNodeInfo()->userStructInfo()->m_w = 0;
887 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
888 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
889 nodePtr->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
890 }
891}
892
893template<class T, class Y>
895 // counts the number of pertinent children corresponding to the $[w,h,a]$-numbering.
896 int pertinentChildCount = 0;
897
898 // is [[true]] as long as children with a full label are found, [[false]] otherwise.
899 bool fullLabel = false;
900
901 PQNode<T, whaInfo*, Y>* currentNode = hChild1; // dummy
902 PQNode<T, whaInfo*, Y>* nextSibling = nullptr; // dummy
903 PQNode<T, whaInfo*, Y>* oldSibling = nullptr; // dummy
904
905 if (hChild1 != nullptr) {
906 fullLabel = true;
907 }
908
909 /*
910 Trace the sequence of full children with at most one incident
911 pertinent child. It marks all full nodes as $b$-node and the partial
912 child, if available as $h$-child. The beginning of the sequence is
913 stored in [[currentNode]] which is equal to [[h_child1]] before
914 entering the while loop. Observe that this chunk cases if the while
915 loop while scanning the sequence has reached the second endmost child
916 of the $Q$-node (see [[if (nextSibling == 0)]]). This case may
917 appear, if all children of the $Q$-node are pertinent and the second
918 endmost child is the only partial child. The value [[fullLabel]] is
919 set to [[false]] as soon as the end of the sequence is detected.
920 */
921 while (fullLabel) {
922 nextSibling = currentNode->getNextSib(oldSibling);
923 if (!nextSibling) {
924 fullLabel = false;
925 }
926
927 if (currentNode->status() == PQNodeRoot::PQNodeStatus::Full) {
928 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
929 pertinentChildCount++;
930 }
931
932 else {
933 if (currentNode->status() == PQNodeRoot::PQNodeStatus::Partial) {
934 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
935 if ((currentNode->getNodeInfo()->userStructInfo()->m_pertLeafCount
936 - currentNode->getNodeInfo()->userStructInfo()->m_h)
937 > 0) {
938 pertinentChildCount++;
939 }
940 }
941 fullLabel = false;
942 }
943 oldSibling = currentNode;
944 currentNode = nextSibling;
945 }
946
947 return pertinentChildCount;
948}
949
950template<class T, class Y>
952 PQNode<T, whaInfo*, Y>* hChild2Sib) {
953 /* Variables:
954 * - \a pertinentChildCount
955 * - \a reachedEnd
956 * - \a _sum denotes the number of pertinent leaves in the frontier
957 * of the sequence.
958 * - \a currentNode is the currently examined node of the sequence.
959 * - \a nextSibling is a pointer needed for tracing the sequence.
960 * - \a oldSibling is a pointer needed for tracing the sequence.
961 */
962 // counts the pertinent children of the sequence.
963 int pertinentChildCount = 0;
964
965 PQNode<T, whaInfo*, Y>* currentNode = hChild2; // dummy
966 PQNode<T, whaInfo*, Y>* nextSibling = nullptr; // dummy
967 PQNode<T, whaInfo*, Y>* oldSibling = nullptr; // dummy
968
969 //Mark [[hChild2]] either as $b$- or as $h$-node.
970 if (hChild2->status() == PQNodeRoot::PQNodeStatus::Full) {
971 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
972 } else {
973 //1. node of sequence is Empty?
975 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
976 }
977
978 if (currentNode->getNodeInfo()->userStructInfo()->m_w
979 - currentNode->getNodeInfo()->userStructInfo()->m_h
980 > 0) {
981 pertinentChildCount++;
982 }
983
984 //Trace the sequence of pertinent children, marking the full children as $b$-node.
985 //If a partial or empty node is detected, the end of the sequence is
986 //reached and the partial node is marked as $h$-node.
987 nextSibling = hChild2Sib;
988 oldSibling = hChild2;
989
990 if (nextSibling != nullptr) {
991 currentNode = nextSibling;
992
993 // is false]as long as the end of the sequence is not detected; true otherwise.
994 bool reachedEnd = false;
995
996 while (!reachedEnd) {
997 if (currentNode->status() == PQNodeRoot::PQNodeStatus::Full) {
998 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
999 pertinentChildCount++;
1000 } else {
1001 if (currentNode->status() == PQNodeRoot::PQNodeStatus::Partial) {
1002 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
1003 if ((currentNode->getNodeInfo()->userStructInfo()->m_w
1004 - currentNode->getNodeInfo()->userStructInfo()->m_h)
1005 > 0) {
1006 pertinentChildCount++;
1007 }
1008 }
1009 reachedEnd = true;
1010 }
1011 if (!reachedEnd) {
1012 nextSibling = currentNode->getNextSib(oldSibling);
1013 if (nextSibling == nullptr) {
1014 reachedEnd = true;
1015 }
1016 oldSibling = currentNode;
1017 currentNode = nextSibling;
1018 }
1019 }
1020 }
1021
1022 return pertinentChildCount;
1023}
1024
1025template<class T, class Y>
1027 PQNodeRoot::PQNodeStatus label, whaType deleteType) {
1032#if 0
1033 PQNode<T,whaInfo*,Y> *currentNode = 0;
1034#endif
1035
1038 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1039 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1040 }
1041 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1042 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1043 }
1044 } else if (label == PQNodeRoot::PQNodeStatus::Partial) {
1046 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1047 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1048 }
1049 }
1050
1051 else {
1053 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1054 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1055 }
1056 }
1057}
1058
1059template<class T, class Y>
1061 /* Variables:
1062 * - \a sumParW = sum_{i in Par(\p nodePtr)} w_i, where
1063 * Par(\p nodePtr) denotes the set of partial children of \p nodePtr.
1064 * - \a sumMax1 = max_{i in Par(\p nodePtr)}1 {(w_i - h_i)}
1065 * where Par(\p nodePtr) denotes the set of partial children of
1066 * - \p nodePtr and max 1 the first maximum.
1067 * - \a sumMax2 = max_{i in Par(\p nodePtr)}2 {(w_i - h_i)}
1068 * where Par(\p nodePtr) denotes the set of partial children of
1069 * \p nodePtr and max2 the second maximum.
1070 * - \a currentNode
1071 * - \a hChild1 is a pointer to the \a hChild1 of \p nodePtr.
1072 * - \a hChild2 is a pointer to the \a hChild2 of \p nodePtr.
1073 * - \a aChild is a pointer to the \a aChild of \p nodePtr.
1074 */
1075 int sumParW = 0;
1076 int sumMax1 = 0;
1077 int sumMax2 = 0;
1078 PQNode<T, whaInfo*, Y>* currentNode = nullptr;
1079 PQNode<T, whaInfo*, Y>* hChild1 = nullptr;
1080 PQNode<T, whaInfo*, Y>* hChild2 = nullptr;
1081 PQNode<T, whaInfo*, Y>* aChild = nullptr;
1082
1083 /*
1084 Computes the $h$-number
1085 \[ h = \sum_{i \in Par(\mbox{[[nodePtr]]})}w_i - \max_{i\in
1086 Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}\]
1087 of the $P$-node [[nodePtr]].
1088 This is done by scanning all partial children stored in the
1089 [[partialChildrenStack]] of [[nodePtr]] summing up the $w_i$ for every
1090 $i \in Par(\mbox{[[nodePtr]]})$ and detecting
1091 \[\max_{i\in Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}.\]
1092 Since this can be simultaneously it also computes
1093 \[\max_{i\in Par(\mbox{[[nodePtr]]})}2\left\{(w_i - h_i)\right\}\]
1094 which is needed to determine the $a$-number.
1095 After successfully determining the $h$-number, the [[hChild1]] and
1096 [[hChild2]] of [[nodePtr]] are set.
1097 */
1098
1100 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1101 currentNode = (*it);
1102 sumParW = sumParW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1103 int sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1104 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1105 if (sumMax1 <= sumHelp) {
1106 sumMax2 = sumMax1;
1107 hChild2 = hChild1;
1108 sumMax1 = sumHelp;
1109 hChild1 = currentNode;
1110 } else if (sumMax2 <= sumHelp) {
1111 sumMax2 = sumHelp;
1112 hChild2 = currentNode;
1113 }
1114 }
1115 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = hChild1;
1116 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = hChild2;
1117 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumParW - sumMax1;
1118
1119 /*
1120 Compute the $a$-number of the $P$-node [[nodePtr]] where
1121 \[ a = \min \{ \alpha_1, \alpha_2\}\]
1122 such that
1123 \[\alpha_1 = \sum_{i \in P(\mbox{[[nodePtr]]})}w_i - \max_{i\in
1124 P(\mbox{[[nodePtr]]})}\left\{(w_i - h_i)\right\} \]
1125 which can be computed calling the function [[alpha1beta1Number]] and
1126 \[{\alpha}_2 \sum_{i \in Par(\mbox{[[nodePtr]]})}w_i -
1127 \max_{i\in Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}
1128 - \max_{i\in Par(\mbox{[[nodePtr]]})}2\left\{(w_i - h_i)\right\}\]
1129 This chunk uses two extra variables
1130 \begin{description}
1131 \item[[alpha1]] $ = \alpha_1$.
1132 \item[[alpha2]] $ = \alpha_2$.
1133 \end{description}
1134 */
1135 int alpha2 = sumParW - sumMax1 - sumMax2;
1136 int alpha1 = alpha1beta1Number(nodePtr, &aChild);
1137
1138 if (alpha1 <= alpha2) {
1139 nodePtr->getNodeInfo()->userStructInfo()->m_a = alpha1;
1140 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = aChild;
1141 } else {
1142 nodePtr->getNodeInfo()->userStructInfo()->m_a = alpha2;
1143 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
1144 }
1145}
1146
1147template<class T, class Y>
1149 /* Variables:
1150 * - sumAllW = sum_{i in P(\p nodePtr)} w_i, where
1151 * P(\p nodePtr) denotes the set of pertinent children of \p nodePtr.
1152 */
1153 int sumAllW = sumPertChild(nodePtr);
1154
1155 hNumQnode(nodePtr, sumAllW);
1156 aNumQnode(nodePtr, sumAllW);
1157}
1158
1159template<class T, class Y>
1161 /* Variables:
1162 * - \a sumLeft = sum_{i in P(\p nodePtr)} w_i - sum_{i
1163 * in P_L(\p nodePtr)}(w_i - h_i), where
1164 * P_L(\p nodePtr) denotes the maximal consecutive sequence
1165 * of pertinent children on the left side of the Q-node
1166 * \p nodePtr such that only the rightmost node in
1167 * P_L(\p nodePtr) may be partial.
1168 * - \a sumRight = sum_{i in P(\p [nodePtr)}w_i - sum_{i
1169 * in P_L(\p nodePtr)}(w_i - h_i), where
1170 * P_L(\p nodePtr) denotes the maximal consecutive sequence
1171 * of pertinent children on the left side of the Q-node
1172 * \p nodePtr such that only the rightmost node in
1173 * P_L(\p nodePtr) may be partial.
1174 * - \a fullLabel
1175 * - \a aChild is a pointer to the a-child of \p nodePtr.
1176 * - \a leftChild is a pointer to the left endmost child of \p nodePtr.
1177 * - \a rightChild is a pointer to the right endmost child of \p nodePtr.
1178 * - \a holdSibling is a pointer to a child of \p nodePtr, needed
1179 * to proceed through sequences of pertinent children.
1180 * - \a checkSibling is a pointer to a currently examined child of \p nodePtr.
1181 */
1182 int sumLeft = 0;
1183 int sumRight = 0;
1184 bool fullLabel = true;
1185 PQNode<T, whaInfo*, Y>* leftChild = nullptr;
1186 PQNode<T, whaInfo*, Y>* rightChild = nullptr;
1187 PQNode<T, whaInfo*, Y>* holdSibling = nullptr;
1188 PQNode<T, whaInfo*, Y>* checkSibling = nullptr;
1189
1190 //Compute the $h$-number of the $Q$-node [[nodePtr]]
1191
1192 //Get endmost children of the $Q$-node [[nodePtr]].
1193 leftChild = nodePtr->getEndmost(nullptr);
1194 rightChild = nodePtr->getEndmost(leftChild);
1195 OGDF_ASSERT(leftChild);
1196 OGDF_ASSERT(rightChild);
1197
1198 /*
1199 Check the left
1200 side of the $Q$-node [[nodePtr]] for the maximal consecutive sequence
1201 of full nodes, including at most one partial child at the end of the sequence.
1202
1203 The variable [[fullLabel]] is [[true]] as long as the [[while]]-loop
1204 has not detected an partial <b>or</b> empty child (see case [[if
1205 (leftChild->status() != Full)]]. Observe that the
1206 construction of the [[while]]-loop examines the last child if it is a
1207 partial child as well (see case [[if (leftChild->status() !=
1208 Empty)]] where in the computation in [[sumLeft]] we take advantage
1209 of the fact, that the $h$-number of a full child is zero).
1210 */
1211 while (fullLabel) {
1212 if (leftChild->status() != PQNodeRoot::PQNodeStatus::Full) {
1213 fullLabel = false;
1214 }
1215 if (leftChild->status() != PQNodeRoot::PQNodeStatus::Empty) {
1216 sumLeft = sumLeft + leftChild->getNodeInfo()->userStructInfo()->m_w
1217 - leftChild->getNodeInfo()->userStructInfo()->m_h;
1218 checkSibling = leftChild->getNextSib(holdSibling);
1219 if (checkSibling == nullptr) {
1220 fullLabel = false;
1221 }
1222 holdSibling = leftChild;
1223 leftChild = checkSibling;
1224 }
1225 }
1226
1227 /*
1228 Check the right
1229 side of the $Q$-node [[nodePtr]] for the maximal consecutive sequence
1230 of full nodes, including at most one partial child at the end of the sequence.
1231
1232 The variable [[fullLabel]] is [[true]] as long as the [[while]]-loop
1233 has not detected an partial <b>or</b> empty child (see case [[if
1234 (leftChild->status() != Full)]]. Observe that the
1235 construction of the [[while]]-loop examines the last child if it is a
1236 partial child as well (see case [[if (leftChild->status() !=
1237 Empty)]] where in the computation in [[sumLeft]] we take advantage
1238 of the fact, that the $h$-number of a full child is zero).
1239 */
1240 holdSibling = nullptr;
1241 checkSibling = nullptr;
1242 fullLabel = true;
1243 while (fullLabel) {
1244 if (rightChild->status() != PQNodeRoot::PQNodeStatus::Full) {
1245 fullLabel = false;
1246 }
1247 if (rightChild->status() != PQNodeRoot::PQNodeStatus::Empty) {
1248 sumRight = sumRight + rightChild->getNodeInfo()->userStructInfo()->m_w
1249 - rightChild->getNodeInfo()->userStructInfo()->m_h;
1250
1251 checkSibling = rightChild->getNextSib(holdSibling);
1252
1253 if (checkSibling == nullptr) {
1254 fullLabel = false;
1255 }
1256
1257 holdSibling = rightChild;
1258 rightChild = checkSibling;
1259 }
1260 }
1261
1262 /*
1263 After computing the number of pertinent leaves that stay in the $PQ$-tree
1264 when keeping either the left pertinent or the right pertinent side of
1265 the $Q$-node in the tree, this chunk chooses the side where the
1266 maximum number of leaves stay in the tree.
1267 Observe that we have to case the fact, that on both sides of the
1268 $Q$-node [[nodePtr]] no pertinent children are.
1269 */
1270 leftChild = nodePtr->getEndmost(nullptr);
1271 rightChild = nodePtr->getEndmost(leftChild);
1272 if (sumLeft == 0 && sumRight == 0) {
1273 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW;
1274 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = nullptr;
1275 } else if (sumLeft < sumRight) {
1276 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW - sumRight;
1277 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = rightChild;
1278 } else {
1279 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW - sumLeft;
1280 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = leftChild;
1281 }
1282}
1283
1284template<class T, class Y>
1286 /* Variables:
1287 * - \a beta1 = sum_{i in P(\p nodePtr} w_i - max_{i in P(\p nodePtr)}{(w_i =
1288 * a_i)}, where $P(\p nodePtr) denotes the set of all pertinent
1289 * children of the Q-node \p nodePtr. Depicts the a-number if just one
1290 * child of \p nodePtr is made a-node. Computed by calling the function alpha1beta1Number().
1291 * - \a beta2 = sum_{i in P(\p nodePtr)} w_i - max_{P_A(\p nodePtr)}{sum_{i in
1292 * P_A(\p nodePtr)}(w_i-h_i)}, where $P_A(\p nodePtr) is a maximal consecutive
1293 * sequence of pertinent children of the Q-node \p nodePtr such that all
1294 * nodes in P_A(\p nodePtr) except for the leftmost and rightmost ones are
1295 * full. Computed by this chunk.
1296 * - \a aSum depicts the number of pertinent leaves of the actual visited sequence.
1297 * - \a aHoldSum depicts the number of leaves in the actual maximum sequence.
1298 * - \a endReached is true if reached the end of the Q-node \p nodePtr and false otherwise.
1299 * - \a leftMost pointer to the leftmost end of the actual visited sequence.
1300 * - \a leftMostHold pointer to the leftmost end of the current maximum sequence.
1301 * - \a actualNode pointer to a child of the Q-node. It is the
1302 * node that is actually processed in the sequence of children.
1303 * - \a currentNode pointer to a node in a consecutive pertinent
1304 * sequence. Needed to process all nodes stored in \a sequence.
1305 * - \a lastChild is a pointer to the endmost child of the Q-node
1306 * that is opposite to the endmost child, where this chunk starts
1307 * processing the sequence of children.
1308 * - \a sequence is a SList of type PQNode<T,whaInfo*,Y>* storing
1309 * the nodes of a consecutive sequence that is actually processed.
1310 */
1311 PQNode<T, whaInfo*, Y>* aChild = nullptr;
1312 int beta1 = alpha1beta1Number(nodePtr, &aChild);
1313 int beta2 = 0;
1314 int aSum = 0;
1315 int aHoldSum = 0;
1316 bool endReached = 0;
1317 PQNode<T, whaInfo*, Y>* leftMost = nullptr;
1318 PQNode<T, whaInfo*, Y>* leftSib = nullptr;
1319 PQNode<T, whaInfo*, Y>* leftMostHold = nullptr;
1320 PQNode<T, whaInfo*, Y>* leftSibHold = nullptr;
1321 PQNode<T, whaInfo*, Y>* actualNode = nullptr;
1322 PQNode<T, whaInfo*, Y>* currentNode = nullptr;
1323 PQNode<T, whaInfo*, Y>* lastChild = nullptr;
1324 PQNode<T, whaInfo*, Y>* holdSibling = nullptr;
1325 PQNode<T, whaInfo*, Y>* checkSibling = nullptr;
1326 // pointer to the second endmost child
1327
1329
1330 actualNode = nodePtr->getEndmost(nullptr);
1331 lastChild = nodePtr->getEndmost(actualNode);
1332
1333 endReached = false;
1334 while (!endReached) {
1335 /*
1336 Process the children of a $Q$-node [[nodePtr]] from one end of [[nodePtr]] to the
1337 other, searching for a consecutive sequence of pertinent nodes with
1338 the maximum number of pertinent leaves, such that all nodes of the
1339 pertinent sequence are full except possibly the two endmost children
1340 which are allowed to be partial.
1341 */
1342 if (sequence.empty()) {
1343 /*
1344 Currently no consecutive sequence of pertinent children
1345 is detected while scanning the children of the $Q$-node.
1346 Check the [[actualNode]] if it is the first child of
1347 such a sequence. If so, place [[actualNode]] on the stack [[sequence]].
1348 */
1349 if (actualNode->status() != PQNodeRoot::PQNodeStatus::Empty) {
1350 sequence.pushFront(actualNode);
1351 leftMost = nullptr;
1352 leftSib = nullptr;
1353 }
1354 } else {
1355 /*
1356 [[actualNode]] is a sibling of a consecutive pertinent sequence that has
1357 been detected in an earlier step, while scanning the children of the $Q$-node.
1358 This chunk cases on the status of the [[actualNode]].
1359
1360 In case that the status of
1361 the [[actualNode]] is [[Full]], [[actualNode]] is included into the
1362 sequence of pertinent children by pushing it onto the stack
1363 [[sequence]].
1364
1365 If [[actualNode]] is Empty, we have reached the end of
1366 the actual consecutive sequence of pertinent children. In this case
1367 the $a$-numbers of the nodes in the sequence have to be summed up.
1368
1369 If the [[actualNode]] is [[Partial]], the end of the consecutive sequence
1370 is reached and similar actions to the [[Empty]] have to be
1371 performed. However, [[actualNode]] might mark the beginning of
1372 another pertinent sequence. Hence it has to be stored again in [[sequence]].
1373 */
1374 if (actualNode->status() == PQNodeRoot::PQNodeStatus::Full) {
1375 sequence.pushFront(actualNode);
1376 }
1377
1378 else if (actualNode->status() == PQNodeRoot::PQNodeStatus::Empty) {
1379 /*
1380 If [[actualNode]] is Empty, the end of
1381 the actual consecutive sequence of pertinent children is reached . In
1382 this case, all nodes of the currently examined consecutive sequence are stored in
1383 [[sequence]].
1384 They are removed from the stack and their $a$-numbers are summed up.
1385 If necessary, the sequence with the largest number of full leaves in
1386 its frontier is updated.
1387 */
1388 aSum = 0;
1389
1390 while (!sequence.empty()) {
1391 currentNode = sequence.popFrontRet();
1392 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1393 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1394 if (sequence.size() == 1) {
1395 leftSib = currentNode;
1396 }
1397 }
1398 leftMost = currentNode;
1399
1400 if (aHoldSum < aSum) {
1401 aHoldSum = aSum;
1402 leftMostHold = leftMost;
1403 leftSibHold = leftSib;
1404 }
1405
1406 } else {
1407 /*
1408 If the [[actualNode]] is [[Partial]], the end of the consecutive sequence
1409 is reached. In
1410 this case, all nodes of the currently examined consecutive sequence are stored in
1411 [[sequence]].
1412 They are removed from the stack and their $a$-numbers are summed up.
1413 If necessary, the sequence with the largest number of full leaves in
1414 its frontier is updated.
1415 However, [[actualNode]] might mark the beginning of
1416 another pertinent sequence. Hence it has to be stored again in [[sequence]].
1417 */
1418 sequence.pushFront(actualNode);
1419 aSum = 0;
1420 while (!sequence.empty()) {
1421 currentNode = sequence.popFrontRet();
1422 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1423 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1424 if (sequence.size() == 1) {
1425 leftSib = currentNode;
1426 }
1427 }
1428 if (leftSib == nullptr) {
1429 leftSib = actualNode;
1430 }
1431 leftMost = currentNode;
1432
1433 if (aHoldSum < aSum) {
1434 aHoldSum = aSum;
1435 leftMostHold = leftMost;
1436 leftSibHold = leftSib;
1437 }
1438
1439 sequence.pushFront(actualNode);
1440 }
1441 }
1442
1443 // Get the next sibling
1444 if (actualNode != lastChild) {
1445 checkSibling = actualNode->getNextSib(holdSibling);
1446 holdSibling = actualNode;
1447 actualNode = checkSibling;
1448 } else {
1449 // End of Q-node reached.
1450 endReached = true;
1451 }
1452 }
1453
1454
1455 /*
1456 After processing
1457 the last child of the $Q$-node, this chunk checks, if this child was
1458 part of a pertinent consecutive sequence. If this is the case, the
1459 stack storing this seuquence was not emptied and the number of
1460 pertinent leaves in its frontier was not computed. Furhtermore the
1461 last child was not stored in [[sequence]].
1462 This chunk does the necessary updates for the last consecutive sequence.
1463 */
1464 if (!sequence.empty()) {
1465 aSum = 0;
1466 while (!sequence.empty()) {
1467 currentNode = sequence.popFrontRet();
1468 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1469 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1470 if (sequence.size() == 1) {
1471 leftSib = currentNode;
1472 }
1473 }
1474 leftMost = currentNode;
1475
1476 if (aHoldSum < aSum) {
1477 aHoldSum = aSum;
1478 leftMostHold = leftMost;
1479 leftSibHold = leftSib;
1480 }
1481 }
1482 /*
1483 After computing
1484 ${\beta}_1$ and ${\beta}_2$, describing the number of pertinent leaves
1485 that have to be deleted when choosing either one node to be an
1486 $a$-node or a complete sequence, this chunk gets the $a$-number of the
1487 $Q$-node [[nodePtr]] by choosing
1488 \[a = \min\{{\beta}_1,{\beta}_2\]
1489 Also set [[aChild]] and [[hChild2]] of [[nodePtr]] according to the
1490 chosen minimum.
1491 */
1492 beta2 = sumAllW - aHoldSum;
1493 if (beta2 < beta1) {
1494 nodePtr->getNodeInfo()->userStructInfo()->m_a = beta2;
1495 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = leftMostHold;
1496 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2Sib = leftSibHold;
1497 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
1498 } else {
1499 nodePtr->getNodeInfo()->userStructInfo()->m_a = beta1;
1500 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = nullptr;
1501 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2Sib = nullptr;
1502 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = aChild;
1503 }
1504}
1505
1506template<class T, class Y>
1508 PQNode<T, whaInfo*, Y>** aChild) {
1509 /* Variables:
1510 * - \a sumMaxA = max_{i in P(\p nodePtr)}{(w_i = a_i)}.
1511 * - \a sumAllW = w = sum_{i in P(\p nodePtr)}w_i.
1512 * - \a sumHelp is a help variable.
1513 * - \a currentNode depicts a currently examined pertinent node.
1514 *
1515 * The function uses two while loops over the parial and the full
1516 * children of \p nodePtr. It hereby computes the values \p w and
1517 * max_{i in P(\p nodePtr}{(w_i = a_i)}.
1518 * After finishing the while loops, the function
1519 * alpha1beta1Number() returns the numbers alpha_1 = beta_1
1520 * and the \p aChild.
1521 */
1522 int sumMaxA = 0;
1523 int sumAllW = 0;
1524 int sumHelp = 0;
1525 PQNode<T, whaInfo*, Y>* currentNode = nullptr;
1526
1528 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1529 currentNode = (*it);
1530 sumAllW = sumAllW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1531 sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1532 - currentNode->getNodeInfo()->userStructInfo()->m_a;
1533 if (sumMaxA < sumHelp) {
1534 sumMaxA = sumHelp;
1535 (*aChild) = currentNode;
1536 }
1537 }
1538
1539 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1540 currentNode = (*it);
1541 sumAllW = sumAllW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1542 sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1543 - currentNode->getNodeInfo()->userStructInfo()->m_a;
1544 if (sumMaxA < sumHelp) {
1545 sumMaxA = sumHelp;
1546 (*aChild) = currentNode;
1547 }
1548 }
1549 return sumAllW - sumMaxA;
1550}
1551
1552template<class T, class Y>
1554 /* Variables:
1555 * - \a it depicts a currently examined pertinent node.
1556 * - \a sum = \a w = sum_{i in P(\p nodePtr)}w_i.
1557 *
1558 * The function uses two for loops over the parial and the full
1559 * children of \p nodePtr. It hereby computes the values $w$ stored in \a sum.
1560 * After finishing the while loops, the function
1561 * sumPertChild() returns the number \a w.
1562 */
1563 int sum = 0;
1565 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1566 sum = sum + (*it)->getNodeInfo()->userStructInfo()->m_w;
1567 }
1568 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1569 sum = sum + (*it)->getNodeInfo()->userStructInfo()->m_w;
1570 }
1571
1572 return sum;
1573}
1574
1575template<class T, class Y>
1577 if (nodePtr->parent() == nullptr) {
1578 return nullptr;
1579 } else if (nodePtr->parent()->status() != PQNodeRoot::PQNodeStatus::Eliminated) {
1580 return nodePtr->parent();
1581 } else {
1582 PQNode<T, whaInfo*, Y>* nextNode = nodePtr;
1583 PQNode<T, whaInfo*, Y>* currentNode = nullptr;
1584 PQNode<T, whaInfo*, Y>* oldSib = nullptr;
1586
1587 currentNode = nodePtr->getNextSib(nullptr);
1588 oldSib = nodePtr;
1589 L.pushFront(nodePtr);
1590 while (currentNode->parent()->status() == PQNodeRoot::PQNodeStatus::Eliminated) {
1591 L.pushFront(currentNode);
1592 nextNode = currentNode->getNextSib(oldSib);
1593 oldSib = currentNode;
1594 currentNode = nextNode;
1595 }
1596 while (!L.empty()) {
1597 L.popFrontRet()->parent(currentNode->parent());
1598 }
1599 return currentNode->parent();
1600 }
1601}
1602
1603}
Declaration and implementation of ArrayBuffer class.
Declaration of doubly linked lists and iterators.
Declaration and implementation of the class PQNode.
Declaration and implementation of the class PQNodeKey.
Declaration and implementation of the class PQNodeRoot.
Declaration and implementation of the class PQTree.
Declaration of singly linked lists and iterators.
Declaration and implementation of list-based queues (classes QueuePure<E> and Queue<E>).
Basic declarations, included by all source files.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:64
void push(E e)
Puts a new element in the buffer.
Encapsulates a pointer to a list element.
Definition List.h:113
bool valid() const
Returns true iff the iterator points to an element.
Definition List.h:153
The class template MaxSequencePQTree is designed to compute a maximal consecutive sequence of pertine...
int determineMinRemoveSequence(SListPure< PQLeafKey< T, whaInfo *, Y > * > &leafKeys, SList< PQLeafKey< T, whaInfo *, Y > * > &eliminatedKeys)
Computes the maximal pertinent sequence S' of elements of the set S, that can be reduced in a PQ-tree...
void markPertinentChildren(PQNode< T, whaInfo *, Y > *nodePtr, PQNodeRoot::PQNodeStatus label, whaType deleteType)
Marks all full and/or partial children of nodePtr as either an a-, b-, h- or w-node.
PQNode< T, whaInfo *, Y > * GetParent(PQNode< T, whaInfo *, Y > *nodePtr)
Computes for the node nodePtr its valid parent in the PQ-tree.
void aNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the a-number of the partial Q-node nodePtr.
void findMinWHASequence(ArrayBuffer< PQNode< T, whaInfo *, Y > * > &archiv, SList< PQLeafKey< T, whaInfo *, Y > * > &eliminatedKeys)
Checks the [w,h,a]-number of the pertinent root.
SListPure< PQNode< T, whaInfo *, Y > * > eliminatedNodes
Used to store all eliminated nodes (status == PQNodeRoot::PQNodeStatus::Eliminated) of the PQTree.
int alpha1beta1Number(PQNode< T, whaInfo *, Y > *nodePtr, PQNode< T, whaInfo *, Y > **aChild)
Returns alpha_1 = beta_1 = sum_{i in P(nodePtr)} w_i - max_{i in P(nodePtr)}{(w_i = a_i)},...
virtual void CleanNode(PQNode< T, whaInfo *, Y > *nodePtr)
Frees the memory allocated for the node information class of a node in the PQTree.
int sumPertChild(PQNode< T, whaInfo *, Y > *nodePtr)
Returns w = sum_{i in P(nodePtr)}w_i, where nodePtr is any pertinent node of the PQ-tree.
SListPure< PQNode< T, whaInfo *, Y > * > cleanUp
Used to store all pertinent Nodes of the pertinent subtree before removing the minimal pertinent subs...
void haNumQnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of the partial Q-node nodePtr.
virtual bool Bubble(SListPure< PQLeafKey< T, whaInfo *, Y > * > &leafKeys)
The function Bubble() is an overloaded function of the base template class PQTree.
int setAchildren(PQNode< T, whaInfo *, Y > *hChild2, PQNode< T, whaInfo *, Y > *hChild2Sib)
Traces all children of the largest consecutive sequence of pertinent children of a Q-node.
int setHchild(PQNode< T, whaInfo *, Y > *hChild1)
Processes the children of a Q-node, marking a full sequence of children with at most incident partial...
virtual void emptyAllPertinentNodes()
Does a clean up after a reduction.
void hNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the h-number of the partial Q-node nodePtr.
void haNumPnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of a P-node nodePtr.
virtual void clientDefinedEmptyNode(PQNode< T, whaInfo *, Y > *nodePtr)
Does a clean up of a node. Called by emptyAllPertinentNodes.
void setNodePointer(PQNode< T, X, Y > *pqNode)
The function setNodePointer() sets the private member m_nodePointer.
Definition PQBasicKey.h:156
The class template PQLeafKey is a derived class of class template PQBasicKey.
Definition PQLeafKey.h:84
The class template PQBasicKey is an abstract base class.
Definition PQNode.h:56
virtual PQNodeType type() const =0
Returns the variable PQInternalNode::m_type in the derived class PQLeaf and PQInternalNode.
bool setNodeInfo(PQNodeKey< T, X, Y > *pointerToInfo)
Sets the pointer m_pointerToInfo to the specified adress of pointerToInfo.
Definition PQNode.h:303
PQNodeKey< T, X, Y > * getNodeInfo() const
Returns the identification number of a node.
Definition PQNode.h:161
virtual PQNodeStatus status() const =0
Returns the variable PQLeaf::m_status in the derived class PQLeaf and PQInternalNode.
PQNode< T, X, Y > * getEndmost(PQNode< T, X, Y > *other) const
Returns one of the endmost children of node, if node is a Q-node.
Definition PQNode.h:135
int childCount() const
Returns the number of children of a node.
Definition PQNode.h:201
virtual PQLeafKey< T, X, Y > * getKey() const =0
getKey() returns a pointer to the PQLeafKeyof a node, in case that the node is supposed to have a key...
virtual PQNodeMark mark() const =0
mark() returns the variable PQLeaf::m_mark in the derived class PQLeaf and PQInternalNode.
PQNode< T, X, Y > * getNextSib(PQNode< T, X, Y > *other) const
The function getNextSib() returns one of the siblings of the node.
Definition PQNode.h:187
PQNode< T, X, Y > * parent() const
The function parent() returns a pointer to the parent of a node.
Definition PQNode.h:213
int pertChildCount() const
Returs the number of pertinent children of a node.
Definition PQNode.h:234
The class template PQNodeKey is a derived class of class template PQBasicKey.
Definition PQNodeKey.h:54
@ Eliminated
Nodes removed during the template reduction are marked as as Eliminated. Their memory is not freed....
@ WhaDelete
Nodes that need to be removed in order to obtain a maximal pertinent sequence are marked WhaDelete.
@ PertRoot
The pertinent Root is marked PertRoot during the clean up after a reduction. Technical.
List< PQNode< T, whaInfo *, Y > * > * partialChildren(PQNode< T, whaInfo *, Y > *nodePtr)
Definition PQTree.h:660
void emptyNode(PQNode< T, whaInfo *, Y > *nodePtr)
Cleans up all stacks, flags and pointers of a pertinent node that has been visited during the reducti...
Definition PQTree.h:1779
virtual void emptyAllPertinentNodes()
Cleans up all flags that have been set in the pertinent nodes during the reduction process.
Definition PQTree.h:1744
List< PQNode< T, whaInfo *, Y > * > * fullChildren(PQNode< T, whaInfo *, Y > *nodePtr)
Definition PQTree.h:658
The parameterized class Queue<E> implements list-based queues.
Definition Queue.h:205
E pop()
Removes front element and returns it.
Definition Queue.h:336
bool empty() const
Returns true iff the queue is empty.
Definition Queue.h:243
iterator append(const E &x)
Adds x at the end of queue.
Definition Queue.h:324
Singly linked lists (maintaining the length of the list).
Definition SList.h:845
int size() const
Returns the number of elements in the list.
Definition SList.h:880
E popFrontRet()
Removes the first element from the list and returns it.
Definition SList.h:971
SListIterator< E > pushFront(const E &x)
Adds element x at the beginning of the list.
Definition SList.h:926
Encapsulates a pointer to an ogdf::SList element.
Definition SList.h:104
bool valid() const
Returns true iff the iterator points to an element.
Definition SList.h:134
Singly linked lists.
Definition SList.h:191
bool empty() const
Returns true iff the list is empty.
Definition SList.h:238
E popFrontRet()
Removes the first element from the list and returns it.
Definition SList.h:544
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition SList.h:459
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
whaType
The definitions for W, B, H and A describe the type of a node during the computation of the maximal p...
Definition whaInfo.h:49
Declaration of class whaInfo.