Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

MaxSequencePQTree.h
Go to the documentation of this file.
1 
35 #pragma once
36 
37 #include <ogdf/basic/ArrayBuffer.h>
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 
48 namespace ogdf {
49 template<class T, class X, class Y>
50 class PQLeafKey;
51 
103 template<class T, class Y>
104 class MaxSequencePQTree : public PQTree<T, whaInfo*, Y> {
105 public:
107 
108  MaxSequencePQTree() : PQTree<T, whaInfo*, Y>() { }
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 
134  virtual void clientDefinedEmptyNode(PQNode<T, whaInfo*, Y>* nodePtr);
135 
137 
181  virtual void emptyAllPertinentNodes();
182 
209  SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys);
210 
211 protected:
214 
229  virtual bool Bubble(SListPure<PQLeafKey<T, whaInfo*, Y>*>& leafKeys);
230 
252 
260 
269 
270 private:
293  SList<PQLeafKey<T, whaInfo*, Y>*>& eliminatedKeys);
294 
305  int setHchild(PQNode<T, whaInfo*, Y>* hChild1);
306 
321 
335  whaType deleteType);
336 
338  void haNumPnode(PQNode<T, whaInfo*, Y>* nodePtr);
339 
345  void haNumQnode(PQNode<T, whaInfo*, Y>* nodePtr);
346 
365  void aNumQnode(PQNode<T, whaInfo*, Y>* nodePtr, int sumAllW);
366 
372  void hNumQnode(PQNode<T, whaInfo*, Y>* nodePtr, int sumAllW);
373 
384 
389  int sumPertChild(PQNode<T, whaInfo*, Y>* nodePtr);
390 };
391 
392 template<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());
447  }
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) {
469  (*itn)->mark(PQNodeRoot::PQNodeMark::Unmarked);
470  }
471 
472  return true;
473 }
474 
475 template<class T, class Y>
477  if (nodePtr->getNodeInfo()) {
478  delete nodePtr->getNodeInfo()->userStructInfo();
479  delete nodePtr->getNodeInfo();
480  }
481 }
482 
483 template<class T, class Y>
485  if (nodePtr->status() == PQNodeRoot::PQNodeStatus::Eliminated) {
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 
497 template<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;
522  if (nodePtr->status() == PQNodeRoot::PQNodeStatus::ToBeDeleted) {
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 
536 template<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]].
587  + nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount;
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 
667 template<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)) {
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 =
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 =
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;
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;
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;
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);
858  nodePtr->pertChildCount(1);
859  } else {
860  markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
861  whaType::W);
862  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;
890  }
891 }
892 
893 template<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 
950 template<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) {
972  } else {
973  //1. node of sequence is Empty?
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 
1025 template<class T, class Y>
1027  PQNodeRoot::PQNodeStatus label, whaType deleteType) {
1032 #if 0
1033  PQNode<T,whaInfo*,Y> *currentNode = 0;
1034 #endif
1035 
1036  if (label == PQNodeRoot::PQNodeStatus::Pertinent) {
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 
1059 template<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 
1147 template<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 
1159 template<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 
1284 template<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 
1328  SList<PQNode<T, whaInfo*, Y>*> sequence;
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 
1506 template<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 
1552 template<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 
1575 template<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 }
ogdf::ArrayBuffer
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition: Array.h:53
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::MaxSequencePQTree::GetParent
PQNode< T, whaInfo *, Y > * GetParent(PQNode< T, whaInfo *, Y > *nodePtr)
Computes for the node nodePtr its valid parent in the PQ-tree.
Definition: MaxSequencePQTree.h:1576
ArrayBuffer.h
Declaration and implementation of ArrayBuffer class.
ogdf::Queue::append
iterator append(const E &x)
Adds x at the end of queue.
Definition: Queue.h:324
ogdf::whaInfo::m_notVisitedCount
int m_notVisitedCount
Definition: whaInfo.h:108
ogdf::PQNodeRoot::PQNodeType::PNode
@ PNode
PQNode.h
Declaration and implementation of the class PQNode.
ogdf::MaxSequencePQTree::haNumQnode
void haNumQnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of the partial Q-node nodePtr.
Definition: MaxSequencePQTree.h:1148
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::begin
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
ogdf::whaInfo::m_a
int m_a
Definition: whaInfo.h:97
ogdf::PQLeafKey
The class template PQLeafKey is a derived class of class template PQBasicKey.
Definition: PQInternalNode.h:40
ogdf::whaInfo::m_hChild1
PQNodeRoot * m_hChild1
Definition: whaInfo.h:116
ogdf::whaType::A
@ A
ogdf::SListIteratorBase
Encapsulates a pointer to an ogdf::SList element.
Definition: SList.h:50
ogdf::PQNodeRoot::PQNodeStatus::WhaDelete
@ WhaDelete
Nodes that need to be removed in order to obtain a maximal pertinent sequence are marked WhaDelete.
ogdf::whaInfo::m_w
int m_w
Definition: whaInfo.h:91
ogdf::MaxSequencePQTree::MaxSequencePQTree
MaxSequencePQTree()
Definition: MaxSequencePQTree.h:108
ogdf::PQNode::setNodeInfo
bool setNodeInfo(PQNodeKey< T, X, Y > *pointerToInfo)
Sets the pointer m_pointerToInfo to the specified adress of pointerToInfo.
Definition: PQNode.h:303
ogdf::SList
Singly linked lists (maintaining the length of the list).
Definition: SList.h:845
ogdf::SList::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: SList.h:971
ogdf::ListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: List.h:153
Queue.h
Declaration and implementation of list-based queues (classes QueuePure<E> and Queue<E>).
ogdf::PQNode::mark
virtual PQNodeMark mark() const =0
mark() returns the variable PQLeaf::m_mark in the derived class PQLeaf and PQInternalNode.
ogdf::PQTree
Definition: PQNode.h:53
ogdf::PQNodeRoot::PQNodeMark::Unmarked
@ Unmarked
ogdf::MaxSequencePQTree::findMinWHASequence
void findMinWHASequence(ArrayBuffer< PQNode< T, whaInfo *, Y > * > &archiv, SList< PQLeafKey< T, whaInfo *, Y > * > &eliminatedKeys)
Checks the [w,h,a]-number of the pertinent root.
Definition: MaxSequencePQTree.h:668
ogdf::whaInfo::m_h
int m_h
Definition: whaInfo.h:85
PQNodeRoot.h
Declaration and implementation of the class PQNodeRoot.
ogdf::whaInfo::defaultValues
void defaultValues()
Definition: whaInfo.h:72
ogdf::MaxSequencePQTree::sumPertChild
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.
Definition: MaxSequencePQTree.h:1553
ogdf::SListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: SList.h:134
PQTree.h
Declaration and implementation of the class PQTree.
ogdf::MaxSequencePQTree::eliminatedNodes
SListPure< PQNode< T, whaInfo *, Y > * > eliminatedNodes
Used to store all eliminated nodes (status == PQNodeRoot::PQNodeStatus::Eliminated) of the PQTree.
Definition: MaxSequencePQTree.h:268
ogdf::PQNodeRoot::PQNodeStatus::Pertinent
@ Pertinent
ogdf::MaxSequencePQTree::haNumPnode
void haNumPnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of a P-node nodePtr.
Definition: MaxSequencePQTree.h:1060
ogdf::PQTree::emptyAllPertinentNodes
virtual void emptyAllPertinentNodes()
Cleans up all flags that have been set in the pertinent nodes during the reduction process.
Definition: PQTree.h:1744
ogdf::whaType::H
@ H
ogdf::MaxSequencePQTree::Bubble
virtual bool Bubble(SListPure< PQLeafKey< T, whaInfo *, Y > * > &leafKeys)
The function Bubble() is an overloaded function of the base template class PQTree.
Definition: MaxSequencePQTree.h:393
ogdf::whaType::B
@ B
ogdf::PQNodeRoot::PQNodeType::Leaf
@ Leaf
ogdf::SListPure::empty
bool empty() const
Returns true iff the list is empty.
Definition: SList.h:238
ogdf::whaType
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
PQNodeKey.h
Declaration and implementation of the class PQNodeKey.
ogdf::PQNode::getKey
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...
ogdf::whaInfo::m_aChild
PQNodeRoot * m_aChild
Definition: whaInfo.h:112
ogdf::PQNode::pertChildCount
int pertChildCount() const
Returs the number of pertinent children of a node.
Definition: PQNode.h:234
ogdf::PQNodeRoot::PQNodeStatus::Empty
@ Empty
ogdf::Queue::pop
E pop()
Removes front element and returns it.
Definition: Queue.h:336
ogdf::SList::size
int size() const
Returns the number of elements in the list.
Definition: SList.h:880
SList.h
Declaration of singly linked lists and iterators.
ogdf::PQNodeKey::userStructInfo
virtual X userStructInfo()
Returns m_userStructInfo.
Definition: PQNodeKey.h:69
ogdf::PQNodeRoot::PQNodeStatus::Partial
@ Partial
ogdf::PQNode::status
virtual PQNodeStatus status() const =0
Returns the variable PQLeaf::m_status in the derived class PQLeaf and PQInternalNode.
ogdf::PQNode::getNextSib
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
ogdf::ArrayBuffer::push
void push(E e)
Puts a new element in the buffer.
Definition: ArrayBuffer.h:217
ogdf::SListPure
Singly linked lists.
Definition: SList.h:52
ogdf::MaxSequencePQTree::~MaxSequencePQTree
~MaxSequencePQTree()
Definition: MaxSequencePQTree.h:110
ogdf::MaxSequencePQTree::aNumQnode
void aNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the a-number of the partial Q-node nodePtr.
Definition: MaxSequencePQTree.h:1285
ogdf::PQNode::getEndmost
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
ogdf::Queue
The parameterized class Queue<E> implements list-based queues.
Definition: Queue.h:205
ogdf::SList::pushFront
SListIterator< E > pushFront(const E &x)
Adds element x at the beginning of the list.
Definition: SList.h:926
ogdf::MaxSequencePQTree::determineMinRemoveSequence
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...
Definition: MaxSequencePQTree.h:537
ogdf::PQNode::type
virtual PQNodeType type() const =0
Returns the variable PQInternalNode::m_type in the derived class PQLeaf and PQInternalNode.
ogdf::PQNodeRoot::PQNodeStatus::Full
@ Full
whaInfo.h
Declaration of class whaInfo.
ogdf::PQNodeKey< T, whaInfo *, Y >
ogdf::MaxSequencePQTree::setAchildren
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.
Definition: MaxSequencePQTree.h:951
ogdf::MaxSequencePQTree::clientDefinedEmptyNode
virtual void clientDefinedEmptyNode(PQNode< T, whaInfo *, Y > *nodePtr)
Does a clean up of a node. Called by emptyAllPertinentNodes.
Definition: MaxSequencePQTree.h:484
ogdf::Queue::empty
bool empty() const
Returns true iff the queue is empty.
Definition: Queue.h:243
ogdf::SListPure::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: SList.h:544
ogdf::PQNodeRoot::PQNodeStatus::Eliminated
@ Eliminated
Nodes removed during the template reduction are marked as as Eliminated. Their memory is not freed....
ogdf::PQNode::getNodeInfo
PQNodeKey< T, X, Y > * getNodeInfo() const
Returns the identification number of a node.
Definition: PQNode.h:161
ogdf::PQNodeRoot::PQNodeStatus
PQNodeStatus
Definition: PQNodeRoot.h:50
ogdf::MaxSequencePQTree
The class template MaxSequencePQTree is designed to compute a maximal consecutive sequence of pertine...
Definition: MaxSequencePQTree.h:104
basic.h
Basic declarations, included by all source files.
ogdf::MaxSequencePQTree::alpha1beta1Number
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)},...
Definition: MaxSequencePQTree.h:1507
ogdf::whaType::W
@ W
ogdf::MaxSequencePQTree::markPertinentChildren
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.
Definition: MaxSequencePQTree.h:1026
ogdf::PQNodeRoot::PQNodeMark::Queued
@ Queued
List.h
Declaration of doubly linked lists and iterators.
ogdf::whaInfo::m_hChild2
PQNodeRoot * m_hChild2
Definition: whaInfo.h:121
ogdf::whaInfo::m_pertLeafCount
int m_pertLeafCount
Definition: whaInfo.h:104
ogdf::whaInfo::m_hChild2Sib
PQNodeRoot * m_hChild2Sib
Definition: whaInfo.h:126
ogdf::MaxSequencePQTree::cleanUp
SListPure< PQNode< T, whaInfo *, Y > * > cleanUp
Used to store all pertinent Nodes of the pertinent subtree before removing the minimal pertinent subs...
Definition: MaxSequencePQTree.h:259
ogdf::ListIteratorBase
Encapsulates a pointer to a list element.
Definition: List.h:51
ogdf::SListPure::pushFront
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition: SList.h:459
ogdf::whaInfo::m_deleteType
whaType m_deleteType
Definition: whaInfo.h:101
ogdf::PQNode::childCount
int childCount() const
Returns the number of children of a node.
Definition: PQNode.h:201
ogdf::MaxSequencePQTree::CleanNode
virtual void CleanNode(PQNode< T, whaInfo *, Y > *nodePtr)
Frees the memory allocated for the node information class of a node in the PQTree.
Definition: MaxSequencePQTree.h:476
ogdf::MaxSequencePQTree::hNumQnode
void hNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the h-number of the partial Q-node nodePtr.
Definition: MaxSequencePQTree.h:1160
ogdf::MaxSequencePQTree::setHchild
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...
Definition: MaxSequencePQTree.h:894
ogdf::PQNode::parent
PQNode< T, X, Y > * parent() const
The function parent() returns a pointer to the parent of a node.
Definition: PQNode.h:213
ogdf::MaxSequencePQTree::emptyAllPertinentNodes
virtual void emptyAllPertinentNodes()
Does a clean up after a reduction.
Definition: MaxSequencePQTree.h:498
ogdf::PQNodeRoot::PQNodeStatus::PertRoot
@ PertRoot
The pertinent Root is marked PertRoot during the clean up after a reduction. Technical.
ogdf::PQNodeRoot::PQNodeStatus::ToBeDeleted
@ ToBeDeleted
ogdf::whaInfo
Definition: whaInfo.h:51
ogdf::PQNode< T, whaInfo *, Y >