* This file is a part of LEMON, a generic C++ optimization library
* Copyright (C) 2003-2008
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
#ifndef LEMON_CANCEL_AND_TIGHTEN_H
#define LEMON_CANCEL_AND_TIGHTEN_H
/// \ingroup min_cost_flow
/// \brief Cancel and Tighten algorithm for finding a minimum cost flow.
#include <lemon/circulation.h>
#include <lemon/bellman_ford.h>
#include <lemon/howard.h>
#include <lemon/adaptors.h>
#include <lemon/tolerance.h>
#include <lemon/static_graph.h>
/// \addtogroup min_cost_flow
/// \brief Implementation of the Cancel and Tighten algorithm for
/// finding a minimum cost flow.
/// \ref CancelAndTighten implements the Cancel and Tighten algorithm for
/// finding a minimum cost flow.
/// \tparam Digraph The digraph type the algorithm runs on.
/// \tparam LowerMap The type of the lower bound map.
/// \tparam CapacityMap The type of the capacity (upper bound) map.
/// \tparam CostMap The type of the cost (length) map.
/// \tparam SupplyMap The type of the supply map.
/// - Arc capacities and costs should be \e non-negative \e integers.
/// - Supply values should be \e signed \e integers.
/// - The value types of the maps should be convertible to each other.
/// - \c CostMap::Value must be signed type.
template < typename Digraph,
typename LowerMap = typename Digraph::template ArcMap<int>,
typename CapacityMap = typename Digraph::template ArcMap<int>,
typename CostMap = typename Digraph::template ArcMap<int>,
typename SupplyMap = typename Digraph::template NodeMap<int> >
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
typedef typename CapacityMap::Value Capacity;
typedef typename CostMap::Value Cost;
typedef typename SupplyMap::Value Supply;
typedef typename Digraph::template ArcMap<Capacity> CapacityArcMap;
typedef typename Digraph::template NodeMap<Supply> SupplyNodeMap;
typedef ResidualDigraph< const Digraph,
CapacityArcMap, CapacityArcMap > ResDigraph;
/// The type of the flow map.
typedef typename Digraph::template ArcMap<Capacity> FlowMap;
/// The type of the potential map.
typedef typename Digraph::template NodeMap<Cost> PotentialMap;
/// \brief Map adaptor class for handling residual arc costs.
/// Map adaptor class for handling residual arc costs.
class ResidualCostMap : public MapBase<typename ResDigraph::Arc, Cost>
typedef typename ResDigraph::Arc Arc;
const CostMap &_cost_map;
ResidualCostMap(const CostMap &cost_map) : _cost_map(cost_map) {}
Cost operator[](const Arc &e) const {
return ResDigraph::forward(e) ? _cost_map[e] : -_cost_map[e];
}; //class ResidualCostMap
/// \brief Map adaptor class for handling reduced arc costs.
/// Map adaptor class for handling reduced arc costs.
class ReducedCostMap : public MapBase<Arc, Cost>
const CostMap &_cost_map;
const PotentialMap &_pot_map;
ReducedCostMap( const Digraph &gr,
const PotentialMap &pot_map ) :
_gr(gr), _cost_map(cost_map), _pot_map(pot_map) {}
inline Cost operator[](const Arc &e) const {
return _cost_map[e] + _pot_map[_gr.source(e)]
- _pot_map[_gr.target(e)];
}; //class ReducedCostMap
struct BFOperationTraits {
static double zero() { return 0; }
static double infinity() {
return std::numeric_limits<double>::infinity();
static double plus(const double& left, const double& right) {
static bool less(const double& left, const double& right) {
return left + 1e-6 < right;
}; // class BFOperationTraits
// The digraph the algorithm runs on
// The original lower bound map
// The modified capacity map
CapacityArcMap _capacity;
// The modified supply map
// Arc map of the current flow
// Node map of the current potentials
PotentialMap *_potential;
ResidualCostMap _res_cost;
/// \brief General constructor (with lower bounds).
/// General constructor (with lower bounds).
/// \param digraph The digraph the algorithm runs on.
/// \param lower The lower bounds of the arcs.
/// \param capacity The capacities (upper bounds) of the arcs.
/// \param cost The cost (length) values of the arcs.
/// \param supply The supply values of the nodes (signed).
CancelAndTighten( const Digraph &digraph,
const CapacityMap &capacity,
const SupplyMap &supply ) :
_graph(digraph), _lower(&lower), _capacity(digraph), _cost(cost),
_supply(digraph), _flow(NULL), _local_flow(false),
_potential(NULL), _local_potential(false),
_res_graph(NULL), _res_cost(_cost)
// Check the sum of supply values
for (NodeIt n(_graph); n != INVALID; ++n) {
_valid_supply = sum == 0;
// Remove non-zero lower bounds
for (ArcIt e(_graph); e != INVALID; ++e) {
_capacity[e] = capacity[e];
_capacity[e] -= lower[e];
_supply[_graph.source(e)] -= lower[e];
_supply[_graph.target(e)] += lower[e];
/// \brief General constructor (without lower bounds).
/// General constructor (without lower bounds).
/// \param digraph The digraph the algorithm runs on.
/// \param capacity The capacities (upper bounds) of the arcs.
/// \param cost The cost (length) values of the arcs.
/// \param supply The supply values of the nodes (signed).
CancelAndTighten( const Digraph &digraph,
const CapacityMap &capacity,
const SupplyMap &supply ) :
_graph(digraph), _lower(NULL), _capacity(capacity), _cost(cost),
_supply(supply), _flow(NULL), _local_flow(false),
_potential(NULL), _local_potential(false),
_res_graph(NULL), _res_cost(_cost)
// Check the sum of supply values
for (NodeIt n(_graph); n != INVALID; ++n) sum += _supply[n];
_valid_supply = sum == 0;
/// \brief Simple constructor (with lower bounds).
/// Simple constructor (with lower bounds).
/// \param digraph The digraph the algorithm runs on.
/// \param lower The lower bounds of the arcs.
/// \param capacity The capacities (upper bounds) of the arcs.
/// \param cost The cost (length) values of the arcs.
/// \param s The source node.
/// \param t The target node.
/// \param flow_value The required amount of flow from node \c s
/// to node \c t (i.e. the supply of \c s and the demand of \c t).
CancelAndTighten( const Digraph &digraph,
const CapacityMap &capacity,
_graph(digraph), _lower(&lower), _capacity(capacity), _cost(cost),
_supply(digraph, 0), _flow(NULL), _local_flow(false),
_potential(NULL), _local_potential(false),
_res_graph(NULL), _res_cost(_cost)
// Remove non-zero lower bounds
_supply[t] = -flow_value;
for (ArcIt e(_graph); e != INVALID; ++e) {
_capacity[e] -= lower[e];
_supply[_graph.source(e)] -= lower[e];
_supply[_graph.target(e)] += lower[e];
/// \brief Simple constructor (without lower bounds).
/// Simple constructor (without lower bounds).
/// \param digraph The digraph the algorithm runs on.
/// \param capacity The capacities (upper bounds) of the arcs.
/// \param cost The cost (length) values of the arcs.
/// \param s The source node.
/// \param t The target node.
/// \param flow_value The required amount of flow from node \c s
/// to node \c t (i.e. the supply of \c s and the demand of \c t).
CancelAndTighten( const Digraph &digraph,
const CapacityMap &capacity,
_graph(digraph), _lower(NULL), _capacity(capacity), _cost(cost),
_supply(digraph, 0), _flow(NULL), _local_flow(false),
_potential(NULL), _local_potential(false),
_res_graph(NULL), _res_cost(_cost)
_supply[t] = -flow_value;
if (_local_flow) delete _flow;
if (_local_potential) delete _potential;
/// \brief Set the flow map.
CancelAndTighten& flowMap(FlowMap &map) {
/// \brief Set the potential map.
/// Set the potential map.
CancelAndTighten& potentialMap(PotentialMap &map) {
_local_potential = false;
/// \name Execution control
/// \brief Run the algorithm.
/// \return \c true if a feasible flow can be found.
return init() && start();
/// \name Query Functions
/// The result of the algorithm can be obtained using these
/// \ref lemon::CancelAndTighten::run() "run()" must be called before
/// \brief Return a const reference to the arc map storing the
/// Return a const reference to the arc map storing the found flow.
/// \pre \ref run() must be called before using this function.
const FlowMap& flowMap() const {
/// \brief Return a const reference to the node map storing the
/// found potentials (the dual solution).
/// Return a const reference to the node map storing the found
/// potentials (the dual solution).
/// \pre \ref run() must be called before using this function.
const PotentialMap& potentialMap() const {
/// \brief Return the flow on the given arc.
/// Return the flow on the given arc.
/// \pre \ref run() must be called before using this function.
Capacity flow(const Arc& arc) const {
/// \brief Return the potential of the given node.
/// Return the potential of the given node.
/// \pre \ref run() must be called before using this function.
Cost potential(const Node& node) const {
return (*_potential)[node];
/// \brief Return the total cost of the found flow.
/// Return the total cost of the found flow. The complexity of the
/// function is \f$ O(e) \f$.
/// \pre \ref run() must be called before using this function.
for (ArcIt e(_graph); e != INVALID; ++e)
c += (*_flow)[e] * _cost[e];
/// Initialize the algorithm.
if (!_valid_supply) return false;
// Initialize flow and potential maps
_flow = new FlowMap(_graph);
_potential = new PotentialMap(_graph);
_res_graph = new ResDigraph(_graph, _capacity, *_flow);
// Find a feasible flow using Circulation
Circulation< Digraph, ConstMap<Arc, Capacity>,
CapacityArcMap, SupplyMap >
circulation( _graph, constMap<Arc>(Capacity(0)),
return circulation.flowMap(*_flow).run();
const double LIMIT_FACTOR = 0.01;
typedef typename Digraph::template NodeMap<double> FloatPotentialMap;
typedef typename Digraph::template NodeMap<int> LevelMap;
typedef typename Digraph::template NodeMap<bool> BoolNodeMap;
typedef typename Digraph::template NodeMap<Node> PredNodeMap;
typedef typename Digraph::template NodeMap<Arc> PredArcMap;
typedef typename ResDigraph::template ArcMap<double> ResShiftCostMap;
FloatPotentialMap pi(_graph);
BoolNodeMap reached(_graph);
BoolNodeMap processed(_graph);
PredNodeMap pred_node(_graph);
PredArcMap pred_arc(_graph);
int node_num = countNodes(_graph);
typedef std::pair<Arc, bool> pair;
std::vector<pair> stack(node_num);
std::vector<Node> proc_vector(node_num);
ResShiftCostMap shift_cost(*_res_graph);
// Initialize epsilon and the node potentials
for (ArcIt e(_graph); e != INVALID; ++e) {
if (_capacity[e] - (*_flow)[e] > 0 && _cost[e] < -epsilon)
else if ((*_flow)[e] > 0 && _cost[e] > epsilon)
for (NodeIt v(_graph); v != INVALID; ++v) {
int limit = int(LIMIT_FACTOR * node_num);
if (limit < MIN_LIMIT) limit = MIN_LIMIT;
while (epsilon * node_num >= 1) {
// Find and cancel cycles in the admissible digraph using DFS
for (NodeIt n(_graph); n != INVALID; ++n) {
for (NodeIt start(_graph); start != INVALID; ++start) {
if (reached[start]) continue;
pred_arc[start] = INVALID;
pred_node[start] = INVALID;
// Find the first admissible residual outgoing arc
_graph.firstOut(e, start);
while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 ||
!tol.negative(_cost[e] + p - pi[_graph.target(e)])) )
stack[++stack_head] = pair(e, true);
_graph.firstIn(e, start);
while ( e != INVALID && ((*_flow)[e] == 0 ||
!tol.negative(-_cost[e] + p - pi[_graph.source(e)])) )
stack[++stack_head] = pair(e, false);
proc_vector[++proc_head] = start;
while (stack_head >= 0) {
Arc se = stack[stack_head].first;
bool sf = stack[stack_head].second;
// Find the first admissible residual outgoing arc
while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 ||
!tol.negative(_cost[e] + p - pi[_graph.target(e)])) )
stack[++stack_head] = pair(e, true);
while ( e != INVALID && ((*_flow)[e] == 0 ||
!tol.negative(-_cost[e] + p - pi[_graph.source(e)])) )
stack[++stack_head] = pair(e, false);
Capacity d, delta = sf ? _capacity[se] - (*_flow)[se] :
for (n = u; n != v; n = pred_node[n]) {
d = _graph.target(pred_arc[n]) == n ?
_capacity[pred_arc[n]] - (*_flow)[pred_arc[n]] :
std::cout << "CYCLE FOUND: ";
std::cout << _cost[se] + pi[_graph.source(se)] - pi[_graph.target(se)];
std::cout << _graph.id(se) << ":" << -(_cost[se] + pi[_graph.source(se)] - pi[_graph.target(se)]);
for (n = u; n != v; n = pred_node[n]) {
if (_graph.target(pred_arc[n]) == n)
std::cout << " " << _cost[pred_arc[n]] + pi[_graph.source(pred_arc[n])] - pi[_graph.target(pred_arc[n])];
std::cout << " " << -(_cost[pred_arc[n]] + pi[_graph.source(pred_arc[n])] - pi[_graph.target(pred_arc[n])]);
// Augment along the cycle
(*_flow)[se] = sf ? (*_flow)[se] + delta :
for (n = u; n != v; n = pred_node[n]) {
if (_graph.target(pred_arc[n]) == n)
(*_flow)[pred_arc[n]] += delta;
(*_flow)[pred_arc[n]] -= delta;
for (n = u; stack_head > 0 && n != w; n = pred_node[n]) {
// Find the next admissible residual outgoing arc
Arc e = stack[stack_head].first;
if (!stack[stack_head].second) {
while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 ||
!tol.negative(_cost[e] + p - pi[_graph.target(e)])) )
stack[stack_head] = pair(e, true);
while ( e != INVALID && ((*_flow)[e] == 0 ||
!tol.negative(-_cost[e] + p - pi[_graph.source(e)])) )
stack[stack_head] = pair(e, false);
while (stack_head >= 0 && stack[stack_head].first == INVALID) {
proc_vector[++proc_head] = v;
v = stack[stack_head].second ?
_graph.source(stack[stack_head].first) :
_graph.target(stack[stack_head].first);
// Find the next admissible residual outgoing arc
Arc e = stack[stack_head].first;
if (!stack[stack_head].second) {
while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 ||
!tol.negative(_cost[e] + p - pi[_graph.target(e)])) )
stack[stack_head] = pair(e, true);
while ( e != INVALID && ((*_flow)[e] == 0 ||
!tol.negative(-_cost[e] + p - pi[_graph.source(e)])) )
stack[stack_head] = pair(e, false);
// Tighten potentials and epsilon
for (int i = proc_head; i >= 0; --i) {
for (InArcIt e(_graph, v); e != INVALID; ++e) {
Node u = _graph.source(e);
if ( _capacity[e] - (*_flow)[e] > 0 &&
tol.negative(_cost[e] + pi[u] - p) &&
level[u] + 1 > l ) l = level[u] + 1;
for (OutArcIt e(_graph, v); e != INVALID; ++e) {
Node u = _graph.target(e);
tol.negative(-_cost[e] + pi[u] - p) &&
level[u] + 1 > l ) l = level[u] + 1;
for (ArcIt e(_graph); e != INVALID; ++e) {
Node u = _graph.source(e);
Node v = _graph.target(e);
if (_capacity[e] - (*_flow)[e] > 0 && level[u] - level[v] > 0) {
p = (_cost[e] + pi[u] - pi[v] + epsilon) /
(level[u] - level[v] + 1);
if (q < 0 || p < q) q = p;
else if ((*_flow)[e] > 0 && level[v] - level[u] > 0) {
p = (-_cost[e] - pi[u] + pi[v] + epsilon) /
(level[v] - level[u] + 1);
if (q < 0 || p < q) q = p;
for (NodeIt v(_graph); v != INVALID; ++v) {
for (ArcIt e(_graph); e != INVALID; ++e) {
double curr = _cost[e] + pi[_graph.source(e)]
if (_capacity[e] - (*_flow)[e] > 0 && curr < -epsilon)
else if ((*_flow)[e] > 0 && curr > epsilon)
// Set epsilon to the minimum cycle mean
StaticDigraph static_graph;
typename ResDigraph::template NodeMap<typename StaticDigraph::Node> node_ref(*_res_graph);
typename ResDigraph::template ArcMap<typename StaticDigraph::Arc> arc_ref(*_res_graph);
static_graph.build(*_res_graph, node_ref, arc_ref);
typename StaticDigraph::template NodeMap<double> static_pi(static_graph);
typename StaticDigraph::template ArcMap<double> static_cost(static_graph);
for (typename ResDigraph::ArcIt e(*_res_graph); e != INVALID; ++e)
static_cost[arc_ref[e]] = _res_cost[e];
Howard<StaticDigraph, typename StaticDigraph::template ArcMap<double> >
mmc(static_graph, static_cost);
epsilon = -mmc.cycleMean();
Howard<ResDigraph, ResidualCostMap> mmc(*_res_graph, _res_cost);
epsilon = -mmc.cycleMean();
// Compute feasible potentials for the current epsilon
for (typename StaticDigraph::ArcIt e(static_graph); e != INVALID; ++e)
static_cost[e] += epsilon;
typename BellmanFord<StaticDigraph, typename StaticDigraph::template ArcMap<double> >::
template SetDistMap<typename StaticDigraph::template NodeMap<double> >::
template SetOperationTraits<BFOperationTraits>::Create
bf(static_graph, static_cost);
bf.distMap(static_pi).init(0);
for (NodeIt n(_graph); n != INVALID; ++n)
pi[n] = static_pi[node_ref[n]];
for (typename ResDigraph::ArcIt e(*_res_graph); e != INVALID; ++e)
shift_cost[e] = _res_cost[e] + epsilon;
typename BellmanFord<ResDigraph, ResShiftCostMap>::
template SetDistMap<FloatPotentialMap>::
template SetOperationTraits<BFOperationTraits>::Create
bf(*_res_graph, shift_cost);
// std::cout << t1.realTime() << " " << t2.realTime() << " " << t3.realTime() << "\n";
// Handle non-zero lower bounds
for (ArcIt e(_graph); e != INVALID; ++e)
(*_flow)[e] += (*_lower)[e];
}; //class CancelAndTighten
#endif //LEMON_CANCEL_AND_TIGHTEN_H