Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

HeavyPathDecomposition.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/Math.h>
36 
37 #include <vector>
38 
39 namespace ogdf {
40 namespace steiner_tree {
41 
46 template<typename T>
48 private:
52 
53  std::vector<std::vector<node>> chains;
54  std::vector<std::vector<node>> chainsOfTerminals;
61  std::vector<node> fatherOfChain;
62 
63  std::vector<std::vector<T>> longestDistToSteinerAncestorOnChain;
64  std::vector<std::vector<T>> longestDistToSteinerAncestorSegTree;
65 
70  void buildMaxSegmentTree(std::vector<T>& segmentTree, const int nodeIndex, const int left,
71  const int right, const std::vector<T>& baseArray) const {
72  if (left == right) { // leaf
73  segmentTree[nodeIndex] = baseArray[left];
74  return;
75  }
76 
77  int middle = (left + right) >> 1;
78  int leftNodeIndex = nodeIndex + nodeIndex + 1;
79  int rightNodeIndex = leftNodeIndex + 1;
80 
81  buildMaxSegmentTree(segmentTree, leftNodeIndex, left, middle, baseArray);
82  buildMaxSegmentTree(segmentTree, rightNodeIndex, middle + 1, right, baseArray);
83 
84  segmentTree[nodeIndex] = max(segmentTree[leftNodeIndex], segmentTree[rightNodeIndex]);
85  }
86 
91  T getMaxSegmentTree(const std::vector<T>& segmentTree, const int nodeIndex, const int left,
92  const int right, const int queryLeft, const int queryRight) const {
93  if (queryLeft > queryRight || left > queryRight || queryLeft > right) {
94  return 0;
95  }
96 
97  if (queryLeft <= left && right <= queryRight) { // included
98  return segmentTree[nodeIndex];
99  }
100 
101  int middleIndex = (left + right) >> 1;
102  int leftNodeIndex = nodeIndex + nodeIndex + 1;
103  int rightNodeIndex = leftNodeIndex + 1;
104 
105  T maxValue(0);
106  if (queryLeft <= middleIndex) {
108  getMaxSegmentTree(segmentTree, leftNodeIndex, left, middleIndex, queryLeft,
109  queryRight));
110  }
111  if (queryRight > middleIndex) {
113  getMaxSegmentTree(segmentTree, rightNodeIndex, middleIndex + 1, right,
114  queryLeft, queryRight));
115  }
116 
117  return maxValue;
118  }
119 
124  T distanceToAncestor(node v, node ancestor) const {
125  if (ancestor == nullptr) {
126  return distanceToRoot[v];
127  }
128  return distanceToRoot[v] - distanceToRoot[ancestor];
129  }
130 
137  longestDistToSteinerAncestorOnChain.resize((int)chains.size());
138  for (int i = 0; i < (int)chains.size(); ++i) {
139  longestDistToSteinerAncestorOnChain[i].resize((int)chains[i].size());
140  for (int j = 0; j < (int)chains[i].size(); ++j) {
143  if (j > 0) {
146  }
147  }
148  }
149  }
150 
157  longestDistToSteinerAncestorSegTree.resize((int)chains.size());
158  for (int i = 0; i < (int)chains.size(); ++i) {
159  longestDistToSteinerAncestorSegTree[i].resize(4 * (int)chains[i].size());
160 
161  std::vector<T> distanceToSteinerAncestor_byPosition;
162  distanceToSteinerAncestor_byPosition.resize(chains[i].size());
163  for (int j = 0; j < (int)chains[i].size(); ++j) {
164  distanceToSteinerAncestor_byPosition[j] =
166  }
167 
169  (int)chains[i].size() - 1, distanceToSteinerAncestor_byPosition);
170  }
171  }
172 
177  void dfsHeavyPathDecomposition(node v, node closestSteinerUpNode) {
178  weightOfSubtree[v] = 1;
179  node heaviestSon = nullptr;
180  closestSteinerAncestor[v] = closestSteinerUpNode;
181 
182  for (adjEntry adj : v->adjEntries) {
183  edge e = adj->theEdge();
184  node son = adj->twinNode();
185 
186  if (weightOfSubtree[son] != 0) { // the parent
187  continue;
188  }
189 
190  nodeLevel[son] = nodeLevel[v] + 1;
191  distanceToRoot[son] = distanceToRoot[v] + tree.weight(e);
192 
194 
195  fatherOfChain[chainOfNode[son]] = v;
196  weightOfSubtree[v] += weightOfSubtree[son];
197  if (heaviestSon == nullptr || weightOfSubtree[heaviestSon] < weightOfSubtree[son]) {
198  heaviestSon = son;
199  }
200  }
201 
202  if (heaviestSon == nullptr) { // it's leaf => new chain
203  OGDF_ASSERT((v->degree() <= 1));
204 
205  std::vector<node> new_chain;
206  chains.push_back(new_chain);
207  chainsOfTerminals.push_back(new_chain);
208 
209  fatherOfChain.push_back(nullptr);
210  chainOfNode[v] = (int)chains.size() - 1;
211  } else {
212  chainOfNode[v] = chainOfNode[heaviestSon];
213  }
214 
215  chains[chainOfNode[v]].push_back(v);
216  chainsOfTerminals[chainOfNode[v]].push_back(v);
217  positionOnChain[v] = (int)chains[chainOfNode[v]].size() - 1;
218  }
219 
225  node binarySearchUpmostTerminal(node v, const std::vector<node>& chainOfTerminals) const {
226  int left = 0, middle, right = (int)chainOfTerminals.size() - 1;
227  while (left <= right) {
228  middle = (left + right) >> 1;
229 
230  if (nodeLevel[chainOfTerminals[middle]] >= nodeLevel[v]) {
231  right = middle - 1;
232  } else {
233  left = middle + 1;
234  }
235  }
236 
237  if (left == (int)chainOfTerminals.size()) {
238  return nullptr;
239  }
240  return chainOfTerminals[left];
241  }
242 
252  void computeBottleneckOnBranch(node x, node ancestor, T& longestPathDistance,
253  T& fromLowestToAncestor) const {
254  node upmostTerminal = x;
255  while (closestSteinerAncestor[chains[chainOfNode[x]][0]] != nullptr
257  >= nodeLevel[ancestor]) {
258  Math::updateMax(longestPathDistance,
260 
261  if (!chainsOfTerminals[chainOfNode[x]].empty()
263  upmostTerminal = chainsOfTerminals[chainOfNode[x]][0];
264  }
265  x = fatherOfChain[chainOfNode[x]];
266  }
267 
268  // search the upmost terminal on the current chain that has level >= level[ancestor]
269  node upmostTerminalLastChain =
271  if (nodeLevel[upmostTerminalLastChain] > nodeLevel[x]) {
272  upmostTerminalLastChain = nullptr;
273  }
274  if (upmostTerminalLastChain != nullptr) {
275  upmostTerminal = upmostTerminalLastChain;
276  }
277 
278  if (upmostTerminalLastChain != nullptr) {
279  Math::updateMax(longestPathDistance,
281  static_cast<int>(chains[chainOfNode[x]].size()) - 1,
282  positionOnChain[upmostTerminalLastChain] + 1, positionOnChain[x]));
283  }
284 
285  fromLowestToAncestor = distanceToAncestor(upmostTerminal, ancestor);
286  }
287 
288 public:
290  : tree {treeEWGraphCopy}
291  , chainOfNode {tree, -1}
292  , positionOnChain {tree, -1}
293  , weightOfSubtree {tree, 0}
294  , nodeLevel {tree, 0}
295  , distanceToRoot {tree, 0}
296  , closestSteinerAncestor {tree, nullptr} {
297  OGDF_ASSERT(!tree.empty());
298  node root = tree.firstNode();
299 
300  dfsHeavyPathDecomposition(root, nullptr);
301  fatherOfChain[chainOfNode[root]] = nullptr;
302 
303  // reverse the obtained chains
304  int numberOfChains = static_cast<int>(chains.size());
305  for (int i = 0; i < numberOfChains; ++i) {
306  reverse(chains[i].begin(), chains[i].end());
308  for (node v : chains[i]) {
309  positionOnChain[v] = (int)chains[i].size() - 1 - positionOnChain[v];
310  }
311  }
312 
315  }
316 
322  while (chainOfNode[x] != chainOfNode[y]) {
323  int xlevelOfFatherOfChain = fatherOfChain[chainOfNode[x]] != nullptr
325  : -1;
326  int ylevelOfFatherOfChain = fatherOfChain[chainOfNode[y]] != nullptr
328  : -1;
329 
330  if (xlevelOfFatherOfChain >= ylevelOfFatherOfChain) {
331  x = fatherOfChain[chainOfNode[x]];
332  } else {
333  y = fatherOfChain[chainOfNode[y]];
334  }
335  }
336 
337  if (nodeLevel[x] <= nodeLevel[y]) {
338  return x;
339  }
340  return y;
341  }
342 
348  T xLongestPathDistance = 0, yLongestPathDistance = 0;
349  T xFromLowestToLCA = 0, yFromLowestToLCA = 0;
350  node xyLowestCommonAncestor = lowestCommonAncestor(x, y);
351 
352  computeBottleneckOnBranch(x, xyLowestCommonAncestor, xLongestPathDistance, xFromLowestToLCA);
353  computeBottleneckOnBranch(y, xyLowestCommonAncestor, yLongestPathDistance, yFromLowestToLCA);
354 
355  T maxValue = max(xLongestPathDistance, yLongestPathDistance);
356  Math::updateMax(maxValue, xFromLowestToLCA + yFromLowestToLCA);
357 
358  return maxValue;
359  }
360 };
361 
362 }
363 }
ogdf
The namespace for all OGDF objects.
Definition: AugmentationModule.h:36
ogdf::steiner_tree::HeavyPathDecomposition::fatherOfChain
std::vector< node > fatherOfChain
the first node from bottom up that does not belong to the chain
Definition: HeavyPathDecomposition.h:61
ogdf::steiner_tree::HeavyPathDecomposition::nodeLevel
NodeArray< int > nodeLevel
the level of a node in the tree
Definition: HeavyPathDecomposition.h:58
ogdf::steiner_tree::HeavyPathDecomposition::HeavyPathDecomposition
HeavyPathDecomposition(const EdgeWeightedGraphCopy< T > &treeEWGraphCopy)
Definition: HeavyPathDecomposition.h:289
ogdf::steiner_tree::HeavyPathDecomposition::tree
const EdgeWeightedGraphCopy< T > & tree
constant ref to the tree to be decomposed
Definition: HeavyPathDecomposition.h:49
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::steiner_tree::HeavyPathDecomposition::getBottleneckSteinerDistance
T getBottleneckSteinerDistance(node x, node y) const
computes in the bottleneck distance between terminals x and y
Definition: HeavyPathDecomposition.h:347
ogdf::steiner_tree::HeavyPathDecomposition::chainsOfTerminals
std::vector< std::vector< node > > chainsOfTerminals
list of chains only of terminals corresponding to the decomposition
Definition: HeavyPathDecomposition.h:54
ogdf::steiner_tree::HeavyPathDecomposition::dfsHeavyPathDecomposition
void dfsHeavyPathDecomposition(node v, node closestSteinerUpNode)
performs the heavy path decomposition on the tree belonging to the class updates the fields of the cl...
Definition: HeavyPathDecomposition.h:177
ogdf::tlp::Attribute::size
@ size
ogdf::steiner_tree::HeavyPathDecomposition::positionOnChain
NodeArray< int > positionOnChain
position of a node on his chain
Definition: HeavyPathDecomposition.h:56
ogdf::steiner_tree::HeavyPathDecomposition::terminals
List< node > terminals
list of terminals of the desc tree
Definition: HeavyPathDecomposition.h:50
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:135
EdgeWeightedGraphCopy.h
Extends the GraphCopy concept to weighted graphs.
ogdf::reverse
Reverse< T > reverse(T &container)
Provides iterators for container to make it easily iterable in reverse.
Definition: Reverse.h:74
ogdf::steiner_tree::HeavyPathDecomposition::longestDistToSteinerAncestorOnChain
std::vector< std::vector< T > > longestDistToSteinerAncestorOnChain
the max of the interval 0..i for every i on chains
Definition: HeavyPathDecomposition.h:63
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:153
ogdf::steiner_tree::HeavyPathDecomposition::distanceToAncestor
T distanceToAncestor(node v, node ancestor) const
computes the sum of all edges on the path from v to ancestor v must be in ancestor's subtree
Definition: HeavyPathDecomposition.h:124
ogdf::steiner_tree::HeavyPathDecomposition::chainOfNode
NodeArray< int > chainOfNode
the index of a node's chain
Definition: HeavyPathDecomposition.h:55
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:276
ogdf::steiner_tree::HeavyPathDecomposition::computeLongestDistToSteinerAncestorSegTree
void computeLongestDistToSteinerAncestorSegTree()
creates for every chain a segment tree built on a fictive array which keeps for every node the sum of...
Definition: HeavyPathDecomposition.h:156
ogdf::steiner_tree::HeavyPathDecomposition::distanceToRoot
NodeArray< T > distanceToRoot
the length of the edge to his father
Definition: HeavyPathDecomposition.h:59
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:264
ogdf::steiner_tree::HeavyPathDecomposition::getMaxSegmentTree
T getMaxSegmentTree(const std::vector< T > &segmentTree, const int nodeIndex, const int left, const int right, const int queryLeft, const int queryRight) const
extracts the maximum on the required interval
Definition: HeavyPathDecomposition.h:91
ogdf::node
NodeElement * node
The type of nodes.
Definition: Graph_d.h:63
ogdf::steiner_tree::HeavyPathDecomposition::computeLongestDistToSteinerAncestorOnChain
void computeLongestDistToSteinerAncestorOnChain()
creates for every chain an array with the maximum of every prefix of a fictive array which keeps for ...
Definition: HeavyPathDecomposition.h:136
ogdf::List
Doubly linked lists (maintaining the length of the list).
Definition: List.h:42
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:651
ogdf::steiner_tree::HeavyPathDecomposition::binarySearchUpmostTerminal
node binarySearchUpmostTerminal(node v, const std::vector< node > &chainOfTerminals) const
performs a binary search on chainOfTerminals, searches for the closest node to the root on chainOfTer...
Definition: HeavyPathDecomposition.h:225
ogdf::steiner_tree::HeavyPathDecomposition::lowestCommonAncestor
node lowestCommonAncestor(node x, node y) const
computes the lowest common ancestor of nodes x and y using the hpd
Definition: HeavyPathDecomposition.h:321
Math.h
Mathematical Helpers.
ogdf::steiner_tree::HeavyPathDecomposition::isTerminal
const NodeArray< bool > isTerminal
isTerminal of the desc tree
Definition: HeavyPathDecomposition.h:51
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:168
ogdf::steiner_tree::HeavyPathDecomposition::weightOfSubtree
NodeArray< int > weightOfSubtree
weight of the subtree rooted in one node
Definition: HeavyPathDecomposition.h:57
ogdf::Math::updateMax
void updateMax(T &max, const T &newValue)
Stores the maximum of max and newValue in max.
Definition: Math.h:90
ogdf::end
HypergraphRegistry< HypernodeElement >::iterator end(const HypergraphRegistry< HypernodeElement > &self)
ogdf::steiner_tree::HeavyPathDecomposition::longestDistToSteinerAncestorSegTree
std::vector< std::vector< T > > longestDistToSteinerAncestorSegTree
segment tree for segment maxs on every chain
Definition: HeavyPathDecomposition.h:64
ogdf::EdgeWeightedGraphCopy
Definition: EdgeWeightedGraphCopy.h:40
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:356
ogdf::steiner_tree::HeavyPathDecomposition::chains
std::vector< std::vector< node > > chains
list of chains of nodes corresponding to the decomposition
Definition: HeavyPathDecomposition.h:53
ogdf::steiner_tree::HeavyPathDecomposition::computeBottleneckOnBranch
void computeBottleneckOnBranch(node x, node ancestor, T &longestPathDistance, T &fromLowestToAncestor) const
computes for the path from x to ancestor the maximum distance (sum of edges) between any two consecut...
Definition: HeavyPathDecomposition.h:252
ogdf::steiner_tree::HeavyPathDecomposition::closestSteinerAncestor
NodeArray< node > closestSteinerAncestor
the highest-level Steiner ancestor of the current node
Definition: HeavyPathDecomposition.h:60
ogdf::steiner_tree::HeavyPathDecomposition::buildMaxSegmentTree
void buildMaxSegmentTree(std::vector< T > &segmentTree, const int nodeIndex, const int left, const int right, const std::vector< T > &baseArray) const
builds a max segment tree on the baseArray
Definition: HeavyPathDecomposition.h:70
ogdf::steiner_tree::HeavyPathDecomposition
An implementation of the heavy path decomposition on trees.
Definition: HeavyPathDecomposition.h:47
ogdf::Math::maxValue
Container::value_type maxValue(const Container &values)
Returns the maximum of an iterable container of given values.
Definition: Math.h:235
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:233