Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

BlowupGraph.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/ArrayBuffer.h>
35 #include <ogdf/basic/Graph.h>
36 #include <ogdf/basic/GraphList.h>
37 #include <ogdf/basic/HashArray.h>
38 #include <ogdf/basic/Hashing.h>
39 #include <ogdf/basic/List.h>
40 #include <ogdf/basic/Math.h>
41 #include <ogdf/basic/basic.h>
42 
43 #include <iostream>
44 #include <utility>
45 
47 template<typename T>
49 } // namespace ogdf::steiner_tree::goemans
50 
51 namespace ogdf::steiner_tree {
52 template<typename T, typename ExtraDataType>
54 } // namespace ogdf::steiner_tree
55 
56 //#define OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
57 
58 namespace ogdf {
59 template<typename T>
60 class EdgeWeightedGraph;
61 
62 namespace steiner_tree {
63 namespace goemans {
64 
69 template<typename T>
70 class BlowupGraph {
71 private:
74  const double m_eps;
75 
78 
85 
88 
89  int m_lcm;
90  int m_y;
94 
96 
98 
99  /* witness set (for some component and specified K (core edge set))
100  *
101  * W(e) = { e } if e is a core edge
102  * W(e) =
103  * take the path P of loss edges from u to e in the component
104  * add every incident core edge of u
105  * that is: if we root the loss connected component at the terminal,
106  * W(e) = all core edges incident to the subtree below e
107  *
108  * Need fast lookups for:
109  * (1) |W(f)|
110  * (2) all loss edges f such that given core edge e is in W(f)
111  * (3) all loss edges f such that W(f) is a subset of a given basis -> for each e \in B: do (2)
112  *
113  * Data Structures:
114  * - witnessCard[e] = |W(e)|
115  * - witness[v_e] = { f | e \in W(f) }
116  * (Note that core edges are given as nodes.)
117  * Also note that we can save it all much sparser.
118  */
121 
122 protected:
124  void computeLCM() {
125  ArrayBuffer<int> denominators;
126 
127  for (int i = 0; i < m_fullCompStore.size(); ++i) {
128  OGDF_ASSERT(m_fullCompStore.extra(i) <= 1.0 + m_eps);
130  int num, denom;
131  Math::getFraction(m_fullCompStore.extra(i), num, denom);
132  OGDF_ASSERT(Math::gcd(num, denom) == 1);
133  denominators.push(denom);
134  }
135 
136  m_lcm = 1;
137  for (int denom : denominators) {
138  m_lcm = Math::lcm(m_lcm, denom);
139  }
140 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
141  std::cout << "Normalizing factor is " << m_lcm << std::endl;
142 #endif
143  }
144 
147  const node v = m_graph.newNode();
148  m_isTerminal[v] = true;
149  m_terminals.pushBack(v);
150  m_original[v] = t;
151 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
152  std::cout << "Add terminal " << v << " representing original terminal " << t << std::endl;
153 #endif
154  return v;
155  }
156 
158  const node vCopy = m_graph.newNode();
159  m_original[vCopy] = v;
160  return vCopy;
161  }
162 
166  node v = m_fullCompStore.original(start->theNode());
167  List<adjEntry> queueT;
168  List<node> queueC;
169  queueT.pushBack(start);
170  queueC.pushBack(copy[v]);
171  while (!queueT.empty()) {
172  const adjEntry inAdj = queueT.popFrontRet();
173  const node wT = inAdj->twinNode();
174  const node vC = queueC.popFrontRet();
175 
176  const node wO = m_fullCompStore.original(wT);
177  if (m_fullCompStore.isTerminal(wT)) {
178  newEdge(vC, copy[wO], m_fullCompStore.graph().weight(inAdj->theEdge()), cap);
179  } else { // not a terminal
180  const node wC = initNode(wO);
181  newEdge(vC, wC, m_fullCompStore.graph().weight(inAdj->theEdge()), cap);
182  const adjEntry back = inAdj->twin();
183  for (adjEntry adj = back->cyclicSucc(); adj != back; adj = adj->cyclicSucc()) {
184  queueT.pushBack(adj);
185  queueC.pushBack(wC);
186  }
187  }
188  }
189  return copy[v];
190  }
191 
193  void initSource(ArrayBuffer<std::pair<node, int>>& roots) {
194  OGDF_ASSERT(m_source == nullptr);
196 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
197  std::cout << "Add source node " << getSource() << " with edges to:" << std::endl;
198 #endif
199  for (auto root : roots) {
200 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
201  std::cout << " * node " << root.first << " with cost 0 and capacity " << root.second
202  << std::endl;
203 #endif
204  newEdge(getSource(), root.first, 0, root.second);
205  }
206  }
207 
210  const List<node>& terminals) {
211  ArrayBuffer<std::pair<node, int>> roots; // roots (in the blowupGraph) and their capacities
212 
213  NodeArray<node> copy(originalGraph, nullptr);
214  for (node t : terminals) { // generate all terminals
215  copy[t] = initTerminal(t);
216  }
217  for (int i = 0; i < m_fullCompStore.size(); ++i) {
218  int cap = int(getLCM() * m_fullCompStore.extra(i) + m_eps);
220  roots.push(std::make_pair(root, cap));
221  }
222 
223  removeIsolatedTerminals(); // can exist by preprocessing
224 
225 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
226  for (edge e : m_graph.edges) {
227  std::cout << "Edge from " << e << " of cost " << m_cost[e] << " and capacity "
228  << m_capacity[e] << std::endl;
229  }
230 #endif
231 
232  // compute core edges (and replace these edges by nodes)
233  // and witness sets
234  initCoreWitness();
235 
236  initSource(roots);
237  }
238 
241  OGDF_ASSERT(m_pseudotarget == nullptr);
243 
244 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
245  std::cout << "Add pseudo-target " << getPseudotarget()
246  << " with edges coming from:" << std::endl;
247 #endif
248  for (node v : terminals()) {
249  OGDF_ASSERT(v);
250  int y_v = -getLCM();
251  // compute y_v, the number of components containing v in the blow up graph - N
252  // NOTE: for the non-blowup variant this is simply the sum of all x_C where C contains v ... - 1
253  for (adjEntry adj : v->adjEntries) {
254  if (adj->twinNode() != getSource()) {
255  y_v += getCapacity(adj->theEdge());
256  }
257  }
258  OGDF_ASSERT(y_v >= 0);
259 
260  if (y_v > 0) {
261  newEdge(v, getPseudotarget(), 0, y_v);
262 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
263  std::cout << " * terminal " << v << " with zero cost and capacity " << y_v
264  << std::endl;
265 #endif
266  m_y += y_v;
267  }
268  }
269  }
270 
272  void initTarget() {
273  OGDF_ASSERT(m_target == nullptr);
275 
277 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
278  std::cout << "Add edge from pseudo-target " << getPseudotarget() << " to target "
279  << getTarget() << " with zero cost and capacity " << m_y << std::endl;
280 #endif
281  }
282 
285 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
286  std::cout << " * updating for terminal " << v << std::endl;
287 #endif
288  int delta = 0;
289  int capSource = 0;
290  int capTarget = -getLCM();
291 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
292  std::cout << " * target capacity initialized to " << capTarget
293  << ", source capacity and delta to 0" << std::endl;
294 #endif
295  adjEntry adj2;
296  for (adjEntry adj = v->firstAdj(); adj; adj = adj2) {
297  adj2 = adj->succ();
298  if (adj->twinNode() == getSource()) {
299 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
300  std::cout << " * remove edge with capacity " << getCapacity(adj->theEdge())
301  << " from source " << getSource() << std::endl;
302 #endif
303  OGDF_ASSERT(adj->theEdge()->source() == getSource());
304 
305  // remove arcs from the source
306  m_graph.delEdge(adj->theEdge());
307  } else if (adj->twinNode() == getPseudotarget()) {
308 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
309  std::cout << " * remove edge to pseudotarget " << getPseudotarget()
310  << " with capacity " << getCapacity(adj->theEdge())
311  << " participating in delta" << std::endl;
312 #endif
313  OGDF_ASSERT(adj->theEdge()->target() == getPseudotarget());
314 
315  // remove arcs to the pseudotarget
316  delta -= getCapacity(adj->theEdge());
317  m_graph.delEdge(adj->theEdge());
318  } else {
319 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
320  std::cout << " * update target capacity for edge " << adj->theEdge()
321  << " by adding " << getCapacity(adj->theEdge()) << std::endl;
322 #endif
323  // compute y_v for the contraction node
324  capTarget += getCapacity(adj->theEdge());
325  // compute s->v capacity
326  if (v != adj->theEdge()->target()) { // outgoing edge
327 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
328  std::cout << " and change source capacity by the same amount" << std::endl;
329 #endif
330  capSource += getCapacity(adj->theEdge());
331  }
332  }
333  }
334 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
335  std::cout << " * new target capacity is " << capTarget << " and delta = " << delta
336  << std::endl;
337 #endif
338  OGDF_ASSERT(capTarget >= 0);
339  if (capTarget > 0) {
340  newEdge(v, getPseudotarget(), 0, capTarget);
341 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
342  std::cout << " * new edge from pseudotarget to target with zero cost and capacity "
343  << capTarget << std::endl;
344 #endif
345  }
346  if (capSource > 0) {
347 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
348  std::cout << " * new edge from source to " << v << " with zero cost and capacity "
349  << capSource << std::endl;
350 #endif
351  newEdge(getSource(), v, 0, capSource);
352  }
353 
354  return delta + capTarget;
355  }
356 
357  void setCapacity(edge e, int capacity) { m_capacity[e] = capacity; }
358 
361 
364  void addCore(node e) { m_coreEdges.pushBack(e); }
365 
367  void addWitness(node e, edge f) {
368  ++m_witnessCard[f];
369  m_witness[e].push(f);
370  }
371 
378  m_witnessCard.init(m_graph, 0);
379  m_witness.init(m_graph);
380 
381  // compute set of core edges
382  EdgeArray<bool> isLossEdge;
383  m_ceModule.call(m_graph, terminals(), isLossEdge);
384 
385  // add nodes for core edges and be able to map them
386  EdgeArray<node> splitMap(m_graph, nullptr);
387  ArrayBuffer<edge> coreEdges;
388  for (edge e : m_graph.edges) {
389  if (!isLossEdge[e]) {
390  splitMap[e] = m_graph.newNode();
391  coreEdges.push(e);
392  }
393  }
394 
395  // traverse losses from all terminals to find witness sets
396  NodeArray<adjEntry> pred(m_graph, nullptr);
397  for (node t : terminals()) {
398  ArrayBuffer<node> stack;
399  stack.push(t);
400  while (!stack.empty()) {
401  // for each node v "below" an edge e in the traversal:
402  // add all incident core edges vw to W(e)
403  const node v = stack.popRet();
404  for (adjEntry adj : v->adjEntries) {
405  const edge e = adj->theEdge();
406  const node w = adj->twinNode();
407  if (!pred[v] || w != pred[v]->theNode()) { // do not look at backward arcs in the tree
408  if (isLossEdge[e]) {
409  stack.push(w);
410  pred[w] = adj;
411  } else {
412  for (node x = v; pred[x]; x = pred[x]->theNode()) {
413  addWitness(splitMap[e], pred[x]->theEdge());
414  }
415  }
416  }
417  }
418  }
419  }
420 
421  // finally replace core edges by nodes
422  for (edge e : coreEdges) {
423  const T w = getCost(e);
424  const node x = splitMap[e];
425  const int cap = getCapacity(e);
426  OGDF_ASSERT(x);
427  newEdge(e->source(), x, w, cap);
428  newEdge(x, e->target(), 0, cap);
429  // the cost of a core edge node is hence the weight of one incident edge;
430  // also keep capacity.
431  // Note that we cannot guarantee throughout the algorithm that the edge
432  // with the non-zero cost is the first one nor that it is the incoming one
433  // because both directions and adjacency orders can be changed.
434  m_graph.delEdge(e);
435  addCore(x);
436  }
437  }
438 
440  void makeCWCopy(const HashArray<edge, edge>& edgeMap) {
441  for (HashConstIterator<edge, edge> pair = edgeMap.begin(); pair.valid(); ++pair) {
442  const edge eO = pair.key();
443  const edge eC = pair.info();
444  const node vO = eO->target();
445  const node vC = eC->target();
446  m_witnessCard[eC] = m_witnessCard[eO]; // copy witness cardinality
447  if (vC == vO) { // target is a terminal, so it cannot be a core edge
448  continue;
449  }
450  for (ListIterator<node> it = m_coreEdges.begin(); it.valid(); ++it) {
451  if (*it == vO) { // vO is a core edge
452  m_coreEdges.insertAfter(vC, it); // make vC a core edge
453 
454  // copy witness sets
455  // XXX: do we need this or are witness sets computed after the loop again?!
456  for (edge e : m_witness[vO]) {
457  m_witness[vC].push(edgeMap[e]);
458  }
459  break;
460  }
461  }
462  }
463  }
464 
466 
467 public:
470  const FullComponentWithExtraStore<T, double>& fullCompStore,
471  const CoreEdgeModule<T>& ceModule, double eps = 1e-8)
472  : m_fullCompStore(fullCompStore)
473  , m_eps(eps)
474  , m_terminals()
475  , m_isTerminal(m_graph, false)
476  , m_original(m_graph, nullptr)
477  , m_cost(m_graph)
479  , m_y(0)
480  , m_source(nullptr)
481  , m_pseudotarget(nullptr)
482  , m_target(nullptr)
483  , m_ceModule(ceModule) {
484  computeLCM();
485 
486 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
487  std::cout << "Full components to use in blowup graph:\n";
488  for (int k = 0; k < m_fullCompStore.size(); ++k) {
489  std::cout << " * " << m_fullCompStore.terminals(k) << " cost "
490  << m_fullCompStore.cost(k) << " support " << m_fullCompStore.extra(k)
491  << " (normalized to " << m_fullCompStore.extra(k) * m_lcm << ")" << std::endl;
492  }
493 #endif
494 
497  initTarget();
498  }
499 
502 
503  const Graph& getGraph() const { return m_graph; }
504 
506  node getSource() const { return m_source; }
507 
509  node getPseudotarget() const { return m_pseudotarget; }
510 
512  node getTarget() const { return m_target; }
513 
515  int getCapacity(edge e) const { return m_capacity[e]; }
516 
518  const EdgeArray<int>& capacities() const { return m_capacity; }
519 
521  T getCost(edge e) const { return m_cost[e]; }
522 
524  node getOriginal(node v) const { return m_original[v]; }
525 
527  int getLCM() const { return m_lcm; }
528 
530  int getY() const { return m_y; }
531 
533  const List<node>& terminals() const { return m_terminals; }
534 
536  bool isTerminal(node v) const { return m_isTerminal[v]; }
537 
541 
543  T getCoreCapacity(node v) const {
544  OGDF_ASSERT(v->degree() == 2);
545  return getCapacity(v->firstAdj()->theEdge());
546  }
547 
549  T getCoreCost(node v) const {
550  OGDF_ASSERT(v->degree() == 2);
551  T val = getCost(v->firstAdj()->theEdge());
552  if (val == 0) {
553  val = getCost(v->lastAdj()->theEdge());
554  }
555  return val;
556  }
557 
559  double computeCoreWeight(node v) const {
560  double weight = (double)getCoreCost(v);
561  for (edge e : witnessList(v)) {
563  weight += (double)getCost(e) / numberOfWitnesses(e);
564  }
565  return weight;
566  }
567 
569 
572 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
573  std::cout << "Updating capacities (y = " << m_y << ")" << std::endl;
574 #endif
575  for (node t : terminals()) {
577 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
578  std::cout << " * new y = " << m_y << std::endl;
579 #endif
580  }
581  // XXX: doing it for v and all terminals we have met during cleanup would be sufficient
582  OGDF_ASSERT(getTarget()->degree() == 1);
583  setCapacity(getTarget()->firstAdj()->theEdge(), m_y);
584  }
585 
587  edge newEdge(node v, node w, T cost, int capacity) {
588  edge e = m_graph.newEdge(v, w);
589  m_cost[e] = cost;
590  m_capacity[e] = capacity;
591  return e;
592  }
593 
596  for (edge e : edges) {
597  m_graph.delEdge(e);
598  }
599  }
600 
602  void contract(node& v, node t) {
603  if (v->degree() == 0) {
604  std::swap(v, t);
605  }
606 
608  m_terminals.removeFirst(t);
609  m_isTerminal[t] = false;
610 
611  if (t->degree() > 0) {
612  v = m_graph.contract(m_graph.newEdge(v, t));
613  // the contract method ensures that capacities, weights, and everything is kept
614  } else {
615  m_graph.delNode(t);
616  }
617  }
618 
620  template<typename NODELIST>
621  void contract(NODELIST& nodes) {
622  auto it = nodes.begin();
623  node v = *it;
624  for (++it; it != nodes.end(); ++it) {
625  contract(v, *it);
626  }
627  }
628 
634  void removeBasis(node v) {
635  ArrayBuffer<node> cleanup;
636  cleanup.push(v->firstAdj()->twinNode());
637  cleanup.push(v->lastAdj()->twinNode());
638  OGDF_ASSERT(v->degree() == 2);
639  OGDF_ASSERT(v->firstAdj()->twinNode() != v->lastAdj()->twinNode());
640  m_graph.delNode(v);
641 
642  while (!cleanup.empty()) {
643  v = cleanup.popRet();
644  if (!isTerminal(v)) {
645  OGDF_ASSERT(v->degree() >= 1);
646  if (v->degree() == 1) { // v is a pendant node, delete
647 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
648  std::cout << " * remove pendant node " << v << " for cleanup" << std::endl;
649 #endif
650  cleanup.push(v->firstAdj()->twinNode());
651  m_graph.delNode(v);
652  } else if (v->indeg() == 0) { // v has no incoming edge, fix
653 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
654  std::cout << " * " << v << " has no incoming edge -> fix directions"
655  << std::endl;
656 #endif
657  const node w = v->firstAdj()->twinNode();
658  const edge e = v->firstAdj()->theEdge();
659 #ifdef OGDF_STEINER_TREE_GOEMANS_BLOWUP_GRAPH_LOGGING
660  std::cout << " * make " << w << " parent of " << v << " (reverse edge "
661  << e << ")" << std::endl;
662 #endif
663  m_graph.reverseEdge(e);
664  OGDF_ASSERT(e->source() == w);
665  if (!isTerminal(w)) {
666  cleanup.push(w);
667  // when w is cleaned up, it must not go back to v
668  if (w->firstAdj()->theEdge() == e) {
669  // move first adjacency entries of w away (w->v is not first anymore)
670  m_graph.moveAdjAfter(w->firstAdj(), w->lastAdj());
671  }
672  }
673  }
674  }
675  }
676  }
677 
680  for (ListIterator<node> it = m_terminals.begin(), itNext; it.valid(); it = itNext) {
681  itNext = it.succ();
682  if ((*it)->degree() == 0) {
683  m_graph.delNode(*it);
684  m_terminals.del(it);
685  }
686  }
687  }
688 
691  edge rootEdge = nullptr;
692  OGDF_ASSERT(!isTerminal(v));
693  for (auto it = v->adjEntries.begin(); it != v->adjEntries.end();) {
694  edge e = (*it)->theEdge();
695  if (e->source() != v) { // incoming edge
696  rootEdge = e;
697  if (isTerminal(e->source())) {
698  break;
699  }
700  v = e->source();
701  it = v->adjEntries.begin();
702  } else {
703  ++it;
704  }
705  }
706  OGDF_ASSERT(rootEdge != nullptr);
707  OGDF_ASSERT(isTerminal(rootEdge->source()));
708  return rootEdge;
709  }
710 
712  void copyComponent(const edge origEdge, const int origCap, const int copyCap) {
713  if (copyCap == 0) {
714  return;
715  }
716  List<edge> todo;
717  List<node> origin;
718  HashArray<edge, edge> edgeMap;
719  todo.pushBack(origEdge);
720  origin.pushBack(origEdge->source());
721  while (!todo.empty()) {
722  edge eO = todo.popFrontRet();
723  node vC = origin.popFrontRet();
724  node wO = eO->target();
725  node wC = wO;
726  if (!isTerminal(wO)) {
727  wC = initNode(getOriginal(wO));
728  }
729  edge eC = newEdge(vC, wC, getCost(eO), copyCap);
730  setCapacity(eO, origCap);
731  edgeMap[eO] = eC;
732  if (!isTerminal(wO)) {
733  for (adjEntry adj = eO->adjTarget()->cyclicSucc(); adj != eO->adjTarget();
734  adj = adj->cyclicSucc()) {
735  OGDF_ASSERT(adj->theEdge()->target() != eO->target()); // outgoing edges
736  origin.pushBack(wC);
737  todo.pushBack(adj->theEdge());
738  }
739  }
740  }
741  makeCWCopy(edgeMap);
742  }
743 
746 
748  const List<node>& core() const { return m_coreEdges; }
749 
752  void delCore(node e) {
753  /* What happens when we remove a core edge?
754  * - loss edges are not affected
755  * - we have to remove a core edge e from W(f) for all f, which means:
756  * for all elements f of witness[v_e], decrease witnessCard[f], then remove witness[v_e]
757  */
758  for (edge f : m_witness[e]) {
759  --m_witnessCard[f];
760  }
761  // witness[e] is removed by removing the node from the graph
762  m_coreEdges.removeFirst(e);
763  }
764 
766  int numberOfWitnesses(edge e) const { return m_witnessCard[e]; }
767 
769  const ArrayBuffer<edge>& witnessList(node e) const { return m_witness[e]; }
770 
772 };
773 
774 }
775 }
776 }
ogdf::ArrayBuffer< int >
HashArray.h
Declaration and implementation of HashArray class.
ogdf::steiner_tree::goemans::BlowupGraph::numberOfWitnesses
int numberOfWitnesses(edge e) const
Return the number of witnesses of an edge.
Definition: BlowupGraph.h:766
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ArrayBuffer.h
Declaration and implementation of ArrayBuffer class.
Graph.h
Includes declaration of graph class.
ogdf::steiner_tree::goemans::BlowupGraph::initCoreWitness
void initCoreWitness()
Finds a "random" set of core edges and "replace" found edges by nodes, also find the witness sets for...
Definition: BlowupGraph.h:377
ogdf::steiner_tree::goemans::BlowupGraph::m_fullCompStore
const FullComponentWithExtraStore< T, double > & m_fullCompStore
all enumerated full components, with solution
Definition: BlowupGraph.h:73
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::ArrayBuffer::empty
bool empty() const
Returns true if the buffer is empty, false otherwise.
Definition: ArrayBuffer.h:238
ogdf::Graph::delNode
virtual void delNode(node v)
Removes node v and all incident edges from the graph.
ogdf::steiner_tree::FullComponentStore::original
node original(node v) const
Definition: FullComponentStore.h:284
ogdf::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:166
ogdf::steiner_tree::goemans::BlowupGraph::getGraph
const Graph & getGraph() const
Definition: BlowupGraph.h:503
ogdf::steiner_tree::FullComponentStore::terminals
const Array< node > & terminals(int id) const
Returns the list of terminals in the full component with given id.
Definition: FullComponentStore.h:254
ogdf::steiner_tree::goemans::BlowupGraph::findRootEdge
edge findRootEdge(node v)
Finds the root node of a component given by v, an arbitrary inner nonterminal of the component.
Definition: BlowupGraph.h:690
ogdf::Math::lcm
T lcm(T a, T b)
Returns the least common multipler of two numbers.
Definition: Math.h:197
ogdf::steiner_tree::goemans::BlowupGraph::initSource
void initSource(ArrayBuffer< std::pair< node, int >> &roots)
Connects source to component roots.
Definition: BlowupGraph.h:193
Hashing.h
Declaration of classes used for hashing.
ogdf::steiner_tree::goemans::BlowupGraph::m_graph
Graph m_graph
Definition: BlowupGraph.h:72
ogdf::steiner_tree::goemans::BlowupGraph::removeBasis
void removeBasis(node v)
Removes a basis and cleans up.
Definition: BlowupGraph.h:634
ogdf::NodeElement::lastAdj
adjEntry lastAdj() const
Returns the last entry in the adjacency list.
Definition: Graph_d.h:289
ogdf::steiner_tree::goemans::BlowupGraph::m_original
NodeArray< node > m_original
Mapping of blowup graph nodes to original nodes. If a node in a blowup graph represents more than one...
Definition: BlowupGraph.h:84
ogdf::steiner_tree::goemans::BlowupGraph::delEdges
void delEdges(ArrayBuffer< edge > edges)
Removes edges in edges.
Definition: BlowupGraph.h:595
ogdf::steiner_tree::goemans::BlowupGraph::m_isTerminal
NodeArray< bool > m_isTerminal
Incidence vector for the blowup graph terminals.
Definition: BlowupGraph.h:77
ogdf::steiner_tree::goemans::BlowupGraph::initPseudotarget
void initPseudotarget()
Connects pseudotarget.
Definition: BlowupGraph.h:240
ogdf::List::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: List.h:1591
ogdf::steiner_tree::goemans::BlowupGraph::updateSourceAndTargetArcCapacities
int updateSourceAndTargetArcCapacities(const node v)
Updates arc capacities s->v and v->t.
Definition: BlowupGraph.h:284
ogdf::steiner_tree::goemans
Definition: Approximation.h:65
ogdf::Graph::moveAdjAfter
void moveAdjAfter(adjEntry adjMove, adjEntry adjAfter)
Moves adjacency entry adjMove after adjAfter.
Definition: Graph_d.h:1546
ogdf::steiner_tree::goemans::BlowupGraph::getCoreCost
T getCoreCost(node v) const
Get cost of a core edge.
Definition: BlowupGraph.h:549
ogdf::steiner_tree::goemans::BlowupGraph::addWitness
void addWitness(node e, edge f)
Adds e to W(f)
Definition: BlowupGraph.h:367
ogdf::steiner_tree::FullComponentStore::size
int size() const
Returns the number of full components in the store.
Definition: FullComponentStore.h:248
ogdf::steiner_tree::goemans::BlowupGraph::initBlowupGraphComponent
node initBlowupGraphComponent(const NodeArray< node > &copy, adjEntry start, int cap)
Does a bfs of the component tree to add directed components with the first terminal as root.
Definition: BlowupGraph.h:165
ogdf::ArrayBuffer::popRet
E popRet()
Removes the newest element from the buffer and returns it.
Definition: ArrayBuffer.h:232
ogdf::HashArray::begin
HashConstIterator< I, E, H > begin() const
Returns an iterator to the first element in the list of all elements.
Definition: HashArray.h:112
ogdf::Math::getFraction
void getFraction(double d, int &num, int &denom, const double epsilon=5e-10, const int count=10)
Converts a double to a fraction.
Definition: Math.h:204
ogdf::steiner_tree::goemans::BlowupGraph::m_eps
const double m_eps
epsilon for double operations
Definition: BlowupGraph.h:74
ogdf::AdjElement::twin
adjEntry twin() const
Returns the corresponding adjacency element associated with the same edge.
Definition: Graph_d.h:172
ogdf::Graph::delEdge
virtual void delEdge(edge e)
Removes edge e from the graph.
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::Graph::reverseEdge
void reverseEdge(edge e)
Reverses the edge e, i.e., exchanges source and target node.
ogdf::steiner_tree::goemans::BlowupGraph::terminals
const List< node > & terminals() const
Returns a reference to the list containing all terminals in the blowup graph.
Definition: BlowupGraph.h:533
ogdf::steiner_tree::goemans::BlowupGraph::m_terminals
List< node > m_terminals
The terminals in the blowup graph.
Definition: BlowupGraph.h:76
ogdf::steiner_tree::goemans::BlowupGraph::getY
int getY() const
Returns the y-value of all terminals.
Definition: BlowupGraph.h:530
ogdf::steiner_tree
Definition: MinSteinerTreeMehlhorn.h:297
ogdf::Math::gcd
T gcd(T a, T b)
Returns the greatest common divisor of two numbers.
Definition: Math.h:175
ogdf::steiner_tree::goemans::BlowupGraph::getOriginal
node getOriginal(node v) const
Returns the original node of v.
Definition: BlowupGraph.h:524
ogdf::steiner_tree::goemans::BlowupGraph::addCore
void addCore(node e)
Adds a core edge.
Definition: BlowupGraph.h:364
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
ogdf::steiner_tree::goemans::BlowupGraph::setCapacity
void setCapacity(edge e, int capacity)
Definition: BlowupGraph.h:357
ogdf::steiner_tree::goemans::BlowupGraph::core
const List< node > & core() const
Return list of core edges (implemented by nodes)
Definition: BlowupGraph.h:748
Minisat::Internal::copy
static void copy(const T &from, T &to)
Definition: Alg.h:61
ogdf::steiner_tree::goemans::BlowupGraph::m_cost
EdgeArray< T > m_cost
Definition: BlowupGraph.h:86
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:283
ogdf::steiner_tree::goemans::BlowupGraph::m_capacity
EdgeArray< int > m_capacity
Definition: BlowupGraph.h:87
ogdf::steiner_tree::goemans::BlowupGraph::getCost
T getCost(edge e) const
Returns the cost of e.
Definition: BlowupGraph.h:521
ogdf::EdgeWeightedGraph
Definition: GraphIO.h:56
ogdf::steiner_tree::goemans::BlowupGraph::m_source
node m_source
Definition: BlowupGraph.h:91
ogdf::steiner_tree::goemans::BlowupGraph::m_witnessCard
EdgeArray< int > m_witnessCard
Definition: BlowupGraph.h:119
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::AdjElement::succ
adjEntry succ() const
Returns the successor in the adjacency list.
Definition: Graph_d.h:218
ogdf::steiner_tree::goemans::BlowupGraph::initNode
node initNode(node v)
Definition: BlowupGraph.h:157
ogdf::steiner_tree::goemans::BlowupGraph::delCore
void delCore(node e)
Remove a core edge.
Definition: BlowupGraph.h:752
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::NodeElement::indeg
int indeg() const
Returns the indegree of the node.
Definition: Graph_d.h:277
ogdf::steiner_tree::goemans::BlowupGraph::getCoreCapacity
T getCoreCapacity(node v) const
Get capacity of a core edge.
Definition: BlowupGraph.h:543
ogdf::HashArray
Indexed arrays using hashing for element access.
Definition: HashArray.h:93
ogdf::steiner_tree::goemans::BlowupGraph::m_ceModule
const CoreEdgeModule< T > & m_ceModule
Definition: BlowupGraph.h:95
ogdf::steiner_tree::goemans::BlowupGraph::contract
void contract(NODELIST &nodes)
Contracts nodes.
Definition: BlowupGraph.h:621
ogdf::ArrayBuffer::push
void push(E e)
Puts a new element in the buffer.
Definition: ArrayBuffer.h:217
ogdf::steiner_tree::goemans::BlowupGraph::getSource
node getSource() const
Returns the source node.
Definition: BlowupGraph.h:506
ogdf::steiner_tree::FullComponentStore::cost
T cost(int i) const
Returns the sum of edge costs of this full component.
Definition: FullComponentStore.h:270
ogdf::steiner_tree::goemans::BlowupGraph::getPseudotarget
node getPseudotarget() const
Returns the pseudotarget node.
Definition: BlowupGraph.h:509
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
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::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:869
ogdf::steiner_tree::goemans::BlowupGraph::getTarget
node getTarget() const
Returns the target node.
Definition: BlowupGraph.h:512
ogdf::HashConstIterator
Iterators for hash tables.
Definition: Hashing.h:205
ogdf::steiner_tree::FullComponentStore::start
adjEntry start(int i) const
Definition: FullComponentStore.h:276
ogdf::steiner_tree::FullComponentWithExtraStore::extra
ExtraDataType & extra(int i)
Returns a reference to the extra data of this full component.
Definition: FullComponentStore.h:366
Math.h
Mathematical Helpers.
ogdf::steiner_tree::goemans::BlowupGraph::getLCM
int getLCM() const
Returns the least common multiple of all denominators.
Definition: BlowupGraph.h:527
ogdf::steiner_tree::goemans::BlowupGraph::initTarget
void initTarget()
Connects target.
Definition: BlowupGraph.h:272
ogdf::steiner_tree::FullComponentStore::isTerminal
bool isTerminal(int id, node t) const
checks if a given node t is a terminal in the full component with given id
Definition: FullComponentStore.h:261
ogdf::steiner_tree::FullComponentStore::graph
const EdgeWeightedGraph< T > & graph() const
Definition: FullComponentStore.h:282
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::AdjElement::cyclicSucc
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition: Graph_d.h:354
ogdf::steiner_tree::goemans::BlowupGraph::m_pseudotarget
node m_pseudotarget
Definition: BlowupGraph.h:92
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:410
ogdf::steiner_tree::goemans::BlowupGraph::newEdge
edge newEdge(node v, node w, T cost, int capacity)
Adds and returns a new edge between v and w of specified cost and capacity.
Definition: BlowupGraph.h:587
ogdf::steiner_tree::goemans::BlowupGraph::updateSpecialCapacities
void updateSpecialCapacities()
Updates capacities from source to terminals and terminals to pseudotarget.
Definition: BlowupGraph.h:571
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
ogdf::steiner_tree::goemans::BlowupGraph::copyComponent
void copyComponent(const edge origEdge, const int origCap, const int copyCap)
Copy a component in the blowup graph and set original capacity to origCap and capacity of copy to cop...
Definition: BlowupGraph.h:712
basic.h
Basic declarations, included by all source files.
ogdf::steiner_tree::goemans::BlowupGraph::contract
void contract(node &v, node t)
Contracts node v and terminal t into v.
Definition: BlowupGraph.h:602
ogdf::steiner_tree::goemans::BlowupGraph::capacities
const EdgeArray< int > & capacities() const
Returns a reference to the edge array containing all capacities.
Definition: BlowupGraph.h:518
ogdf::Graph::newNode
node newNode(int index=-1)
Creates a new node and returns it.
Definition: Graph_d.h:1064
ogdf::NodeElement::firstAdj
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition: Graph_d.h:286
ogdf::steiner_tree::goemans::BlowupGraph::isTerminal
bool isTerminal(node v) const
Returns true if and only if v is a terminal.
Definition: BlowupGraph.h:536
ogdf::steiner_tree::goemans::CoreEdgeModule
Interface for core edge finder algorithms.
Definition: BlowupGraph.h:48
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::goemans::BlowupGraph::initBlowupGraphComponents
void initBlowupGraphComponents(const EdgeWeightedGraph< T > &originalGraph, const List< node > &terminals)
Initializes all components in the blowup graph as well as core edges and witness sets.
Definition: BlowupGraph.h:209
ogdf::steiner_tree::goemans::BlowupGraph::makeCWCopy
void makeCWCopy(const HashArray< edge, edge > &edgeMap)
Copies witness sets and core edges for a given copy map.
Definition: BlowupGraph.h:440
ogdf::steiner_tree::goemans::BlowupGraph::m_coreEdges
List< node > m_coreEdges
the core edges as nodes
Definition: BlowupGraph.h:97
ogdf::steiner_tree::goemans::BlowupGraph::m_lcm
int m_lcm
Definition: BlowupGraph.h:89
ogdf::Graph::contract
node contract(edge e, bool keepSelfLoops=false)
Contracts edge e while preserving the order of adjacency entries.
ogdf::steiner_tree::goemans::BlowupGraph::m_target
node m_target
Definition: BlowupGraph.h:93
ogdf::ListIteratorBase
Encapsulates a pointer to a list element.
Definition: List.h:51
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::Graph::newEdge
edge newEdge(node v, node w, int index=-1)
Creates a new edge (v,w) and returns it.
Definition: Graph_d.h:1083
ogdf::steiner_tree::goemans::BlowupGraph::initTerminal
node initTerminal(node t)
Inserts a terminal.
Definition: BlowupGraph.h:146
ogdf::steiner_tree::goemans::BlowupGraph::m_y
int m_y
Definition: BlowupGraph.h:90
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::steiner_tree::goemans::BlowupGraph::witnessList
const ArrayBuffer< edge > & witnessList(node e) const
Return list of loss edges f in W(e)
Definition: BlowupGraph.h:769
ogdf::steiner_tree::FullComponentWithExtraStore
A data structure to store full components with extra data for each component.
Definition: FullComponentStore.h:361
ogdf::steiner_tree::goemans::BlowupGraph::m_witness
NodeArray< ArrayBuffer< edge > > m_witness
Definition: BlowupGraph.h:120
ogdf::steiner_tree::goemans::BlowupGraph::computeCoreWeight
double computeCoreWeight(node v) const
Compute the weight of a core edge.
Definition: BlowupGraph.h:559
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::steiner_tree::goemans::BlowupGraph::removeIsolatedTerminals
void removeIsolatedTerminals()
Removes isolated terminals.
Definition: BlowupGraph.h:679
ogdf::steiner_tree::goemans::BlowupGraph::getCapacity
int getCapacity(edge e) const
Returns the capacity of e.
Definition: BlowupGraph.h:515
ogdf::steiner_tree::goemans::BlowupGraph::computeLCM
void computeLCM()
Computes the least common multiple of the values assigned to the full components.
Definition: BlowupGraph.h:124
ogdf::steiner_tree::goemans::BlowupGraph::BlowupGraph
BlowupGraph(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const FullComponentWithExtraStore< T, double > &fullCompStore, const CoreEdgeModule< T > &ceModule, double eps=1e-8)
Initializes a blowup graph including core edges and witness sets.
Definition: BlowupGraph.h:469