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
35#include <ogdf/basic/Graph.h>
37#include <ogdf/basic/basic.h>
40#include <ogdf/tree/LCA.h>
41
42#include <utility>
43
44namespace ogdf::steiner_tree {
45template<typename T>
46class Triple;
47} // namespace ogdf::steiner_tree
48
49namespace ogdf {
50template<typename T>
51class EdgeWeightedGraphCopy;
52
53namespace steiner_tree {
54
60//#define OGDF_SAVEDYNAMIC_CHANGE_TST
61template<typename T>
62class SaveDynamic : public Save<T> {
63public:
71 : Save<T>()
72 , m_tree()
73 , m_treeEdge(m_tree, nullptr)
74 , m_steinerTree(&steinerTree)
75 , m_cTerminals(*m_steinerTree, nullptr) {
77 m_lca = new LCA(m_tree, m_root);
78 }
79
80 virtual ~SaveDynamic() { delete m_lca; }
81
90 virtual T gain(node u, node v, node w) const {
91 node save1 = lca(m_steinerTree->copy(u), m_steinerTree->copy(v));
92 node save2 = lca(m_steinerTree->copy(u), m_steinerTree->copy(w));
93 if (save1 == save2) {
94 save2 = lca(m_steinerTree->copy(v), m_steinerTree->copy(w));
95 }
96 return weight(save1) + weight(save2);
97 }
98
106 virtual T saveWeight(node u, node v) const { return weight(saveEdge(u, v)); }
107
115 virtual edge saveEdge(node u, node v) const {
116 OGDF_ASSERT(m_steinerTree->copy(u));
117 OGDF_ASSERT(m_steinerTree->copy(v));
118 node anc = lca(m_steinerTree->copy(u), m_steinerTree->copy(v));
119 OGDF_ASSERT(anc);
120 return m_treeEdge[anc];
121 }
122
131 virtual void update(const Triple<T>& t) {
132#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
133 edge se0 = saveEdge(t.s0(), t.s1());
134 edge se1 = saveEdge(t.s0(), t.s2());
135 edge se2 = saveEdge(t.s1(), t.s2());
136#endif
137 // initialize the three terminal nodes
138 node s0 = m_steinerTree->copy(t.s0());
139 node s1 = m_steinerTree->copy(t.s1());
140 node s2 = m_steinerTree->copy(t.s2());
141
142 // determine the save edges
143 node save1 = lca(s0, s1);
144 node save2 = lca(s0, s2);
145 if (save1 == save2) {
146 save2 = lca(s1, s2);
147 }
148
149 node v0 = m_cTerminals[s0];
150 node v1 = m_cTerminals[s1];
151 node v2 = m_cTerminals[s2];
152
153 int v0level = m_lca->level(v0);
154 int v1level = m_lca->level(v1);
155 int v2level = m_lca->level(v2);
156
157 delete m_lca;
158
159 node v = m_tree.newNode();
160 node currentNode = m_tree.newNode();
161#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
162 const node newNode0 = v, newNode1 = currentNode;
163#endif
164 OGDF_ASSERT(!m_treeEdge[currentNode]);
165 m_tree.newEdge(currentNode, v);
166 m_cTerminals[s0] = v;
167 m_cTerminals[s1] = v;
168 m_cTerminals[s2] = currentNode;
169
170 while (v0) {
171 // bubble pointers such that level(v0) >= level(v1) >= level(v2)
172 if (v1level < v2level) {
173 std::swap(v1, v2);
174 std::swap(v1level, v2level);
175 }
176 if (v0level < v1level) {
177 std::swap(v0, v1);
178 std::swap(v0level, v1level);
179 }
180 if (v1level < v2level) {
181 std::swap(v1, v2);
182 std::swap(v1level, v2level);
183 }
184 // bubble pointers such that weight(v0) <= weight(v1), weight(v2)
185 if (weight(v1) > weight(v2)) {
186 std::swap(v1, v2);
187 std::swap(v1level, v2level);
188 }
189 if (weight(v0) > weight(v1)) {
190 std::swap(v0, v1);
191 std::swap(v0level, v1level);
192 }
193 // now v0 is the node with the least weight... if equal, with the highest level.
194
195 if (v0 != save1 && v0 != save2) {
196 for (adjEntry adj : currentNode->adjEntries) {
197 edge e = adj->theEdge();
198 if (e->target() == currentNode) {
199 m_tree.delEdge(e);
200 break;
201 }
202 }
203 m_tree.newEdge(v0, currentNode);
204 currentNode = v0;
205 } // else: nothing to do since m_tree is binary and save1/save2 are LCAs
206
207 // set v0 to its parent or to nullptr if there is no parent
208 v = v0;
209 v0 = nullptr;
210 edge e = nullptr;
211 for (adjEntry adj : v->adjEntries) {
212 e = adj->theEdge();
213 if (e->target() == v) {
214 v0 = e->source();
215 --v0level;
216 break;
217 }
218 }
219 OGDF_ASSERT(e != nullptr);
220 if (v1 == e->target()) {
221 v1 = e->source();
222 --v1level;
223 }
224 if (v2 == e->target()) {
225 v2 = e->source();
226 --v2level;
227 }
228 }
229 m_root = currentNode;
230 m_tree.delNode(save1);
231 m_tree.delNode(save2);
232
233 m_lca = new LCA(m_tree, m_root);
234
235#ifdef OGDF_SAVEDYNAMIC_CHANGE_TST
236 edge newEdge0, newEdge1;
237 contractTripleInSteinerTree(t, *m_steinerTree, se0, se1, se2, newEdge0, newEdge1);
238 m_treeEdge[newNode0] = newEdge0;
239 m_treeEdge[newNode1] = newEdge1;
240#endif
241 }
242
243protected:
251 node lca(node u, node v) const {
252 OGDF_ASSERT(u);
253 OGDF_ASSERT(v);
254 return m_lca->call(m_cTerminals[u], m_cTerminals[v]);
255 }
256
258 T weight(edge e) const { return e ? m_steinerTree->weight(e) : 0; }
259
261 T weight(node v) const { return weight(m_treeEdge[v]); }
262
263private:
267#ifndef OGDF_SAVEDYNAMIC_CHANGE_TST
268 const
269#endif
273};
274
275}
276}
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
The Sparse Table Algorithm for the Least Common Ancestor problem as proposed by Bender and Farach-Col...
Interface for various LCA methods.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
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
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
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(int index=-1)
Creates a new node and returns it.
Definition Graph_d.h:1061
edge newEdge(node v, node w, int index=-1)
Creates a new edge (v,w) and returns it.
Definition Graph_d.h:1080
Implements the <O(n log n), O(1)>-time "sparse table" algorithm by Bender and Farach-Colton to comput...
Definition LCA.h:54
int level(node v) const
Returns the level of a node. The level of the root is 0.
Definition LCA.h:76
node call(node u, node v) const
Returns the LCA of two nodes u and v.
Class for the representation of nodes.
Definition Graph_d.h:241
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:272
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
Dynamically updatable weighted Tree for determining save edges via LCA computation.
Definition SaveDynamic.h:62
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.
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:90
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:70
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:50
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:52
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.