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