Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MinSteinerTreePrimalDual.h
Go to the documentation of this file.
1
34#pragma once
35
37#include <ogdf/basic/Graph.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
49namespace ogdf {
50template<typename T>
51class EdgeWeightedGraph;
52
63template<typename T>
65private:
69 const T MAX_VALUE = std::numeric_limits<T>::max();
70
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
128protected:
144 virtual T computeSteinerTree(const EdgeWeightedGraph<T>& G, const List<node>& terminals,
145 const NodeArray<bool>& isTerminal, EdgeWeightedGraphCopy<T>*& finalSteinerTree) override;
146
147public:
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
162template<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
170template<typename T>
172 return m_pComponents->find(m_componentMapping[v]);
173}
174
175template<typename T>
176bool MinSteinerTreePrimalDual<T>::isActive(int component) const {
177 return m_activeComponentIterators[component].valid();
178}
179
180template<typename T>
182 m_activeComponentIterators[comp] = m_activeComponents.pushBack(comp);
183}
184
185template<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
205template<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
216template<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
245template<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
326template<typename T>
328 return m_lowerBound;
329}
330
331}
Implementation of disjoint sets data structures (union-find functionality).
Extends the GraphCopy concept to weighted graphs.
Includes declaration of graph class.
Declaration and implementation of HashArray class.
Declaration of doubly linked lists and iterators.
Declaration of ogdf::MinSteinerTreeModule.
Basic declarations, included by all source files.
A Union/Find data structure for maintaining disjoint sets.
Class for the representation of edges.
Definition Graph_d.h:364
node target() const
Returns the target node of the edge.
Definition Graph_d.h:402
node source() const
Returns the source node of the edge.
Definition Graph_d.h:399
edge newEdge(node u, node v, T weight)
void setOriginalGraph(const Graph *wG) override
Re-initializes the copy using G (which might be null), but does not create any nodes or edges.
node newNode(node vOrig)
Creates a new node in the graph copy with original node vOrig.
Definition GraphCopy.h:191
edge copy(edge e) const override
Returns the first edge in the list of edges corresponding to edge e.
Definition GraphCopy.h:463
Indexed arrays using hashing for element access.
Definition HashArray.h:93
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
Serves as an interface for various methods to compute or approximate minimum Steiner trees on undirec...
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.
Primal-Dual approximation algorithm for Steiner tree problems.
const NodeArray< bool > * m_pIsTerminal
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.
void mergeComponents(const node v, const node w)
Merges two disjoint components.
int getComponent(const node v) const
Finds the biggest set including node v.
void updatePriorities(double eps)
Must be called after merging any two components.
double getLastLowerBound() const
Returns the lower bound calculated while solving the last problem.
HashArray< int, ListIterator< int > > m_activeComponentIterators
double getNextEdge(edge *nextEdge)
Idendifies the next edge with a tight-to-be packing constraint.
void init()
Initializes all required datastructes.
bool isActive(int component) const
Returns whether the given component is active.
const EdgeWeightedGraph< T > * m_pGraph
void makeActive(int component)
Marks the specified component as active.
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.
Class for the representation of nodes.
Definition Graph_d.h:241
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.