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/Graph.h>
35 #include <ogdf/basic/GraphList.h>
36 #include <ogdf/basic/List.h>
37 #include <ogdf/basic/Math.h>
38 #include <ogdf/basic/basic.h>
39 
40 #include <algorithm>
41 #include <vector>
42 
43 namespace ogdf {
44 template<typename T>
45 class EdgeWeightedGraphCopy;
46 
47 namespace steiner_tree {
48 
53 template<typename T>
55 private:
59 
60  std::vector<std::vector<node>> chains;
61  std::vector<std::vector<node>> chainsOfTerminals;
68  std::vector<node> fatherOfChain;
69 
70  std::vector<std::vector<T>> longestDistToSteinerAncestorOnChain;
71  std::vector<std::vector<T>> longestDistToSteinerAncestorSegTree;
72 
77  void buildMaxSegmentTree(std::vector<T>& segmentTree, const int nodeIndex, const int left,
78  const int right, const std::vector<T>& baseArray) const {
79  if (left == right) { // leaf
80  segmentTree[nodeIndex] = baseArray[left];
81  return;
82  }
83 
84  int middle = (left + right) >> 1;
85  int leftNodeIndex = nodeIndex + nodeIndex + 1;
86  int rightNodeIndex = leftNodeIndex + 1;
87 
88  buildMaxSegmentTree(segmentTree, leftNodeIndex, left, middle, baseArray);
89  buildMaxSegmentTree(segmentTree, rightNodeIndex, middle + 1, right, baseArray);
90 
91  segmentTree[nodeIndex] = max(segmentTree[leftNodeIndex], segmentTree[rightNodeIndex]);
92  }
93 
98  T getMaxSegmentTree(const std::vector<T>& segmentTree, const int nodeIndex, const int left,
99  const int right, const int queryLeft, const int queryRight) const {
100  if (queryLeft > queryRight || left > queryRight || queryLeft > right) {
101  return 0;
102  }
103 
104  if (queryLeft <= left && right <= queryRight) { // included
105  return segmentTree[nodeIndex];
106  }
107 
108  int middleIndex = (left + right) >> 1;
109  int leftNodeIndex = nodeIndex + nodeIndex + 1;
110  int rightNodeIndex = leftNodeIndex + 1;
111 
112  T maxValue(0);
113  if (queryLeft <= middleIndex) {
115  getMaxSegmentTree(segmentTree, leftNodeIndex, left, middleIndex, queryLeft,
116  queryRight));
117  }
118  if (queryRight > middleIndex) {
120  getMaxSegmentTree(segmentTree, rightNodeIndex, middleIndex + 1, right,
121  queryLeft, queryRight));
122  }
123 
124  return maxValue;
125  }
126 
131  T distanceToAncestor(node v, node ancestor) const {
132  if (ancestor == nullptr) {
133  return distanceToRoot[v];
134  }
135  return distanceToRoot[v] - distanceToRoot[ancestor];
136  }
137 
144  longestDistToSteinerAncestorOnChain.resize((int)chains.size());
145  for (int i = 0; i < (int)chains.size(); ++i) {
146  longestDistToSteinerAncestorOnChain[i].resize((int)chains[i].size());
147  for (int j = 0; j < (int)chains[i].size(); ++j) {
150  if (j > 0) {
153  }
154  }
155  }
156  }
157 
164  longestDistToSteinerAncestorSegTree.resize((int)chains.size());
165  for (int i = 0; i < (int)chains.size(); ++i) {
166  longestDistToSteinerAncestorSegTree[i].resize(4 * (int)chains[i].size());
167 
168  std::vector<T> distanceToSteinerAncestor_byPosition;
169  distanceToSteinerAncestor_byPosition.resize(chains[i].size());
170  for (int j = 0; j < (int)chains[i].size(); ++j) {
171  distanceToSteinerAncestor_byPosition[j] =
173  }
174 
176  (int)chains[i].size() - 1, distanceToSteinerAncestor_byPosition);
177  }
178  }
179 
184  void dfsHeavyPathDecomposition(node v, node closestSteinerUpNode) {
185  weightOfSubtree[v] = 1;
186  node heaviestSon = nullptr;
187  closestSteinerAncestor[v] = closestSteinerUpNode;
188 
189  for (adjEntry adj : v->adjEntries) {
190  edge e = adj->theEdge();
191  node son = adj->twinNode();
192 
193  if (weightOfSubtree[son] != 0) { // the parent
194  continue;
195  }
196 
197  nodeLevel[son] = nodeLevel[v] + 1;
198  distanceToRoot[son] = distanceToRoot[v] + tree.weight(e);
199 
201 
202  fatherOfChain[chainOfNode[son]] = v;
203  weightOfSubtree[v] += weightOfSubtree[son];
204  if (heaviestSon == nullptr || weightOfSubtree[heaviestSon] < weightOfSubtree[son]) {
205  heaviestSon = son;
206  }
207  }
208 
209  if (heaviestSon == nullptr) { // it's leaf => new chain
210  OGDF_ASSERT((v->degree() <= 1));
211 
212  std::vector<node> new_chain;
213  chains.push_back(new_chain);
214  chainsOfTerminals.push_back(new_chain);
215 
216  fatherOfChain.push_back(nullptr);
217  chainOfNode[v] = (int)chains.size() - 1;
218  } else {
219  chainOfNode[v] = chainOfNode[heaviestSon];
220  }
221 
222  chains[chainOfNode[v]].push_back(v);
223  chainsOfTerminals[chainOfNode[v]].push_back(v);
224  positionOnChain[v] = (int)chains[chainOfNode[v]].size() - 1;
225  }
226 
232  node binarySearchUpmostTerminal(node v, const std::vector<node>& chainOfTerminals) const {
233  int left = 0, middle, right = (int)chainOfTerminals.size() - 1;
234  while (left <= right) {
235  middle = (left + right) >> 1;
236 
237  if (nodeLevel[chainOfTerminals[middle]] >= nodeLevel[v]) {
238  right = middle - 1;
239  } else {
240  left = middle + 1;
241  }
242  }
243 
244  if (left == (int)chainOfTerminals.size()) {
245  return nullptr;
246  }
247  return chainOfTerminals[left];
248  }
249 
259  void computeBottleneckOnBranch(node x, node ancestor, T& longestPathDistance,
260  T& fromLowestToAncestor) const {
261  node upmostTerminal = x;
262  while (closestSteinerAncestor[chains[chainOfNode[x]][0]] != nullptr
264  >= nodeLevel[ancestor]) {
265  Math::updateMax(longestPathDistance,
267 
268  if (!chainsOfTerminals[chainOfNode[x]].empty()
270  upmostTerminal = chainsOfTerminals[chainOfNode[x]][0];
271  }
272  x = fatherOfChain[chainOfNode[x]];
273  }
274 
275  // search the upmost terminal on the current chain that has level >= level[ancestor]
276  node upmostTerminalLastChain =
278  if (nodeLevel[upmostTerminalLastChain] > nodeLevel[x]) {
279  upmostTerminalLastChain = nullptr;
280  }
281  if (upmostTerminalLastChain != nullptr) {
282  upmostTerminal = upmostTerminalLastChain;
283  }
284 
285  if (upmostTerminalLastChain != nullptr) {
286  Math::updateMax(longestPathDistance,
288  static_cast<int>(chains[chainOfNode[x]].size()) - 1,
289  positionOnChain[upmostTerminalLastChain] + 1, positionOnChain[x]));
290  }
291 
292  fromLowestToAncestor = distanceToAncestor(upmostTerminal, ancestor);
293  }
294 
295 public:
297  : tree {treeEWGraphCopy}
298  , chainOfNode {tree, -1}
299  , positionOnChain {tree, -1}
300  , weightOfSubtree {tree, 0}
301  , nodeLevel {tree, 0}
302  , distanceToRoot {tree, 0}
303  , closestSteinerAncestor {tree, nullptr} {
304  OGDF_ASSERT(!tree.empty());
305  node root = tree.firstNode();
306 
307  dfsHeavyPathDecomposition(root, nullptr);
308  fatherOfChain[chainOfNode[root]] = nullptr;
309 
310  // reverse the obtained chains
311  int numberOfChains = static_cast<int>(chains.size());
312  for (int i = 0; i < numberOfChains; ++i) {
313  reverse(chains[i].begin(), chains[i].end());
315  for (node v : chains[i]) {
316  positionOnChain[v] = (int)chains[i].size() - 1 - positionOnChain[v];
317  }
318  }
319 
322  }
323 
329  while (chainOfNode[x] != chainOfNode[y]) {
330  int xlevelOfFatherOfChain = fatherOfChain[chainOfNode[x]] != nullptr
332  : -1;
333  int ylevelOfFatherOfChain = fatherOfChain[chainOfNode[y]] != nullptr
335  : -1;
336 
337  if (xlevelOfFatherOfChain >= ylevelOfFatherOfChain) {
338  x = fatherOfChain[chainOfNode[x]];
339  } else {
340  y = fatherOfChain[chainOfNode[y]];
341  }
342  }
343 
344  if (nodeLevel[x] <= nodeLevel[y]) {
345  return x;
346  }
347  return y;
348  }
349 
355  T xLongestPathDistance = 0, yLongestPathDistance = 0;
356  T xFromLowestToLCA = 0, yFromLowestToLCA = 0;
357  node xyLowestCommonAncestor = lowestCommonAncestor(x, y);
358 
359  computeBottleneckOnBranch(x, xyLowestCommonAncestor, xLongestPathDistance, xFromLowestToLCA);
360  computeBottleneckOnBranch(y, xyLowestCommonAncestor, yLongestPathDistance, yFromLowestToLCA);
361 
362  T maxValue = max(xLongestPathDistance, yLongestPathDistance);
363  Math::updateMax(maxValue, xFromLowestToLCA + yFromLowestToLCA);
364 
365  return maxValue;
366  }
367 };
368 
369 }
370 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
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:68
Graph.h
Includes declaration of graph class.
ogdf::steiner_tree::HeavyPathDecomposition::nodeLevel
NodeArray< int > nodeLevel
the level of a node in the tree
Definition: HeavyPathDecomposition.h:65
ogdf::steiner_tree::HeavyPathDecomposition::HeavyPathDecomposition
HeavyPathDecomposition(const EdgeWeightedGraphCopy< T > &treeEWGraphCopy)
Definition: HeavyPathDecomposition.h:296
ogdf::steiner_tree::HeavyPathDecomposition::tree
const EdgeWeightedGraphCopy< T > & tree
constant ref to the tree to be decomposed
Definition: HeavyPathDecomposition.h:56
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::steiner_tree::HeavyPathDecomposition::getBottleneckSteinerDistance
T getBottleneckSteinerDistance(node x, node y) const
computes in the bottleneck distance between terminals x and y
Definition: HeavyPathDecomposition.h:354
ogdf::steiner_tree::HeavyPathDecomposition::chainsOfTerminals
std::vector< std::vector< node > > chainsOfTerminals
list of chains only of terminals corresponding to the decomposition
Definition: HeavyPathDecomposition.h:61
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:184
ogdf::tlp::Attribute::size
@ size
ogdf::steiner_tree::HeavyPathDecomposition::positionOnChain
NodeArray< int > positionOnChain
position of a node on his chain
Definition: HeavyPathDecomposition.h:63
ogdf::steiner_tree::HeavyPathDecomposition::terminals
List< node > terminals
list of terminals of the desc tree
Definition: HeavyPathDecomposition.h:57
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
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:70
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
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:131
ogdf::steiner_tree::HeavyPathDecomposition::chainOfNode
NodeArray< int > chainOfNode
the index of a node's chain
Definition: HeavyPathDecomposition.h:62
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:283
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:163
ogdf::steiner_tree::HeavyPathDecomposition::distanceToRoot
NodeArray< T > distanceToRoot
the length of the edge to his father
Definition: HeavyPathDecomposition.h:66
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
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:98
ogdf::node
NodeElement * node
The type of nodes.
Definition: Graph_d.h:70
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:143
ogdf::List
Doubly linked lists (maintaining the length of the list).
Definition: DfsMakeBiconnected.h:40
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
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:232
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:328
Math.h
Mathematical Helpers.
ogdf::steiner_tree::HeavyPathDecomposition::isTerminal
const NodeArray< bool > isTerminal
isTerminal of the desc tree
Definition: HeavyPathDecomposition.h:58
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::steiner_tree::HeavyPathDecomposition::weightOfSubtree
NodeArray< int > weightOfSubtree
weight of the subtree rooted in one node
Definition: HeavyPathDecomposition.h:64
ogdf::Math::updateMax
void updateMax(T &max, const T &newValue)
Stores the maximum of max and newValue in max.
Definition: Math.h:94
basic.h
Basic declarations, included by all source files.
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:71
ogdf::EdgeWeightedGraphCopy
Definition: EdgeWeightedGraphCopy.h:44
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::steiner_tree::HeavyPathDecomposition::chains
std::vector< std::vector< node > > chains
list of chains of nodes corresponding to the decomposition
Definition: HeavyPathDecomposition.h:60
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:259
ogdf::steiner_tree::HeavyPathDecomposition::closestSteinerAncestor
NodeArray< node > closestSteinerAncestor
the highest-level Steiner ancestor of the current node
Definition: HeavyPathDecomposition.h:67
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:77
ogdf::steiner_tree::HeavyPathDecomposition
An implementation of the heavy path decomposition on trees.
Definition: HeavyPathDecomposition.h:54
ogdf::Math::maxValue
Container::value_type maxValue(const Container &values)
Returns the maximum of an iterable container of given values.
Definition: Math.h:239
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240