51class EdgeWeightedGraph;
164 m_activeComponentIterators.clear();
165 m_activeComponents.clear();
166 m_componentMapping.init(*m_pGraph);
167 m_priorities.init(*m_pGraph, 0);
172 return m_pComponents->find(m_componentMapping[v]);
177 return m_activeComponentIterators[component].valid();
182 m_activeComponentIterators[comp] = m_activeComponents.pushBack(comp);
187 int compV = getComponent(v);
188 int compW = getComponent(w);
191 if (isActive(compV)) {
192 m_activeComponents.del(m_activeComponentIterators[compV]);
194 if (isActive(compW)) {
195 m_activeComponents.del(m_activeComponentIterators[compW]);
199 int compNew = m_pComponents->link(compV, compW);
200 if (!m_activeComponents.empty()) {
208 m_pGraph->allNodes(nodes);
209 for (
node v : nodes) {
210 if (isActive(getComponent(v))) {
211 m_priorities(v) += eps;
218 double result = MAX_VALUE;
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) {
229 double value = m_pGraph->weight(e) - m_priorities(v) - m_priorities(w);
230 int divisor = isActive(compV) + isActive(compW);
236 if (*nextEdge ==
nullptr || value < result) {
250 m_pTerminals = &terminals;
251 m_pIsTerminal = &isTerminal;
253 m_pComponents = &components;
262 m_pGraph->allNodes(nodes);
263 for (
node v : nodes) {
264 int comp = m_pComponents->makeSet();
265 m_componentMapping[v] = comp;
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;
277 std::cout << std::endl;
279 std::cout <<
"loop starting... " << std::endl;
283 while (!m_activeComponents.empty()) {
284#ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
285 std::cout <<
"active component exists" << std::endl;
288 edge minEdge =
nullptr;
289 double minValue = getNextEdge(&minEdge);
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;
300 if (finalSteinerTree->
copy(v) ==
nullptr) {
303 if (finalSteinerTree->
copy(w) ==
nullptr) {
308 T weight = m_pGraph->weight(minEdge);
310 finalSteinerTree->
newEdge(minEdge, weight);
312 m_lowerBound += m_activeComponents.size() * minValue;
314 mergeComponents(v, w);
316 updatePriorities(minValue);
318 result -= this->pruneAllDanglingSteinerPaths(*finalSteinerTree, *m_pIsTerminal);
320#ifdef OGDF_MINSTEINERTREE_PRIMAL_DUAL_LOGGING
321 std::cout <<
"calculation finished!" << std::endl;
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.
node target() const
Returns the target node of the edge.
node source() const
Returns the source node of the edge.
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.
edge copy(edge e) const override
Returns the first edge in the list of edges corresponding to edge e.
Indexed arrays using hashing for element access.
Doubly linked lists (maintaining the length of the list).
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.
List< int > m_activeComponents
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.
NodeArray< int > m_componentMapping
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.
NodeArray< double > m_priorities
void init()
Initializes all required datastructes.
bool isActive(int component) const
Returns whether the given component is active.
const EdgeWeightedGraph< T > * m_pGraph
const List< node > * m_pTerminals
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.
DisjointSets * m_pComponents
Class for the representation of nodes.
RegisteredArray for nodes, edges and adjEntries of a graph.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
The namespace for all OGDF objects.