Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MinSTCutMaxFlow.h
Go to the documentation of this file.
1
32#pragma once
33
36#include <ogdf/basic/Graph.h>
39#include <ogdf/basic/List.h>
40#include <ogdf/basic/basic.h>
43
44#include <cstddef>
45#include <functional>
46#include <memory>
47
48namespace ogdf {
49template<typename T>
50class MaxFlowModule;
51
59template<typename TCost>
60class MinSTCutMaxFlow : public MinSTCutModule<TCost> {
61 using MinSTCutModule<TCost>::m_gc;
62
63public:
79 explicit MinSTCutMaxFlow(bool treatAsUndirected = true,
81 bool primaryCut = true, bool calculateOtherCut = true,
82 EpsilonTest* epsilonTest = new EpsilonTest())
83 : m_mfModule(mfModule)
84 , m_treatAsUndirected(treatAsUndirected)
85 , m_primaryCut(primaryCut)
86 , m_calculateOtherCut(calculateOtherCut)
87 , m_et(epsilonTest) { }
88
92 virtual bool call(const Graph& graph, const EdgeArray<TCost>& weight, node s, node t,
93 List<edge>& edgeList, edge e_st = nullptr) override;
94
98 virtual bool call(const Graph& graph, node s, node t, List<edge>& edgeList,
99 edge e_st = nullptr) override {
100 EdgeArray<TCost> weight(graph, 1);
101 return call(graph, weight, s, t, edgeList, e_st);
102 }
103
113 void call(const Graph& graph, const EdgeArray<TCost>& weights, const EdgeArray<TCost>& flow,
114 const node source, const node target);
115
119 enum class cutType {
120 FRONT_CUT,
121 BACK_CUT,
122 NO_CUT
123 };
124
128 void setEpsilonTest(EpsilonTest* et) { m_et.reset(et); }
129
140
149
153 bool isBackCutEdge(const edge e) const {
155 return m_nodeSet[e->target()] == cutType::BACK_CUT
157 }
158
163 bool isInFrontCut(const node v) const {
165 return m_nodeSet[v] == cutType::FRONT_CUT;
166 }
167
174 bool isInBackCut(const node v) const {
176 return m_nodeSet[v] == cutType::BACK_CUT;
177 }
178
190 bool isOfType(const node v, cutType type) const { return m_nodeSet[v] == type; }
191
192private:
194 std::unique_ptr<MaxFlowModule<TCost>> m_mfModule;
198 bool m_primaryCut = true;
205
206
207 std::unique_ptr<EpsilonTest> m_et;
214
222 void markCut(node startNode, bool frontCut, std::function<node(node)> origNode) {
223 List<node> queue;
224 queue.pushBack(startNode);
225 m_nodeSet[origNode(startNode)] = (frontCut ? cutType::FRONT_CUT : cutType::BACK_CUT);
226 frontCut ? m_frontCutCount++ : m_backCutCount++;
227
228 while (!queue.empty()) {
229 const node v = queue.popFrontRet();
230 for (adjEntry adj : v->adjEntries) {
231 const node w = adj->twinNode();
232 const edge e = adj->theEdge();
233 if (m_nodeSet[origNode(w)] == cutType::NO_CUT
234 && (((frontCut ? e->source() : e->target()) == v
235 && m_et->less(m_flow[e], m_weight[e]))
236 || ((frontCut ? e->target() : e->source()) == v
237 && m_et->greater(m_flow[e], TCost(0))))) {
238 queue.pushBack(w);
239 m_nodeSet[origNode(w)] = (frontCut ? cutType::FRONT_CUT : cutType::BACK_CUT);
240 frontCut ? m_frontCutCount++ : m_backCutCount++;
241 }
242 }
243 }
244 }
245
256 void computeCut(const Graph& graph, std::function<edge(edge)> origEdge,
257 std::function<node(node)> origNode, const node source, const node target,
258 List<edge>& edgeList) {
259 m_frontCutCount = 0;
260 m_backCutCount = 0;
261 m_totalCount = graph.numberOfNodes();
262
263
264 List<node> queue;
265 m_nodeSet.init(graph, cutType::NO_CUT);
266
268 // front cut
269 markCut(source, true, origNode);
270 }
271
273 // back cut
274 markCut(target, false, origNode);
275 }
276
278 EdgeArray<bool> visited(graph, false);
279 node startNode = (m_primaryCut ? source : target);
280 adjEntry startAdj = startNode->firstAdj();
281 if (startAdj == nullptr) {
282 return;
283 }
284 if (startAdj->theEdge()->adjTarget() != startAdj) {
285 stack.push(startAdj->theEdge());
286 }
287 for (adjEntry adj = (m_primaryCut ? startAdj->cyclicSucc() : startAdj->cyclicPred());
288 adj != startAdj; adj = (m_primaryCut ? adj->cyclicSucc() : adj->cyclicPred())) {
289 if (adj->theEdge()->adjTarget() != adj) {
290 stack.push(adj->theEdge());
291 }
292 }
293 while (!stack.empty()) {
294 edge e = stack.popRet();
295 if (visited[origEdge(e)]) {
296 continue;
297 }
298 visited[origEdge(e)] = true;
299 if (m_nodeSet[origNode(e->source())] == cutType::FRONT_CUT
300 && m_nodeSet[origNode(e->target())] != cutType::FRONT_CUT) {
301 edgeList.pushBack(origEdge(e));
302
303 if (m_gc->numberOfEdges() != 0) {
304 MinSTCutModule<TCost>::m_direction[origEdge(e)] = m_gc->copy(origEdge(e)) == e;
305 }
306 } else {
307 startAdj = e->adjTarget();
308 for (adjEntry adj = (m_primaryCut ? startAdj->cyclicSucc() : startAdj->cyclicPred());
309 adj != startAdj;
310 adj = (m_primaryCut ? adj->cyclicSucc() : adj->cyclicPred())) {
311 if (adj->theEdge()->adjTarget() != adj) {
312 stack.push(adj->theEdge());
313 }
314 }
315 }
316 }
317 }
318};
319
320template<typename TCost>
321bool MinSTCutMaxFlow<TCost>::call(const Graph& graph, const EdgeArray<TCost>& weight, node source,
322 node target, List<edge>& edgeList, edge e_st) {
324 delete m_gc;
325 m_gc = new GraphCopy(graph);
326
327 if (e_st != nullptr) {
328 m_gc->delEdge(m_gc->copy(e_st));
329 }
330 node s = m_gc->copy(source);
331 node t = m_gc->copy(target);
332 List<edge> edges;
333 m_gc->allEdges(edges);
334 EdgeArray<edge> originalEdge(*m_gc, nullptr);
335 for (edge e : edges) {
336 if (m_treatAsUndirected) {
337 // a reversed edge is made and placed directly next to e
338 edge revEdge = m_gc->newEdge(e->target(), e->source());
339 m_gc->move(revEdge, e->adjTarget(), ogdf::Direction::before, e->adjSource(),
341 originalEdge[revEdge] = m_gc->original(e);
342 }
343 originalEdge[e] = m_gc->original(e);
344 }
345
346 m_flow.init(*m_gc, -1);
347 m_weight.init(*m_gc, 1);
348 for (edge e : m_gc->edges) {
349 edge origEdge = originalEdge[e];
350 m_weight[e] = weight[origEdge];
351 OGDF_ASSERT(m_weight[e] >= 0);
352 }
353
354 m_mfModule->init(*m_gc);
355 m_mfModule->computeFlow(m_weight, s, t, m_flow);
356
357 computeCut(
358 graph, [&](edge e) -> edge { return originalEdge[e]; },
359 [&](node v) -> node { return m_gc->original(v); }, s, t, edgeList);
360
361 return true;
362}
363
364template<typename TCost>
365void MinSTCutMaxFlow<TCost>::call(const Graph& graph, const EdgeArray<TCost>& weights,
366 const EdgeArray<TCost>& flow, const node source, const node target) {
367 delete m_gc;
368 m_gc = new GraphCopy();
369 m_flow = flow;
370 m_weight = weights;
371 List<edge> edgeList;
372 computeCut(
373 graph, [&](edge e) -> edge { return e; }, [&](node v) -> node { return v; }, source,
374 target, edgeList);
375}
376}
Declaration and implementation of ArrayBuffer class.
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Includes declaration of graph class.
Declaration of graph copy classes.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Declaration and implementation of Goldberg-Tarjan max-flow algorithm with global relabeling and gap r...
Template of base class of min-st-cut algorithms.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition Graph_d.h:355
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition Graph_d.h:161
adjEntry cyclicPred() const
Returns the cyclic predecessor in the adjacency list.
Definition Graph_d.h:359
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:64
E popRet()
Removes the newest element from the buffer and returns it.
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
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition Graph_d.h:411
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
Copies of graphs supporting edge splitting.
Definition GraphCopy.h:390
edge copy(edge e) const override
Returns the first edge in the list of edges corresponding to edge e.
Definition GraphCopy.h:463
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
int numberOfEdges() const
Returns the number of edges in the graph.
Definition Graph_d.h:982
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1547
E popFrontRet()
Removes the first element from the list and returns it.
Definition List.h:1591
bool empty() const
Returns true iff the list is empty.
Definition List.h:286
Computes a max flow via Preflow-Push (global relabeling and gap relabeling heuristic).
Min-st-cut algorithm, that calculates the cut via maxflow.
void markCut(node startNode, bool frontCut, std::function< node(node)> origNode)
Mark the all nodes which are in the same cut partition as the startNode.
std::unique_ptr< MaxFlowModule< TCost > > m_mfModule
the module used for calculating the maxflow
bool isBackCutEdge(const edge e) const
Returns whether this edge is entering the back cut.
bool isInBackCut(const node v) const
Returns whether this node is part of the back cut.
EdgeArray< TCost > m_flow
std::unique_ptr< EpsilonTest > m_et
virtual bool call(const Graph &graph, node s, node t, List< edge > &edgeList, edge e_st=nullptr) override
The actual algorithm call.
cutType
The three types of cuts.
@ NO_CUT
node is not part of any cut
@ BACK_CUT
node is in back cut
@ FRONT_CUT
node is in front cut
EdgeArray< TCost > m_weight
bool isFrontCutEdge(const edge e) const
Returns whether this edge is leaving the front cut.
bool isOfType(const node v, cutType type) const
Return whether this node is of the specified type.
MinSTCutMaxFlow(bool treatAsUndirected=true, MaxFlowModule< TCost > *mfModule=new MaxFlowGoldbergTarjan< TCost >(), bool primaryCut=true, bool calculateOtherCut=true, EpsilonTest *epsilonTest=new EpsilonTest())
Constructor.
NodeArray< cutType > m_nodeSet
void computeCut(const Graph &graph, std::function< edge(edge)> origEdge, std::function< node(node)> origNode, const node source, const node target, List< edge > &edgeList)
Partitions the nodes to front and back cut.
void setEpsilonTest(EpsilonTest *et)
Assigns a new epsilon test.
bool m_treatAsUndirected
states whether or not edges are considered undirected while calculating the maxflow
virtual bool call(const Graph &graph, const EdgeArray< TCost > &weight, node s, node t, List< edge > &edgeList, edge e_st=nullptr) override
The actual algorithm call.
bool frontCutIsComplementOfBackCut() const
Returns whether the front cut is the complement of the backcut.
bool m_calculateOtherCut
iff true, the other (near to s for primaryCut == false, near to t for primaryCut == true) cut should ...
bool m_primaryCut
true if the algorithm should search for the mincut nearest to s, false if it should be near to t.
bool isInFrontCut(const node v) const
Returns whether this node is part of the front cut.
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
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition Graph_d.h:287
void init(const Base *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
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
NodeElement * node
The type of nodes.
Definition Graph_d.h:71
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
The namespace for all OGDF objects.