Files
ortools-clone/ortools/graph/max_flow.h
Corentin Le Molgat c34026b101 Bump copyright to 2025
note: done using
```sh
git grep -l "2010-2024 Google" | xargs sed -i 's/2010-2024 Google/2010-2025 Google/'
```
2025-01-10 11:33:35 +01:00

141 lines
5.4 KiB
C++

// Copyright 2010-2025 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef OR_TOOLS_GRAPH_MAX_FLOW_H_
#define OR_TOOLS_GRAPH_MAX_FLOW_H_
#include <cstdint>
#include <memory>
#include <vector>
#include "ortools/graph/flow_problem.pb.h"
#include "ortools/graph/generic_max_flow.h"
#include "ortools/graph/graph.h"
namespace operations_research {
// A simple and efficient max-cost flow interface. This is as fast as
// GenericMaxFlow<ReverseArcStaticGraph>, which is the fastest, but uses
// more memory in order to hide the somewhat involved construction of the
// static graph.
//
// TODO(user): If the need arises, extend this interface to support warm start.
class SimpleMaxFlow {
public:
typedef int32_t NodeIndex;
typedef int32_t ArcIndex;
typedef int64_t FlowQuantity;
// The constructor takes no size.
// New node indices will be created lazily by AddArcWithCapacity().
SimpleMaxFlow();
#ifndef SWIG
// This type is neither copyable nor movable.
SimpleMaxFlow(const SimpleMaxFlow&) = delete;
SimpleMaxFlow& operator=(const SimpleMaxFlow&) = delete;
#endif
// Adds a directed arc with the given capacity from tail to head.
// * Node indices and capacity must be non-negative (>= 0).
// * Self-looping and duplicate arcs are supported.
// * After the method finishes, NumArcs() == the returned ArcIndex + 1.
ArcIndex AddArcWithCapacity(NodeIndex tail, NodeIndex head,
FlowQuantity capacity);
// Returns the current number of nodes. This is one more than the largest
// node index seen so far in AddArcWithCapacity().
NodeIndex NumNodes() const;
// Returns the current number of arcs in the graph.
ArcIndex NumArcs() const;
// Returns user-provided data.
// The implementation will crash if "arc" is not in [0, NumArcs()).
NodeIndex Tail(ArcIndex arc) const;
NodeIndex Head(ArcIndex arc) const;
FlowQuantity Capacity(ArcIndex arc) const;
// Solves the problem (finds the maximum flow from the given source to the
// given sink), and returns the problem status.
enum Status {
// Solve() was called and found an optimal solution. Note that OptimalFlow()
// may be 0 which means that the sink is not reachable from the source.
OPTIMAL,
// There is a flow > std::numeric_limits<FlowQuantity>::max(). Note that in
// this case, the class will contain a solution with a flow reaching that
// bound.
//
// TODO(user): rename POSSIBLE_OVERFLOW to INT_OVERFLOW and modify our
// clients.
POSSIBLE_OVERFLOW,
// The input is inconsistent (bad tail/head/capacity values).
BAD_INPUT,
// This should not happen. There was an error in our code (i.e. file a bug).
BAD_RESULT
};
Status Solve(NodeIndex source, NodeIndex sink);
// Returns the maximum flow we can send from the source to the sink in the
// last OPTIMAL Solve() context.
FlowQuantity OptimalFlow() const;
// Returns the flow on the given arc in the last OPTIMAL Solve() context.
//
// Note: It is possible that there is more than one optimal solution. The
// algorithm is deterministic so it will always return the same solution for
// a given problem. However, there is no guarantee of this from one code
// version to the next (but the code does not change often).
FlowQuantity Flow(ArcIndex arc) const;
// Returns the nodes reachable from the source by non-saturated arcs (.i.e.
// arc with Flow(arc) < Capacity(arc)), the outgoing arcs of this set form a
// minimum cut. This works only if Solve() returned OPTIMAL.
void GetSourceSideMinCut(std::vector<NodeIndex>* result);
// Returns the nodes that can reach the sink by non-saturated arcs, the
// outgoing arcs of this set form a minimum cut. Note that if this is the
// complement set of GetNodeReachableFromSource(), then the min-cut is unique.
// This works only if Solve() returned OPTIMAL.
void GetSinkSideMinCut(std::vector<NodeIndex>* result);
// Change the capacity of an arc.
//
// WARNING: This looks like it enables incremental solves, but as of 2018-02,
// the next Solve() will restart from scratch anyway.
// TODO(user): Support incrementality in the max flow implementation.
void SetArcCapacity(ArcIndex arc, FlowQuantity capacity);
// Creates the protocol buffer representation of the current problem.
FlowModelProto CreateFlowModelProto(NodeIndex source, NodeIndex sink) const;
private:
NodeIndex num_nodes_;
std::vector<NodeIndex> arc_tail_;
std::vector<NodeIndex> arc_head_;
std::vector<FlowQuantity> arc_capacity_;
std::vector<ArcIndex> arc_permutation_;
std::vector<FlowQuantity> arc_flow_;
FlowQuantity optimal_flow_;
// Note that we cannot free the graph before we stop using the max-flow
// instance that uses it.
typedef ::util::ReverseArcStaticGraph<NodeIndex, ArcIndex> Graph;
std::unique_ptr<Graph> underlying_graph_;
std::unique_ptr<GenericMaxFlow<Graph> > underlying_max_flow_;
};
} // namespace operations_research
#endif // OR_TOOLS_GRAPH_MAX_FLOW_H_