Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MinimumCutStoerWagner.h
Go to the documentation of this file.
1
32#pragma once
33
35#include <ogdf/basic/Math.h>
38
39namespace ogdf {
40
49template<typename T = double>
52 virtual T call(const Graph& G) override {
54 return call(G, weights);
55 }
56
58 virtual T call(const Graph& G, const EdgeArray<T>& weights) override {
59 m_minCut = std::numeric_limits<T>::max();
60 m_GC.init(G);
61 m_w.init(m_GC);
63
64 for (edge e : m_GC.edges) {
65 m_w[e] = weights[m_GC.original(e)];
66 OGDF_ASSERT(m_w[e] >= T {});
67 }
68 for (node v : m_GC.nodes) {
69 m_contractedNodes[v].pushBack(m_GC.original(v));
70 }
71
72 mainLoop();
73
74 return value();
75 }
76
82 virtual const ArrayBuffer<edge>& edges() override {
83 if (!m_cutEdges.empty()) {
84 return m_cutEdges;
85 }
86
88
89 for (node v : m_partition) {
90 inPartition[v] = true;
91 }
92
93 for (node v : m_partition) {
94 for (adjEntry adj : v->adjEntries) {
95 if (!inPartition[adj->twinNode()]) {
96 m_cutEdges.push(adj->theEdge());
97 }
98 }
99 }
100 return m_cutEdges;
101 }
102
104 virtual const ArrayBuffer<node>& nodes() override { return m_partition; }
105
106 virtual T value() const override { return m_minCut; }
107
108protected:
111
114
117
120
123
128
130 void mainLoop() {
131 m_partition.clear();
133 while (m_GC.numberOfNodes() > 1) {
135 if (m_minCut == T {}) { // cannot get better so return early
136 return;
137 }
138 }
139 }
140
142 T minimumCutPhase();
143
148 void contraction(node t, node s);
149};
150
151template<typename T>
153 OGDF_ASSERT(t != s);
154
155 // Since nodes in #m_GC correspond to sets of nodes (due to the node contraction),
156 // the NodeArray #m_contractedNodes has to be updated.
157 // Hence append the list of contracted nodes of s to the list of t.
158 m_contractedNodes[t].conc(m_contractedNodes(s));
159
160 // Redirect edges and delete node s
161 safeForEach(s->adjEntries, [&](adjEntry adj) {
162 edge e = adj->theEdge();
163 if (e->source() == t || e->target() == t) {
164 m_GC.delEdge(e);
165 } else if (e->source() == s) {
166 m_GC.moveSource(e, t);
167 } else {
168 m_GC.moveTarget(e, t);
169 }
170 });
171 m_GC.delNode(s);
172
173 // NodeArray containing the first edge of parallel edges
174 NodeArray<edge> incident {m_GC, nullptr};
175
176 // Delete parallel edges and add their weights
177 safeForEach(t->adjEntries, [&](adjEntry adj) {
178 node v {adj->twinNode()};
179 if (v != t) {
180 edge e {adj->theEdge()};
181 edge& f {incident[v]};
182 if (f == nullptr) {
183 f = e;
184 } else {
185 m_w[f] += m_w[e];
186 m_GC.delEdge(e);
187 }
188 }
189 });
190}
191
192template<typename T>
194 /*
195 * This function computes the mincut of the current phase.
196 * First, nodes are explored successively in descending order of the sum of
197 * their incident edge weights; \a s and \a t are always the two last added nodes.
198 * Afterwards, the current mincut value \a cutOfThePhase is computed, which corresponds to the
199 * sum of the weights of those edges incident to node \a t.
200 * At the end, \a s and \a t are contracted and the \a cutOfThePhase is returned.
201 */
202
203 // A priority queue containing the unexplored nodes.
204 // Priorities are the (negative) sum of edge weights incident to the explored nodes.
206 for (node v : m_GC.nodes) {
207 pq.push(v, T {});
208 }
209 std::function<void(node)> updatePQ {[&](node currentNode) {
210 OGDF_ASSERT(!pq.contains(currentNode));
211 for (adjEntry adj : currentNode->adjEntries) {
212 node v {adj->twinNode()};
213 // The code below is at it is due to numerical issues with T=double.
214 if (pq.contains(v)) {
215 T newPriority {pq.priority(v) - m_w[adj->theEdge()]};
216 if (newPriority < pq.priority(v)) {
217 pq.decrease(adj->twinNode(), newPriority);
218 }
219 }
220 }
221 }};
222
223 // The start node can be chosen arbitrarily. It has no effect on the correctness of the algorithm.
224 node s {nullptr};
225 node t {pq.topElement()};
226 pq.pop();
227
228 updatePQ(t);
229
230 // Successively adding the most tightly connected node.
231 while (!pq.empty()) {
232 // Find the most tightly connected node and remove it from the priority queue
233 node currentNode {pq.topElement()};
234 pq.pop();
235
236 // Push the current node to the 2-element list consisting of s and t
237 s = currentNode;
238 std::swap(s, t);
239
240 // Update the priorities
242 }
243
244 // Contains the mincut value according to the current phase.
245 T phaseCut {};
246 for (adjEntry adj : t->adjEntries) {
247 edge e {adj->theEdge()};
248 if (!e->isSelfLoop()) {
249 phaseCut += m_w[adj->theEdge()];
250 }
251 }
252
253 // If the current \a phaseCut is strictly smaller than the global mincut value,
254 // the partition defining the mincut has to be updated.
255 if (phaseCut < m_minCut) {
256 m_partition.clear();
257 for (node v : m_contractedNodes[t]) {
258 m_partition.push(v);
259 }
260 }
261
262 // Performing the node contraction of nodes \a s and \a t.
263 contraction(t, s);
264
265 return phaseCut;
266}
267
268}
Declaration of graph copy classes.
Declaration of ogdf::MinimumCutModule.
Priority queue interface wrapping various heaps.
Mathematical Helpers.
Class for adjacency list elements.
Definition Graph_d.h:79
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:56
void clear()
Clears the buffer.
Definition ArrayBuffer.h:95
void push(E e)
Puts a new element in the buffer.
bool empty() const
Returns true if the buffer is empty, false otherwise.
Dynamic arrays indexed with edges.
Definition EdgeArray.h:125
Class for the representation of edges.
Definition Graph_d.h:300
Copies of graphs supporting edge splitting.
Definition GraphCopy.h:254
void init(const Graph &G)
Re-initializes the copy using the graph G.
const Graph & original() const
Returns a reference to the original graph.
Definition GraphCopy.h:289
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:521
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition Graph_d.h:622
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition Graph_d.h:589
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition Graph_d.h:592
Serves as an interface for various methods to compute minimum cuts with or without edge weights.
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
Prioritized queue interface wrapper for heaps.
AdjElement * adjEntry
The type of adjacency entries.
Definition Graph_d.h:72
EdgeElement * edge
The type of edges.
Definition Graph_d.h:68
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
void updateMin(T &min, const T &newValue)
Stores the minimum of min and newValue in min.
Definition Math.h:98
The namespace for all OGDF objects.
void safeForEach(CONTAINER &container, std::function< void(typename CONTAINER::value_type)> func)
Calls (possibly destructive) func for each element of container.
Computes a minimum cut in a graph.
void contraction(node t, node s)
Contracts the nodes s and t, i.e., s is collapsed to t. The edge (if existing) between s and t is del...
ArrayBuffer< node > m_partition
Store one side of the computed bipartition.
virtual T call(const Graph &G, const EdgeArray< T > &weights) override
Computes a minimum cut on graph G with non-negative weights on edges.
GraphCopy m_GC
The modifiable version of the input graph (used for contractions)
EdgeArray< T > m_w
An EdgeArray containing the corresponding edge weights.
ArrayBuffer< edge > m_cutEdges
Store cut edges if computed.
NodeArray< List< node > > m_contractedNodes
Each node has a list containing the nodes with which it has been contracted. Because the GraphCopy m_...
void mainLoop()
Computes minimum cut by invoking minimumCutPhase() O(|V|) times.
virtual const ArrayBuffer< node > & nodes() override
Returns a const-reference to the list of nodes belonging to one side of the bipartition.
T m_minCut
Stores the value of the minimum cut.
T minimumCutPhase()
Computes and returns the value of the minimum cut of the current phase (iteration).
virtual const ArrayBuffer< edge > & edges() override
Computes the edges defining the computed mincut and returns them.
virtual T value() const override
Returns the value of the last minimum cut computation.
virtual T call(const Graph &G) override
Computes a minimum cut on graph G.