COIN-OR::LEMON - Graph Library

Ticket #180: 180-cas4-08f7479bbc45.patch

File 180-cas4-08f7479bbc45.patch, 5.0 KB (added by Peter Kovacs, 10 years ago)
  • lemon/capacity_scaling.h

    # HG changeset patch
    # User Peter Kovacs <kpeter@inf.elte.hu>
    # Date 1252683113 -7200
    # Node ID 08f7479bbc4500fb408e916af3d5b019c42d1dfc
    # Parent  c9964582a1bd5c5b380a63612cf2cc41195901b3
    Handle negative costs in CapacityScaling (#180)
    
    This algorithm cannot handle arcs of negative cost and
    infinite upper bound, thus it returns UNBOUNDED if such
    an arc exists.
    
    diff --git a/lemon/capacity_scaling.h b/lemon/capacity_scaling.h
    a b  
    5555  ///
    5656  /// \warning Both value types must be signed and all input data must
    5757  /// be integer.
    58   /// \warning This implementation can handle only non-negative arc costs.
     58  /// \warning This algorithm does not support negative costs for such
     59  /// arcs that have infinite upper bound.
    5960  template <typename GR, typename V = int, typename C = V>
    6061  class CapacityScaling
    6162  {
     
    7980      /// bounded), and the algorithm has found optimal flow and node
    8081      /// potentials (primal and dual solutions).
    8182      OPTIMAL,
    82       /// The objective function of the problem is unbounded, i.e.
    83       /// there is a directed cycle having negative total cost and
    84       /// infinite upper bound.
     83      /// The digraph contains an arc of negative cost and infinite
     84      /// upper bound. It means that the objective function is unbounded
     85      /// on that arc, however note that it could actually be bounded
     86      /// over the feasible flows, but this algroithm cannot handle
     87      /// these cases.
    8588      UNBOUNDED
    8689    };
    8790 
     
    459462    /// \n \c OPTIMAL if the problem has optimal solution
    460463    /// (i.e. it is feasible and bounded), and the algorithm has found
    461464    /// optimal flow and node potentials (primal and dual solutions),
    462     /// \n \c UNBOUNDED if the objective function of the problem is
    463     /// unbounded, i.e. there is a directed cycle having negative total
    464     /// cost and infinite upper bound.
     465    /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
     466    /// and infinite upper bound. It means that the objective function
     467    /// is unbounded on that arc, however note that it could actually be
     468    /// bounded over the feasible flows, but this algroithm cannot handle
     469    /// these cases.
    465470    ///
    466471    /// \see ProblemType
    467472    ProblemType run(bool scaling = true) {
    468       if (!init(scaling)) return INFEASIBLE;
     473      ProblemType pt = init(scaling);
     474      if (pt != OPTIMAL) return pt;
    469475      return start();
    470476    }
    471477
     
    609615  private:
    610616
    611617    // Initialize the algorithm
    612     bool init(bool scaling) {
    613       if (_node_num == 0) return false;
     618    ProblemType init(bool scaling) {
     619      if (_node_num == 0) return INFEASIBLE;
    614620
    615621      // Check the sum of supply values
    616622      _sum_supply = 0;
    617623      for (int i = 0; i != _root; ++i) {
    618624        _sum_supply += _supply[i];
    619625      }
    620       if (_sum_supply > 0) return false;
     626      if (_sum_supply > 0) return INFEASIBLE;
    621627     
    622628      // Initialize maps
    623629      for (int i = 0; i != _root; ++i) {
     
    648654          _res_cap[j] = _forward[j] ? _upper[j] : 0;
    649655        }
    650656      }
     657
     658      // Handle negative costs
     659      for (int u = 0; u != _root; ++u) {
     660        for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
     661          Value rc = _res_cap[a];
     662          if (_cost[a] < 0 && rc > 0) {
     663            if (rc == INF) return UNBOUNDED;
     664            _excess[u] -= rc;
     665            _excess[_target[a]] += rc;
     666            _res_cap[a] = 0;
     667            _res_cap[_reverse[a]] += rc;
     668          }
     669        }
     670      }
    651671     
    652672      // Handle GEQ supply type
    653673      if (_sum_supply < 0) {
     
    696716        _delta = 1;
    697717      }
    698718
    699       return true;
     719      return OPTIMAL;
    700720    }
    701721
    702722    ProblemType start() {
  • test/min_cost_flow_test.cc

    diff --git a/test/min_cost_flow_test.cc b/test/min_cost_flow_test.cc
    a b  
    501501    mcf.supplyMap(s6);
    502502    checkMcf(mcf, mcf.run(),
    503503             gr, l2, u, c, s6, mcf.INFEASIBLE, false,  0, "#C15", GEQ);
     504
     505    // Check negative costs
     506    CapacityScaling<Digraph> neg_mcf(neg_gr);
     507    neg_mcf.lowerMap(neg_l1).costMap(neg_c).supplyMap(neg_s);
     508    checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u1,
     509      neg_c, neg_s, neg_mcf.UNBOUNDED, false,    0, "#C16");
     510    neg_mcf.upperMap(neg_u2);
     511    checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u2,
     512      neg_c, neg_s, neg_mcf.OPTIMAL, true,  -40000, "#C17");
     513    neg_mcf.reset().lowerMap(neg_l2).costMap(neg_c).supplyMap(neg_s);
     514    checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l2, neg_u1,
     515      neg_c, neg_s, neg_mcf.UNBOUNDED, false,    0, "#C18");
     516
     517    CapacityScaling<Digraph> negs_mcf(negs_gr);
     518    negs_mcf.costMap(negs_c).supplyMap(negs_s);
     519    checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u,
     520      negs_c, negs_s, negs_mcf.UNBOUNDED, false, 0, "#C19", GEQ);
     521    negs_mcf.upperMap(negs_u);
     522    checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u,
     523      negs_c, negs_s, negs_mcf.OPTIMAL, true, -300, "#C20", GEQ);
    504524  }
    505525
    506526  return 0;