Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

MinSteinerTreePrimalDual.h
Go to the documentation of this file.
1 
34 #pragma once
35 
37 #include <ogdf/basic/Graph.h>
38 #include <ogdf/basic/HashArray.h>
39 #include <ogdf/basic/List.h>
40 #include <ogdf/basic/basic.h>
43 
44 #include <iostream>
45 #include <limits>
46 
47 //#define OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
48 
49 namespace ogdf {
50 template<typename T>
51 class EdgeWeightedGraph;
52 
63 template<typename T>
65 private:
69  const T MAX_VALUE = std::numeric_limits<T>::max();
70 
75  double m_lowerBound;
77 
84  void mergeComponents(const node v, const node w);
85 
91  void makeActive(int component);
92 
98  bool isActive(int component) const;
99 
105  int getComponent(const node v) const;
106 
113  double getNextEdge(edge* nextEdge);
114 
121  void updatePriorities(double eps);
122 
126  void init();
127 
128 protected:
144  virtual T computeSteinerTree(const EdgeWeightedGraph<T>& G, const List<node>& terminals,
145  const NodeArray<bool>& isTerminal, EdgeWeightedGraphCopy<T>*& finalSteinerTree) override;
146 
147 public:
148  virtual T call(const EdgeWeightedGraph<T>& G, const List<node>& terminals,
149  const NodeArray<bool>& isTerminal, EdgeWeightedGraphCopy<T>*& finalSteinerTree) override {
150  m_lowerBound = 0;
151  return MinSteinerTreeModule<T>::call(G, terminals, isTerminal, finalSteinerTree);
152  }
153 
159  double getLastLowerBound() const;
160 };
161 
162 template<typename T>
164  m_activeComponentIterators.clear();
165  m_activeComponents.clear();
166  m_componentMapping.init(*m_pGraph);
167  m_priorities.init(*m_pGraph, 0);
168 }
169 
170 template<typename T>
172  return m_pComponents->find(m_componentMapping[v]);
173 }
174 
175 template<typename T>
176 bool MinSteinerTreePrimalDual<T>::isActive(int component) const {
177  return m_activeComponentIterators[component].valid();
178 }
179 
180 template<typename T>
182  m_activeComponentIterators[comp] = m_activeComponents.pushBack(comp);
183 }
184 
185 template<typename T>
187  int compV = getComponent(v);
188  int compW = getComponent(w);
189 
190  // remove former components
191  if (isActive(compV)) {
192  m_activeComponents.del(m_activeComponentIterators[compV]);
193  }
194  if (isActive(compW)) {
195  m_activeComponents.del(m_activeComponentIterators[compW]);
196  }
197 
198  // craete new component
199  int compNew = m_pComponents->link(compV, compW);
200  if (!m_activeComponents.empty()) {
201  makeActive(compNew);
202  }
203 }
204 
205 template<typename T>
207  List<node> nodes;
208  m_pGraph->allNodes(nodes);
209  for (node v : nodes) {
210  if (isActive(getComponent(v))) {
211  m_priorities(v) += eps;
212  }
213  }
214 }
215 
216 template<typename T>
218  double result = MAX_VALUE;
219  *nextEdge = nullptr;
220 
221  List<edge> edges;
222  m_pGraph->allEdges(edges);
223  for (edge e : edges) {
224  node v = e->source();
225  node w = e->target();
226  int compV = getComponent(v);
227  int compW = getComponent(w);
228  if (compV != compW) { // spanning different components ?
229  double value = m_pGraph->weight(e) - m_priorities(v) - m_priorities(w);
230  int divisor = isActive(compV) + isActive(compW);
231  if (divisor == 0) {
232  value = MAX_VALUE;
233  } else {
234  value /= divisor;
235  }
236  if (*nextEdge == nullptr || value < result) {
237  *nextEdge = e;
238  result = value;
239  }
240  }
241  }
242  return result;
243 }
244 
245 template<typename T>
247  const List<node>& terminals, const NodeArray<bool>& isTerminal,
248  EdgeWeightedGraphCopy<T>*& finalSteinerTree) {
249  m_pGraph = &G;
250  m_pTerminals = &terminals;
251  m_pIsTerminal = &isTerminal;
252  DisjointSets<> components;
253  m_pComponents = &components;
254 
255  finalSteinerTree = new EdgeWeightedGraphCopy<T>();
256  finalSteinerTree->setOriginalGraph(*m_pGraph);
257 
258  init();
259 
260  // initialize components
261  List<node> nodes;
262  m_pGraph->allNodes(nodes);
263  for (node v : nodes) {
264  int comp = m_pComponents->makeSet();
265  m_componentMapping[v] = comp;
266  if (isTerminal(v)) {
267  makeActive(comp);
268  }
269  }
270 
271 #ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
272  std::cout << "Goemans primal-dual starting..." << std::endl;
273  std::cout << "terminals:";
274  for (node v : *m_pTerminals) {
275  std::cout << " " << v;
276  }
277  std::cout << std::endl;
278 
279  std::cout << "loop starting... " << std::endl;
280 #endif
281 
282  T result = 0;
283  while (!m_activeComponents.empty()) {
284 #ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
285  std::cout << "active component exists" << std::endl;
286 #endif
287  // idendify next edge
288  edge minEdge = nullptr;
289  double minValue = getNextEdge(&minEdge);
290  OGDF_ASSERT(minEdge != nullptr);
291 
292 #ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
293  std::cout << "minEdge found: " << minEdge << ", weight is " << m_pGraph->weight(minEdge)
294  << ", adjusted weight is " << minValue << std::endl;
295 #endif
296  node v = minEdge->source();
297  node w = minEdge->target();
298 
299  // include nodes in Steiner tree
300  if (finalSteinerTree->copy(v) == nullptr) {
301  finalSteinerTree->newNode(v);
302  }
303  if (finalSteinerTree->copy(w) == nullptr) {
304  finalSteinerTree->newNode(w);
305  }
306 
307  // include edge in Steiner tree
308  T weight = m_pGraph->weight(minEdge);
309  result += weight;
310  finalSteinerTree->newEdge(minEdge, weight);
311 
312  m_lowerBound += m_activeComponents.size() * minValue;
313 
314  mergeComponents(v, w);
315 
316  updatePriorities(minValue);
317  }
318  result -= this->pruneAllDanglingSteinerPaths(*finalSteinerTree, *m_pIsTerminal);
319 
320 #ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
321  std::cout << "calculation finished!" << std::endl;
322 #endif
323  return result;
324 }
325 
326 template<typename T>
328  return m_lowerBound;
329 }
330 
331 }
HashArray.h
Declaration and implementation of HashArray class.
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
Graph.h
Includes declaration of graph class.
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::MinSteinerTreePrimalDual::m_componentMapping
NodeArray< int > m_componentMapping
Definition: MinSteinerTreePrimalDual.h:71
ogdf::MinSteinerTreePrimalDual::isActive
bool isActive(int component) const
Returns whether the given component is active.
Definition: MinSteinerTreePrimalDual.h:176
ogdf::EdgeWeightedGraphCopy::setOriginalGraph
void setOriginalGraph(const Graph *wG) override
Associates the graph copy with G, but does not create any nodes or edges.
Definition: EdgeWeightedGraphCopy.h:162
ogdf::MinSteinerTreePrimalDual
Primal-Dual approximation algorithm for Steiner tree problems.
Definition: MinSteinerTreePrimalDual.h:64
ogdf::EdgeWeightedGraphCopy::newEdge
edge newEdge(node u, node v, T weight)
Definition: EdgeWeightedGraphCopy.h:169
ogdf::MinSteinerTreePrimalDual::m_lowerBound
double m_lowerBound
Definition: MinSteinerTreePrimalDual.h:75
ogdf::MinSteinerTreePrimalDual::updatePriorities
void updatePriorities(double eps)
Must be called after merging any two components.
Definition: MinSteinerTreePrimalDual.h:206
ogdf::MinSteinerTreePrimalDual::init
void init()
Initializes all required datastructes.
Definition: MinSteinerTreePrimalDual.h:163
ogdf::MinSteinerTreePrimalDual::m_priorities
NodeArray< double > m_priorities
Definition: MinSteinerTreePrimalDual.h:76
EdgeWeightedGraphCopy.h
Extends the GraphCopy concept to weighted graphs.
ogdf::MinSteinerTreePrimalDual::m_activeComponents
List< int > m_activeComponents
Definition: MinSteinerTreePrimalDual.h:74
ogdf::MinSteinerTreeModule
Serves as an interface for various methods to compute or approximate minimum Steiner trees on undirec...
Definition: MinSteinerTreeModule.h:72
MinSteinerTreeModule.h
Declaration of ogdf::MinSteinerTreeModule.
ogdf::MinSteinerTreePrimalDual::MAX_VALUE
const T MAX_VALUE
Definition: MinSteinerTreePrimalDual.h:69
ogdf::MinSteinerTreePrimalDual::m_pTerminals
const List< node > * m_pTerminals
Definition: MinSteinerTreePrimalDual.h:67
ogdf::DisjointSets
A Union/Find data structure for maintaining disjoint sets.
Definition: DisjointSets.h:90
ogdf::EdgeWeightedGraph
Definition: GraphIO.h:56
ogdf::MinSteinerTreePrimalDual::m_pGraph
const EdgeWeightedGraph< T > * m_pGraph
Definition: MinSteinerTreePrimalDual.h:66
ogdf::MinSteinerTreePrimalDual::m_pComponents
DisjointSets * m_pComponents
Definition: MinSteinerTreePrimalDual.h:72
ogdf::MinSteinerTreePrimalDual::makeActive
void makeActive(int component)
Marks the specified component as active.
Definition: MinSteinerTreePrimalDual.h:181
ogdf::HashArray
Indexed arrays using hashing for element access.
Definition: HashArray.h:93
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::GraphCopyBase::newNode
node newNode(node vOrig)
Creates a new node in the graph copy with original node vOrig.
Definition: GraphCopy.h:192
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::MinSteinerTreePrimalDual::getNextEdge
double getNextEdge(edge *nextEdge)
Idendifies the next edge with a tight-to-be packing constraint.
Definition: MinSteinerTreePrimalDual.h:217
ogdf::MinSteinerTreePrimalDual::m_activeComponentIterators
HashArray< int, ListIterator< int > > m_activeComponentIterators
Definition: MinSteinerTreePrimalDual.h:73
ogdf::GraphCopy::copy
edge copy(edge e) const override
Returns the first edge in the list of edges corresponding to edge e.
Definition: GraphCopy.h:464
ogdf::MinSteinerTreeModule::call
virtual T call(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const NodeArray< bool > &isTerminal, EdgeWeightedGraphCopy< T > *&finalSteinerTree)
Calls the Steiner tree algorithm for nontrivial cases but handles trivial cases directly.
Definition: MinSteinerTreeModule.h:399
ogdf::MinSteinerTreePrimalDual::call
virtual T call(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const NodeArray< bool > &isTerminal, EdgeWeightedGraphCopy< T > *&finalSteinerTree) override
Calls the Steiner tree algorithm for nontrivial cases but handles trivial cases directly.
Definition: MinSteinerTreePrimalDual.h:148
ogdf::graphics::init
void init()
Definition: graphics.h:450
ogdf::MinSteinerTreePrimalDual::computeSteinerTree
virtual T computeSteinerTree(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const NodeArray< bool > &isTerminal, EdgeWeightedGraphCopy< T > *&finalSteinerTree) override
Builds a minimum Steiner tree given a weighted graph and a list of terminals.
Definition: MinSteinerTreePrimalDual.h:246
basic.h
Basic declarations, included by all source files.
ogdf::MinSteinerTreePrimalDual::mergeComponents
void mergeComponents(const node v, const node w)
Merges two disjoint components.
Definition: MinSteinerTreePrimalDual.h:186
ogdf::MinSteinerTreePrimalDual::getLastLowerBound
double getLastLowerBound() const
Returns the lower bound calculated while solving the last problem.
Definition: MinSteinerTreePrimalDual.h:327
ogdf::EdgeWeightedGraphCopy
Definition: EdgeWeightedGraphCopy.h:44
DisjointSets.h
Implementation of disjoint sets data structures (union-find functionality).
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::MinSteinerTreePrimalDual::m_pIsTerminal
const NodeArray< bool > * m_pIsTerminal
Definition: MinSteinerTreePrimalDual.h:68
ogdf::Math::minValue
Container::value_type minValue(const Container &values)
Returns the minimum of an iterable container of given values.
Definition: Math.h:232
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::MinSteinerTreePrimalDual::getComponent
int getComponent(const node v) const
Finds the biggest set including node v.
Definition: MinSteinerTreePrimalDual.h:171