Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

MinSTCutMaxFlow.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/ArrayBuffer.h>
35 #include <ogdf/basic/EpsilonTest.h>
36 #include <ogdf/basic/Graph.h>
37 #include <ogdf/basic/GraphCopy.h>
38 #include <ogdf/basic/GraphList.h>
39 #include <ogdf/basic/List.h>
40 #include <ogdf/basic/basic.h>
43 
44 #include <cstddef>
45 #include <functional>
46 #include <memory>
47 
48 namespace ogdf {
49 template<typename T>
50 class MaxFlowModule;
51 
59 template<typename TCost>
60 class MinSTCutMaxFlow : public MinSTCutModule<TCost> {
62 
63 public:
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 
139  }
140 
144  bool isFrontCutEdge(const edge e) const {
146  return m_nodeSet[e->source()] == cutType::FRONT_CUT
147  && m_nodeSet[e->target()] != cutType::FRONT_CUT;
148  }
149 
153  bool isBackCutEdge(const edge e) const {
155  return m_nodeSet[e->target()] == cutType::BACK_CUT
156  && m_nodeSet[e->source()] != 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 
192 private:
194  std::unique_ptr<MaxFlowModule<TCost>> m_mfModule;
196  bool m_treatAsUndirected = false;
198  bool m_primaryCut = true;
204  bool m_calculateOtherCut = 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 
320 template<typename TCost>
321 bool MinSTCutMaxFlow<TCost>::call(const Graph& graph, const EdgeArray<TCost>& weight, node source,
322  node target, List<edge>& edgeList, edge e_st) {
323  MinSTCutModule<TCost>::m_direction.init(graph, -1);
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 
364 template<typename TCost>
365 void 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 }
ogdf::ArrayBuffer
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition: Array.h:53
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ArrayBuffer.h
Declaration and implementation of ArrayBuffer class.
ogdf::MinSTCutMaxFlow::setEpsilonTest
void setEpsilonTest(EpsilonTest *et)
Assigns a new epsilon test.
Definition: MinSTCutMaxFlow.h:128
EpsilonTest.h
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Graph.h
Includes declaration of graph class.
ogdf::EpsilonTest
Definition: EpsilonTest.h:39
ogdf::MinSTCutMaxFlow::isFrontCutEdge
bool isFrontCutEdge(const edge e) const
Returns whether this edge is leaving the front cut.
Definition: MinSTCutMaxFlow.h:144
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::ArrayBuffer::empty
bool empty() const
Returns true if the buffer is empty, false otherwise.
Definition: ArrayBuffer.h:238
ogdf::MinSTCutMaxFlow::m_nodeSet
NodeArray< cutType > m_nodeSet
Definition: MinSTCutMaxFlow.h:208
ogdf::AdjElement::cyclicPred
adjEntry cyclicPred() const
Returns the cyclic predecessor in the adjacency list.
Definition: Graph_d.h:358
ogdf::List::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: List.h:1591
ogdf::MinSTCutMaxFlow::frontCutIsComplementOfBackCut
bool frontCutIsComplementOfBackCut() const
Returns whether the front cut is the complement of the backcut.
Definition: MinSTCutMaxFlow.h:136
ogdf::MinSTCutMaxFlow::m_et
std::unique_ptr< EpsilonTest > m_et
Definition: MinSTCutMaxFlow.h:207
ogdf::MinSTCutMaxFlow::isBackCutEdge
bool isBackCutEdge(const edge e) const
Returns whether this edge is entering the back cut.
Definition: MinSTCutMaxFlow.h:153
ogdf::GraphCopy
Copies of graphs supporting edge splitting.
Definition: GraphCopy.h:391
ogdf::MinSTCutMaxFlow::m_flow
EdgeArray< TCost > m_flow
Definition: MinSTCutMaxFlow.h:209
ogdf::Direction::before
@ before
ogdf::MaxFlowGoldbergTarjan
Computes a max flow via Preflow-Push (global relabeling and gap relabeling heuristic).
Definition: MaxFlowGoldbergTarjan.h:60
ogdf::MinSTCutMaxFlow::MinSTCutMaxFlow
MinSTCutMaxFlow(bool treatAsUndirected=true, MaxFlowModule< TCost > *mfModule=new MaxFlowGoldbergTarjan< TCost >(), bool primaryCut=true, bool calculateOtherCut=true, EpsilonTest *epsilonTest=new EpsilonTest())
Constructor.
Definition: MinSTCutMaxFlow.h:79
ogdf::ArrayBuffer::popRet
E popRet()
Removes the newest element from the buffer and returns it.
Definition: ArrayBuffer.h:232
ogdf::MinSTCutMaxFlow::computeCut
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.
Definition: MinSTCutMaxFlow.h:256
ogdf::MinSTCutMaxFlow::m_calculateOtherCut
bool m_calculateOtherCut
iff true, the other (near to s for primaryCut == false, near to t for primaryCut == true) cut should ...
Definition: MinSTCutMaxFlow.h:204
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::edge
EdgeElement * edge
The type of edges.
Definition: Graph_d.h:74
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
ogdf::MinSTCutMaxFlow::call
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.
Definition: MinSTCutMaxFlow.h:321
ogdf::Direction::after
@ after
ogdf::Graph::numberOfEdges
int numberOfEdges() const
Returns the number of edges in the graph.
Definition: Graph_d.h:985
MaxFlowGoldbergTarjan.h
Declaration and implementation of Goldberg-Tarjan max-flow algorithm with global relabeling and gap r...
ogdf::Graph::numberOfNodes
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition: Graph_d.h:982
backward::Color::type
type
Definition: backward.hpp:1716
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
ogdf::MinSTCutModule
Definition: MinSTCutModule.h:45
ogdf::MinSTCutMaxFlow::cutType::BACK_CUT
@ BACK_CUT
node is in back cut
ogdf::MinSTCutMaxFlow::m_primaryCut
bool m_primaryCut
true if the algorithm should search for the mincut nearest to s, false if it should be near to t.
Definition: MinSTCutMaxFlow.h:198
ogdf::ArrayBuffer::push
void push(E e)
Puts a new element in the buffer.
Definition: ArrayBuffer.h:217
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::node
NodeElement * node
The type of nodes.
Definition: Graph_d.h:70
GraphCopy.h
Declaration of graph copy classes.
ogdf::List< edge >
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:869
ogdf::MinSTCutMaxFlow::call
virtual bool call(const Graph &graph, node s, node t, List< edge > &edgeList, edge e_st=nullptr) override
The actual algorithm call.
Definition: MinSTCutMaxFlow.h:98
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::GraphCopy::copy
edge copy(edge e) const override
Returns the first edge in the list of edges corresponding to edge e.
Definition: GraphCopy.h:464
ogdf::AdjElement::cyclicSucc
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition: Graph_d.h:354
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:410
ogdf::MinSTCutMaxFlow::m_backCutCount
int m_backCutCount
Definition: MinSTCutMaxFlow.h:212
ogdf::MinSTCutMaxFlow::cutType::FRONT_CUT
@ FRONT_CUT
node is in front cut
ogdf::MinSTCutMaxFlow::cutType::NO_CUT
@ NO_CUT
node is not part of any cut
ogdf::MinSTCutModule::m_gc
GraphCopy * m_gc
Definition: MinSTCutModule.h:100
ogdf::MinSTCutMaxFlow::cutType
cutType
The three types of cuts.
Definition: MinSTCutMaxFlow.h:119
basic.h
Basic declarations, included by all source files.
ogdf::MinSTCutMaxFlow::m_totalCount
int m_totalCount
Definition: MinSTCutMaxFlow.h:213
ogdf::MinSTCutMaxFlow::isOfType
bool isOfType(const node v, cutType type) const
Return whether this node is of the specified type.
Definition: MinSTCutMaxFlow.h:190
ogdf::MaxFlowModule
Definition: MaxFlowModule.h:41
ogdf::NodeElement::firstAdj
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition: Graph_d.h:286
ogdf::MinSTCutMaxFlow::m_mfModule
std::unique_ptr< MaxFlowModule< TCost > > m_mfModule
the module used for calculating the maxflow
Definition: MinSTCutMaxFlow.h:194
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::MinSTCutMaxFlow::m_weight
EdgeArray< TCost > m_weight
Definition: MinSTCutMaxFlow.h:210
ogdf::MinSTCutMaxFlow::m_treatAsUndirected
bool m_treatAsUndirected
states whether or not edges are considered undirected while calculating the maxflow
Definition: MinSTCutMaxFlow.h:196
ogdf::MinSTCutMaxFlow::m_frontCutCount
int m_frontCutCount
Definition: MinSTCutMaxFlow.h:211
ogdf::RegisteredArray< GraphRegistry< EdgeElement >, Value, WithDefault, Graph >::init
void init(const Graph *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
Definition: RegisteredArray.h:858
ogdf::MinSTCutMaxFlow::markCut
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.
Definition: MinSTCutMaxFlow.h:222
ogdf::MinSTCutMaxFlow::isInBackCut
bool isInBackCut(const node v) const
Returns whether this node is part of the back cut.
Definition: MinSTCutMaxFlow.h:174
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
MinSTCutModule.h
Template of base class of min-st-cut algorithms.
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::MinSTCutMaxFlow
Min-st-cut algorithm, that calculates the cut via maxflow.
Definition: MinSTCutMaxFlow.h:60
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::MinSTCutMaxFlow::isInFrontCut
bool isInFrontCut(const node v) const
Returns whether this node is part of the front cut.
Definition: MinSTCutMaxFlow.h:163