#ifndef OSRM_PARTITIONER_DINIC_MAX_FLOW_HPP_ #define OSRM_PARTITIONER_DINIC_MAX_FLOW_HPP_ #include "partitioner/bisection_graph_view.hpp" #include #include #include #include #include #include namespace osrm { namespace partitioner { class DinicMaxFlow { public: // maximal number of hops in the graph from source to sink using Level = std::uint32_t; using MinCut = struct { std::size_t num_nodes_source; std::size_t num_edges; std::vector flags; }; // input parameter storing the set o using SourceSinkNodes = std::unordered_set; MinCut operator()(const BisectionGraphView &view, const SourceSinkNodes &source_nodes, const SourceSinkNodes &sink_nodes) const; // validates the inpiut parameters to the flow algorithm (e.g. not intersecting) bool Validate(const BisectionGraphView &view, const SourceSinkNodes &source_nodes, const SourceSinkNodes &sink_nodes) const; private: // the level of each node in the graph (==hops in BFS from source) using LevelGraph = std::vector; // this is actually faster than using an unordered_set, stores all edges that have // capacity grouped by node using FlowEdges = std::vector>; // The level graph (see [1]) is based on a BFS computation. We assign a level to all nodes // (starting with 0 for all source nodes) and assign the hop distance in the residual graph as // the level of the node. // a // / \  // s t // \ / // b // would assign s = 0, a,b = 1, t=2 LevelGraph ComputeLevelGraph(const BisectionGraphView &view, const std::vector &border_source_nodes, const SourceSinkNodes &source_nodes, const SourceSinkNodes &sink_nodes, const FlowEdges &flow) const; // Using the above levels (see ComputeLevelGraph), we can use multiple DFS (that can now be // directed at the sink) to find a flow that completely blocks the level graph (i.e. no path // with increasing level exists from `s` to `t`). std::size_t BlockingFlow(FlowEdges &flow, LevelGraph &levels, const BisectionGraphView &view, const SourceSinkNodes &source_nodes, const std::vector &border_sink_nodes) const; // Finds a single augmenting path from a node to the sink side following levels in the level // graph. We don't actually remove the edges, so we have to check for increasing level values. // Since we know which sinks have been reached, we actually search for these paths starting at // sink nodes, instead of the source, so we can save a few dfs runs std::vector GetAugmentingPath(LevelGraph &levels, const NodeID from, const BisectionGraphView &view, const FlowEdges &flow, const SourceSinkNodes &source_nodes) const; // Builds an actual cut result from a level graph MinCut MakeCut(const BisectionGraphView &view, const LevelGraph &levels, const std::size_t flow_value) const; }; } // namespace partitioner } // namespace osrm // Implementation of Dinics [1] algorithm for max-flow/min-cut. // [1] https://www.cs.bgu.ac.il/~dinitz/D70.pdf #endif // OSRM_PARTITIONER_DINIC_MAX_FLOW_HPP_