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
37#include <memory>
38
39namespace ogdf {
40
48template<typename TCost>
49class MinSTCutMaxFlow : public MinSTCutModule<TCost> {
51
52public:
77
81 virtual bool call(const Graph& graph, const EdgeArray<TCost>& weight, node s, node t,
82 List<edge>& edgeList, edge e_st = nullptr) override;
83
87 virtual bool call(const Graph& graph, node s, node t, List<edge>& edgeList,
88 edge e_st = nullptr) override {
89 EdgeArray<TCost> weight(graph, 1);
90 return call(graph, weight, s, t, edgeList, e_st);
91 }
92
102 void call(const Graph& graph, const EdgeArray<TCost>& weights, const EdgeArray<TCost>& flow,
103 const node source, const node target);
104
108 enum class cutType {
109 FRONT_CUT,
110 BACK_CUT,
111 NO_CUT
112 };
113
118
129
138
142 bool isBackCutEdge(const edge e) const {
144 return m_nodeSet[e->target()] == cutType::BACK_CUT
146 }
147
152 bool isInFrontCut(const node v) const {
154 return m_nodeSet[v] == cutType::FRONT_CUT;
155 }
156
163 bool isInBackCut(const node v) const {
165 return m_nodeSet[v] == cutType::BACK_CUT;
166 }
167
179 bool isOfType(const node v, cutType type) const { return m_nodeSet[v] == type; }
180
181private:
183 std::unique_ptr<MaxFlowModule<TCost>> m_mfModule;
187 bool m_primaryCut = true;
194
195
196 std::unique_ptr<EpsilonTest> m_et;
203
211 void markCut(node startNode, bool frontCut, std::function<node(node)> origNode) {
213 queue.pushBack(startNode);
214 m_nodeSet[origNode(startNode)] = (frontCut ? cutType::FRONT_CUT : cutType::BACK_CUT);
216
217 while (!queue.empty()) {
218 const node v = queue.popFrontRet();
219 for (adjEntry adj : v->adjEntries) {
220 const node w = adj->twinNode();
221 const edge e = adj->theEdge();
222 if (m_nodeSet[origNode(w)] == cutType::NO_CUT
223 && (((frontCut ? e->source() : e->target()) == v
224 && m_et->less(m_flow[e], m_weight[e]))
225 || ((frontCut ? e->target() : e->source()) == v
226 && m_et->greater(m_flow[e], TCost(0))))) {
227 queue.pushBack(w);
230 }
231 }
232 }
233 }
234
245 void computeCut(const Graph& graph, std::function<edge(edge)> origEdge,
246 std::function<node(node)> origNode, const node source, const node target,
247 List<edge>& edgeList) {
248 m_frontCutCount = 0;
249 m_backCutCount = 0;
250 m_totalCount = graph.numberOfNodes();
251
252
255
257 // front cut
258 markCut(source, true, origNode);
259 }
260
262 // back cut
263 markCut(target, false, origNode);
264 }
265
267 EdgeArray<bool> visited(graph, false);
268 node startNode = (m_primaryCut ? source : target);
269 adjEntry startAdj = startNode->firstAdj();
270 if (startAdj == nullptr) {
271 return;
272 }
273 if (startAdj->theEdge()->adjTarget() != startAdj) {
274 stack.push(startAdj->theEdge());
275 }
276 for (adjEntry adj = (m_primaryCut ? startAdj->cyclicSucc() : startAdj->cyclicPred());
277 adj != startAdj; adj = (m_primaryCut ? adj->cyclicSucc() : adj->cyclicPred())) {
278 if (adj->theEdge()->adjTarget() != adj) {
279 stack.push(adj->theEdge());
280 }
281 }
282 while (!stack.empty()) {
283 edge e = stack.popRet();
284 if (visited[origEdge(e)]) {
285 continue;
286 }
287 visited[origEdge(e)] = true;
288 if (m_nodeSet[origNode(e->source())] == cutType::FRONT_CUT
289 && m_nodeSet[origNode(e->target())] != cutType::FRONT_CUT) {
290 edgeList.pushBack(origEdge(e));
291
292 if (m_gc->numberOfEdges() != 0) {
293 MinSTCutModule<TCost>::m_direction[origEdge(e)] = m_gc->copy(origEdge(e)) == e;
294 }
295 } else {
296 startAdj = e->adjTarget();
297 for (adjEntry adj = (m_primaryCut ? startAdj->cyclicSucc() : startAdj->cyclicPred());
298 adj != startAdj;
299 adj = (m_primaryCut ? adj->cyclicSucc() : adj->cyclicPred())) {
300 if (adj->theEdge()->adjTarget() != adj) {
301 stack.push(adj->theEdge());
302 }
303 }
304 }
305 }
306 }
307};
308
309template<typename TCost>
310bool MinSTCutMaxFlow<TCost>::call(const Graph& graph, const EdgeArray<TCost>& weight, node source,
311 node target, List<edge>& edgeList, edge e_st) {
313 delete m_gc;
314 m_gc = new GraphCopy(graph);
315
316 if (e_st != nullptr) {
317 m_gc->delEdge(m_gc->copy(e_st));
318 }
319 node s = m_gc->copy(source);
320 node t = m_gc->copy(target);
321 List<edge> edges;
322 m_gc->allEdges(edges);
323 EdgeArray<edge> originalEdge(*m_gc, nullptr);
324 for (edge e : edges) {
325 if (m_treatAsUndirected) {
326 // a reversed edge is made and placed directly next to e
327 edge revEdge = m_gc->newEdge(e->target(), e->source());
328 m_gc->move(revEdge, e->adjTarget(), ogdf::Direction::before, e->adjSource(),
330 originalEdge[revEdge] = m_gc->original(e);
331 }
332 originalEdge[e] = m_gc->original(e);
333 }
334
335 m_flow.init(*m_gc, -1);
336 m_weight.init(*m_gc, 1);
337 for (edge e : m_gc->edges) {
338 edge origEdge = originalEdge[e];
339 m_weight[e] = weight[origEdge];
340 OGDF_ASSERT(m_weight[e] >= 0);
341 }
342
343 m_mfModule->init(*m_gc);
344 m_mfModule->computeFlow(m_weight, s, t, m_flow);
345
346 computeCut(
347 graph, [&](edge e) -> edge { return originalEdge[e]; },
348 [&](node v) -> node { return m_gc->original(v); }, s, t, edgeList);
349
350 return true;
351}
352
353template<typename TCost>
355 const EdgeArray<TCost>& flow, const node source, const node target) {
356 delete m_gc;
357 m_gc = new GraphCopy();
358 m_flow = flow;
359 m_weight = weights;
360 List<edge> edgeList;
361 computeCut(
362 graph, [&](edge e) -> edge { return e; }, [&](node v) -> node { return v; }, source,
363 target, edgeList);
364}
365}
Declaration and implementation of Goldberg-Tarjan max-flow algorithm with global relabeling and gap r...
Template of base class of min-st-cut algorithms.
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
Dynamic arrays indexed with edges.
Definition EdgeArray.h:125
void init()
Reinitializes the array. Associates the array with no graph.
Definition EdgeArray.h:292
Class for the representation of edges.
Definition Graph_d.h:300
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition Graph_d.h:347
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
Copies of graphs supporting edge splitting.
Definition GraphCopy.h:254
node copy(node v) const
Returns the node in the graph copy corresponding to v.
Definition GraphCopy.h:338
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
int numberOfEdges() const
Returns the number of edges in the graph.
Definition Graph_d.h:625
Doubly linked lists (maintaining the length of the list).
Definition List.h:1435
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1531
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.
Dynamic arrays indexed with nodes.
Definition NodeArray.h:125
void init()
Reinitializes the array. Associates the array with no graph.
Definition NodeArray.h:266
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
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition Graph_d.h:223
NodeElement * node
The type of nodes.
Definition Graph_d.h:64
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()
The namespace for all OGDF objects.