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/Graph.h>
38#include <ogdf/basic/List.h>
39#include <ogdf/basic/Math.h>
41#include <ogdf/basic/basic.h>
43
44#include <functional>
45#include <limits>
46#include <utility>
47
48namespace ogdf {
49
58template<typename T = double>
61 virtual T call(const Graph& G) override {
62 EdgeArray<T> weights(G, 1);
63 return call(G, weights);
64 }
65
67 virtual T call(const Graph& G, const EdgeArray<T>& weights) override {
68 m_minCut = std::numeric_limits<T>::max();
69 m_GC.init(G);
70 m_w.init(m_GC);
72
73 for (edge e : m_GC.edges) {
74 m_w[e] = weights[m_GC.original(e)];
75 OGDF_ASSERT(m_w[e] >= T {});
76 }
77 for (node v : m_GC.nodes) {
78 m_contractedNodes[v].pushBack(m_GC.original(v));
79 }
80
81 mainLoop();
82
83 return value();
84 }
85
91 virtual const ArrayBuffer<edge>& edges() override {
92 if (!m_cutEdges.empty()) {
93 return m_cutEdges;
94 }
95
96 NodeArray<bool> inPartition(m_GC.original(), false);
97
98 for (node v : m_partition) {
99 inPartition[v] = true;
100 }
101
102 for (node v : m_partition) {
103 for (adjEntry adj : v->adjEntries) {
104 if (!inPartition[adj->twinNode()]) {
105 m_cutEdges.push(adj->theEdge());
106 }
107 }
108 }
109 return m_cutEdges;
110 }
111
113 virtual const ArrayBuffer<node>& nodes() override { return m_partition; }
114
115 virtual T value() const override { return m_minCut; }
116
117protected:
120
123
126
129
132
137
139 void mainLoop() {
140 m_partition.clear();
142 while (m_GC.numberOfNodes() > 1) {
144 if (m_minCut == T {}) { // cannot get better so return early
145 return;
146 }
147 }
148 }
149
151 T minimumCutPhase();
152
157 void contraction(node t, node s);
158};
159
160template<typename T>
162 OGDF_ASSERT(t != s);
163
164 // Since nodes in #m_GC correspond to sets of nodes (due to the node contraction),
165 // the NodeArray #m_contractedNodes has to be updated.
166 // Hence append the list of contracted nodes of s to the list of t.
167 m_contractedNodes[t].conc(m_contractedNodes(s));
168
169 // Redirect edges and delete node s
170 safeForEach(s->adjEntries, [&](adjEntry adj) {
171 edge e = adj->theEdge();
172 if (e->source() == t || e->target() == t) {
173 m_GC.delEdge(e);
174 } else if (e->source() == s) {
175 m_GC.moveSource(e, t);
176 } else {
177 m_GC.moveTarget(e, t);
178 }
179 });
180 m_GC.delNode(s);
181
182 // NodeArray containing the first edge of parallel edges
183 NodeArray<edge> incident {m_GC, nullptr};
184
185 // Delete parallel edges and add their weights
186 safeForEach(t->adjEntries, [&](adjEntry adj) {
187 node v {adj->twinNode()};
188 if (v != t) {
189 edge e {adj->theEdge()};
190 edge& f {incident[v]};
191 if (f == nullptr) {
192 f = e;
193 } else {
194 m_w[f] += m_w[e];
195 m_GC.delEdge(e);
196 }
197 }
198 });
199}
200
201template<typename T>
203 /*
204 * This function computes the mincut of the current phase.
205 * First, nodes are explored successively in descending order of the sum of
206 * their incident edge weights; \a s and \a t are always the two last added nodes.
207 * Afterwards, the current mincut value \a cutOfThePhase is computed, which corresponds to the
208 * sum of the weights of those edges incident to node \a t.
209 * At the end, \a s and \a t are contracted and the \a cutOfThePhase is returned.
210 */
211
212 // A priority queue containing the unexplored nodes.
213 // Priorities are the (negative) sum of edge weights incident to the explored nodes.
215 for (node v : m_GC.nodes) {
216 pq.push(v, T {});
217 }
218 std::function<void(node)> updatePQ {[&](node currentNode) {
219 OGDF_ASSERT(!pq.contains(currentNode));
220 for (adjEntry adj : currentNode->adjEntries) {
221 node v {adj->twinNode()};
222 // The code below is at it is due to numerical issues with T=double.
223 if (pq.contains(v)) {
224 T newPriority {pq.priority(v) - m_w[adj->theEdge()]};
225 if (newPriority < pq.priority(v)) {
226 pq.decrease(adj->twinNode(), newPriority);
227 }
228 }
229 }
230 }};
231
232 // The start node can be chosen arbitrarily. It has no effect on the correctness of the algorithm.
233 node s {nullptr};
234 node t {pq.topElement()};
235 pq.pop();
236
237 updatePQ(t);
238
239 // Successively adding the most tightly connected node.
240 while (!pq.empty()) {
241 // Find the most tightly connected node and remove it from the priority queue
242 node currentNode {pq.topElement()};
243 pq.pop();
244
245 // Push the current node to the 2-element list consisting of s and t
246 s = currentNode;
247 std::swap(s, t);
248
249 // Update the priorities
250 updatePQ(currentNode);
251 }
252
253 // Contains the mincut value according to the current phase.
254 T phaseCut {};
255 for (adjEntry adj : t->adjEntries) {
256 edge e {adj->theEdge()};
257 if (!e->isSelfLoop()) {
258 phaseCut += m_w[adj->theEdge()];
259 }
260 }
261
262 // If the current \a phaseCut is strictly smaller than the global mincut value,
263 // the partition defining the mincut has to be updated.
264 if (phaseCut < m_minCut) {
265 m_partition.clear();
266 for (node v : m_contractedNodes[t]) {
267 m_partition.push(v);
268 }
269 }
270
271 // Performing the node contraction of nodes \a s and \a t.
272 contraction(t, s);
273
274 return phaseCut;
275}
276
277}
Declaration and implementation of ArrayBuffer class.
Includes declaration of graph class.
Declaration of graph copy classes.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Declaration of ogdf::MinimumCutModule.
Priority queue interface wrapping various heaps.
Mathematical Helpers.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:64
void clear()
Clears the buffer.
void push(E e)
Puts a new element in the buffer.
bool empty() const
Returns true if the buffer is empty, false otherwise.
Class for the representation of edges.
Definition Graph_d.h:364
void init(const Graph &G)
Re-initializes the copy using G, creating copies for all nodes and edges in G.
Definition GraphCopy.h:72
const Graph & original() const
Returns a reference to the original graph.
Definition GraphCopy.h:104
Copies of graphs supporting edge splitting.
Definition GraphCopy.h:390
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition Graph_d.h:979
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition Graph_d.h:929
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition Graph_d.h:932
Serves as an interface for various methods to compute minimum cuts with or without edge weights.
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
Prioritized queue interface wrapper for heaps.
bool empty() const
Checks whether the queue is empty.
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
void decrease(const E &element, const P &priority)
Decreases the priority of the given element.
bool contains(const E &element) const
Returns whether this queue contains that key.
void pop()
Removes the topmost element from the queue.
void push(const E &element, const P &priority)
Adds a new element to the queue.
const P & priority(const E &element) const
const E & topElement() const
Returns the topmost element in the queue.
AdjElement * adjEntry
The type of adjacency entries.
Definition Graph_d.h:79
EdgeElement * edge
The type of edges.
Definition Graph_d.h:75
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
void updateMin(T &min, const T &newValue)
Stores the minimum of min and newValue in min.
Definition Math.h:102
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.