Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
SaveDynamic.h
Go to the documentation of this file.
1
33#pragma once
34
38#include <ogdf/tree/LCA.h>
39
40namespace ogdf {
41namespace steiner_tree {
42
48//#define OGDF_SAVEDYNAMIC_CHANGE_TST
49template<typename T>
50class SaveDynamic : public Save<T> {
51public:
67
68 virtual ~SaveDynamic() { delete m_lca; }
69
78 virtual T gain(node u, node v, node w) const {
79 node save1 = lca(m_steinerTree->copy(u), m_steinerTree->copy(v));
80 node save2 = lca(m_steinerTree->copy(u), m_steinerTree->copy(w));
81 if (save1 == save2) {
82 save2 = lca(m_steinerTree->copy(v), m_steinerTree->copy(w));
83 }
84 return weight(save1) + weight(save2);
85 }
86
94 virtual T saveWeight(node u, node v) const { return weight(saveEdge(u, v)); }
95
103 virtual edge saveEdge(node u, node v) const {
104 OGDF_ASSERT(m_steinerTree->copy(u));
105 OGDF_ASSERT(m_steinerTree->copy(v));
106 node anc = lca(m_steinerTree->copy(u), m_steinerTree->copy(v));
108 return m_treeEdge[anc];
109 }
110
119 virtual void update(const Triple<T>& t) {
120#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
121 edge se0 = saveEdge(t.s0(), t.s1());
122 edge se1 = saveEdge(t.s0(), t.s2());
123 edge se2 = saveEdge(t.s1(), t.s2());
124#endif
125 // initialize the three terminal nodes
126 node s0 = m_steinerTree->copy(t.s0());
127 node s1 = m_steinerTree->copy(t.s1());
128 node s2 = m_steinerTree->copy(t.s2());
129
130 // determine the save edges
131 node save1 = lca(s0, s1);
132 node save2 = lca(s0, s2);
133 if (save1 == save2) {
134 save2 = lca(s1, s2);
135 }
136
137 node v0 = m_cTerminals[s0];
138 node v1 = m_cTerminals[s1];
139 node v2 = m_cTerminals[s2];
140
141 int v0level = m_lca->level(v0);
142 int v1level = m_lca->level(v1);
143 int v2level = m_lca->level(v2);
144
145 delete m_lca;
146
147 node v = m_tree.newNode();
149#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
150 const node newNode0 = v, newNode1 = currentNode;
151#endif
154 m_cTerminals[s0] = v;
155 m_cTerminals[s1] = v;
157
158 while (v0) {
159 // bubble pointers such that level(v0) >= level(v1) >= level(v2)
160 if (v1level < v2level) {
161 std::swap(v1, v2);
162 std::swap(v1level, v2level);
163 }
164 if (v0level < v1level) {
165 std::swap(v0, v1);
166 std::swap(v0level, v1level);
167 }
168 if (v1level < v2level) {
169 std::swap(v1, v2);
170 std::swap(v1level, v2level);
171 }
172 // bubble pointers such that weight(v0) <= weight(v1), weight(v2)
173 if (weight(v1) > weight(v2)) {
174 std::swap(v1, v2);
175 std::swap(v1level, v2level);
176 }
177 if (weight(v0) > weight(v1)) {
178 std::swap(v0, v1);
179 std::swap(v0level, v1level);
180 }
181 // now v0 is the node with the least weight... if equal, with the highest level.
182
183 if (v0 != save1 && v0 != save2) {
184 for (adjEntry adj : currentNode->adjEntries) {
185 edge e = adj->theEdge();
186 if (e->target() == currentNode) {
187 m_tree.delEdge(e);
188 break;
189 }
190 }
192 currentNode = v0;
193 } // else: nothing to do since m_tree is binary and save1/save2 are LCAs
194
195 // set v0 to its parent or to nullptr if there is no parent
196 v = v0;
197 v0 = nullptr;
198 edge e = nullptr;
199 for (adjEntry adj : v->adjEntries) {
200 e = adj->theEdge();
201 if (e->target() == v) {
202 v0 = e->source();
203 --v0level;
204 break;
205 }
206 }
207 OGDF_ASSERT(e != nullptr);
208 if (v1 == e->target()) {
209 v1 = e->source();
210 --v1level;
211 }
212 if (v2 == e->target()) {
213 v2 = e->source();
214 --v2level;
215 }
216 }
220
221 m_lca = new LCA(m_tree, m_root);
222
223#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
228#endif
229 }
230
231protected:
239 node lca(node u, node v) const {
240 OGDF_ASSERT(u);
241 OGDF_ASSERT(v);
242 return m_lca->call(m_cTerminals[u], m_cTerminals[v]);
243 }
244
246 T weight(edge e) const { return e ? m_steinerTree->weight(e) : 0; }
247
249 T weight(node v) const { return weight(m_treeEdge[v]); }
250
251private:
255#ifndef OGDF_SAVEDYNAMIC_CHANGE_TST
256 const
257#endif
261};
262
263}
264}
The Sparse Table Algorithm for the Least Common Ancestor problem as proposed by Bender and Farach-Col...
Interface for various LCA methods.
Definition of a Triple used in contraction-based approximation algorithm for the minimum Steiner tree...
Class for adjacency list elements.
Definition Graph_d.h:79
Class for the representation of edges.
Definition Graph_d.h:300
node target() const
Returns the target node of the edge.
Definition Graph_d.h:338
node source() const
Returns the source node of the edge.
Definition Graph_d.h:335
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:521
edge newEdge(node v, node w)
Creates a new edge (v,w) and returns it.
virtual void delNode(node v)
Removes node v and all incident edges from the graph.
virtual void delEdge(edge e)
Removes edge e from the graph.
node newNode()
Creates a new node and returns it.
Implements the <O(n log n), O(1)>-time "sparse table" algorithm by Bender and Farach-Colton to comput...
Definition LCA.h:52
int level(node v) const
Returns the level of a node. The level of the root is 0.
Definition LCA.h:74
node call(node u, node v) const
Returns the LCA of two nodes u and v.
Dynamic arrays indexed with nodes.
Definition NodeArray.h:125
Class for the representation of nodes.
Definition Graph_d.h:177
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:208
Dynamically updatable weighted Tree for determining save edges via LCA computation.
Definition SaveDynamic.h:50
Graph m_tree
The weighted binary tree to represent the edge weight hierarchy.
node lca(node u, node v) const
Returns the node in m_tree that is the LCA of two nodes.
virtual T saveWeight(node u, node v) const
Determines the weight of the save edge between two nodes by a LCA query.
Definition SaveDynamic.h:94
virtual T gain(node u, node v, node w) const
Returns the gain (sum of save edge costs) of the given triple, calculated by an LCA query.
Definition SaveDynamic.h:78
virtual void update(const Triple< T > &t)
Updates the weighted tree data structure given a contracted triple.
NodeArray< node > m_cTerminals
Connects terminal nodes in the terminal spanning tree to their leafs in the weighted tree.
node m_root
The root node of the weighted binary tree.
SaveDynamic(EdgeWeightedGraphCopy< T > &steinerTree)
Builds a weighted binary tree based on the given terminal spanning tree.
Definition SaveDynamic.h:58
T weight(node v) const
Returns the associated weight of a node v in m_tree, or 0 if it is not associated.
T weight(edge e) const
Returns the weight of an edge in the terminal tree or 0.
LCA * m_lca
Data structure for calculating the LCAs.
virtual edge saveEdge(node u, node v) const
Determines the save edge between two nodes by a LCA query.
const EdgeWeightedGraphCopy< T > * m_steinerTree
The underlying terminal spanning tree this weighted tree instance represents.
NodeArray< edge > m_treeEdge
Maps each inner node of m_tree to an edge in m_steinerTree.
This class serves as an interface for different approaches concerning the calculation of save edges.
Definition Save.h:45
This class represents a triple used by various contraction-based minimum Steiner tree approximations.
Definition Triple.h:44
Algorithms used by at least two functions of Steiner tree code or its internal helpers.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
node buildHeaviestEdgeInComponentTree(const EdgeWeightedGraphCopy< T > &inputTree, NodeArray< node > &externalNodes, NodeArray< edge > &treeEdge, Graph &outputTree)
Given an edge-weighted tree, builds an auxiliary arborescence where each arc of the input tree is a n...
void contractTripleInSteinerTree(const Triple< T > &t, EdgeWeightedGraphCopy< T > &st, edge save0, edge save1, edge save2, edge &ne0, edge &ne1)
Updates the Steiner tree by deleting save edges, removing all direct connections between the terminal...
The namespace for all OGDF objects.