COIN-OR::LEMON - Graph Library

Ticket #266: suurballe-1a9b60b22a8d.patch

File suurballe-1a9b60b22a8d.patch, 21.9 KB (added by Peter Kovacs, 15 years ago)
  • lemon/suurballe.h

    # HG changeset patch
    # User Peter Kovacs <kpeter@inf.elte.hu>
    # Date 1240618361 -7200
    # Node ID 1a9b60b22a8d6c051cf64b01e5ed028bc4e47386
    # Parent  b95898314e095d3b9f994b1a1068518f25016745
    Modify the interface of Suurballe (#266, #181)
    
     - Move the parameters s and t from the constructor to the run()
       function. It makes the interface capable for multiple run(s,t,k)
       calls (possible improvement in the future) and it is more similar
       to Dijkstra.
     - Simliarly init() and findFlow(k) were replaced by init(s) and
       findFlow(t,k). The separation of parameters s and t is for the
       future plans of supporting multiple targets with one source node.
       For more information see #181.
     - LEMON_ASSERT for the Length type (check if it is integer).
     - Doc improvements.
     - Rearrange query functions.
     - Extend test file.
    
    diff --git a/lemon/suurballe.h b/lemon/suurballe.h
    a b  
    4242  /// finding arc-disjoint paths having minimum total length (cost)
    4343  /// from a given source node to a given target node in a digraph.
    4444  ///
    45   /// In fact, this implementation is the specialization of the
    46   /// \ref CapacityScaling "successive shortest path" algorithm.
     45  /// Note that this problem is a special case of the \ref min_cost_flow
     46  /// "minimum cost flow problem". This implementation is actually an
     47  /// efficient specialized version of the \ref CapacityScaling
     48  /// "Successive Shortest Path" algorithm directly for this problem.
     49  /// Therefore this class provides query functions for flow values and
     50  /// node potentials (the dual solution) just like the minimum cost flow
     51  /// algorithms.
    4752  ///
    4853  /// \tparam GR The digraph type the algorithm runs on.
    49   /// The default value is \c ListDigraph.
    50   /// \tparam LEN The type of the length (cost) map.
    51   /// The default value is <tt>Digraph::ArcMap<int></tt>.
     54  /// \tparam LEN The type of the length map.
     55  /// The default value is <tt>GR::ArcMap<int></tt>.
    5256  ///
    5357  /// \warning Length values should be \e non-negative \e integers.
    5458  ///
    5559  /// \note For finding node-disjoint paths this algorithm can be used
    56   /// with \ref SplitNodes.
     60  /// along with the \ref SplitNodes adaptor.
    5761#ifdef DOXYGEN
    5862  template <typename GR, typename LEN>
    5963#else
    60   template < typename GR = ListDigraph,
     64  template < typename GR,
    6165             typename LEN = typename GR::template ArcMap<int> >
    6266#endif
    6367  class Suurballe
     
    7579    typedef LEN LengthMap;
    7680    /// The type of the lengths.
    7781    typedef typename LengthMap::Value Length;
     82#ifdef DOXYGEN
     83    /// The type of the flow map.
     84    typedef GR::ArcMap<int> FlowMap;
     85    /// The type of the potential map.
     86    typedef GR::NodeMap<Length> PotentialMap;
     87#else
    7888    /// The type of the flow map.
    7989    typedef typename Digraph::template ArcMap<int> FlowMap;
    8090    /// The type of the potential map.
    8191    typedef typename Digraph::template NodeMap<Length> PotentialMap;
     92#endif
     93
    8294    /// The type of the path structures.
    83     typedef SimplePath<Digraph> Path;
     95    typedef SimplePath<GR> Path;
    8496
    8597  private:
    8698
    87     /// \brief Special implementation of the Dijkstra algorithm
    88     /// for finding shortest paths in the residual network.
    89     ///
    90     /// \ref ResidualDijkstra is a special implementation of the
    91     /// \ref Dijkstra algorithm for finding shortest paths in the
    92     /// residual network of the digraph with respect to the reduced arc
    93     /// lengths and modifying the node potentials according to the
    94     /// distance of the nodes.
     99    // ResidualDijkstra is a special implementation of the
     100    // Dijkstra algorithm for finding shortest paths in the
     101    // residual network with respect to the reduced arc lengths
     102    // and modifying the node potentials according to the
     103    // distance of the nodes.
    95104    class ResidualDijkstra
    96105    {
    97106      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
     
    120129    public:
    121130
    122131      /// Constructor.
    123       ResidualDijkstra( const Digraph &digraph,
     132      ResidualDijkstra( const Digraph &graph,
    124133                        const FlowMap &flow,
    125134                        const LengthMap &length,
    126135                        PotentialMap &potential,
    127136                        PredMap &pred,
    128137                        Node s, Node t ) :
    129         _graph(digraph), _flow(flow), _length(length), _potential(potential),
    130         _dist(digraph), _pred(pred), _s(s), _t(t) {}
     138        _graph(graph), _flow(flow), _length(length), _potential(potential),
     139        _dist(graph), _pred(pred), _s(s), _t(t) {}
    131140
    132141      /// \brief Run the algorithm. It returns \c true if a path is found
    133142      /// from the source node to the target node.
     
    236245    ///
    237246    /// Constructor.
    238247    ///
    239     /// \param digraph The digraph the algorithm runs on.
     248    /// \param graph The digraph the algorithm runs on.
    240249    /// \param length The length (cost) values of the arcs.
    241     /// \param s The source node.
    242     /// \param t The target node.
    243     Suurballe( const Digraph &digraph,
    244                const LengthMap &length,
    245                Node s, Node t ) :
    246       _graph(digraph), _length(length), _flow(0), _local_flow(false),
    247       _potential(0), _local_potential(false), _source(s), _target(t),
    248       _pred(digraph) {}
     250    Suurballe( const Digraph &graph,
     251               const LengthMap &length ) :
     252      _graph(graph), _length(length), _flow(0), _local_flow(false),
     253      _potential(0), _local_potential(false), _pred(graph)
     254    {
     255      LEMON_ASSERT(std::numeric_limits<Length>::is_integer,
     256        "The length type of Suurballe must be integer");
     257    }
    249258
    250259    /// Destructor.
    251260    ~Suurballe() {
     
    257266    /// \brief Set the flow map.
    258267    ///
    259268    /// This function sets the flow map.
     269    /// If it is not used before calling \ref run() or \ref init(),
     270    /// an instance will be allocated automatically. The destructor
     271    /// deallocates this automatically allocated map, of course.
    260272    ///
    261     /// The found flow contains only 0 and 1 values. It is the union of
    262     /// the found arc-disjoint paths.
     273    /// The found flow contains only 0 and 1 values, since it is the
     274    /// union of the found arc-disjoint paths.
    263275    ///
    264276    /// \return <tt>(*this)</tt>
    265277    Suurballe& flowMap(FlowMap &map) {
     
    274286    /// \brief Set the potential map.
    275287    ///
    276288    /// This function sets the potential map.
     289    /// If it is not used before calling \ref run() or \ref init(),
     290    /// an instance will be allocated automatically. The destructor
     291    /// deallocates this automatically allocated map, of course.
    277292    ///
    278     /// The potentials provide the dual solution of the underlying
    279     /// minimum cost flow problem.
     293    /// The node potentials provide the dual solution of the underlying
     294    /// \ref min_cost_flow "minimum cost flow problem".
    280295    ///
    281296    /// \return <tt>(*this)</tt>
    282297    Suurballe& potentialMap(PotentialMap &map) {
     
    301316    ///
    302317    /// This function runs the algorithm.
    303318    ///
     319    /// \param s The source node.
     320    /// \param t The target node.
    304321    /// \param k The number of paths to be found.
    305322    ///
    306323    /// \return \c k if there are at least \c k arc-disjoint paths from
    307324    /// \c s to \c t in the digraph. Otherwise it returns the number of
    308325    /// arc-disjoint paths found.
    309326    ///
    310     /// \note Apart from the return value, <tt>s.run(k)</tt> is just a
    311     /// shortcut of the following code.
     327    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
     328    /// just a shortcut of the following code.
    312329    /// \code
    313     ///   s.init();
    314     ///   s.findFlow(k);
     330    ///   s.init(s);
     331    ///   s.findFlow(t, k);
    315332    ///   s.findPaths();
    316333    /// \endcode
    317     int run(int k = 2) {
    318       init();
    319       findFlow(k);
     334    int run(const Node& s, const Node& t, int k = 2) {
     335      init(s);
     336      findFlow(t, k);
    320337      findPaths();
    321338      return _path_num;
    322339    }
     
    324341    /// \brief Initialize the algorithm.
    325342    ///
    326343    /// This function initializes the algorithm.
    327     void init() {
     344    ///
     345    /// \param s The source node.
     346    void init(const Node& s) {
     347      _source = s;
     348
    328349      // Initialize maps
    329350      if (!_flow) {
    330351        _flow = new FlowMap(_graph);
     
    336357      }
    337358      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
    338359      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
    339 
    340       _dijkstra = new ResidualDijkstra( _graph, *_flow, _length,
    341                                         *_potential, _pred,
    342                                         _source, _target );
    343360    }
    344361
    345     /// \brief Execute the successive shortest path algorithm to find
    346     /// an optimal flow.
     362    /// \brief Execute the algorithm to find an optimal flow.
    347363    ///
    348364    /// This function executes the successive shortest path algorithm to
    349     /// find a minimum cost flow, which is the union of \c k or less
     365    /// find a minimum cost flow, which is the union of \c k (or less)
    350366    /// arc-disjoint paths.
    351367    ///
     368    /// \param t The target node.
     369    /// \param k The number of paths to be found.
     370    ///
    352371    /// \return \c k if there are at least \c k arc-disjoint paths from
    353     /// \c s to \c t in the digraph. Otherwise it returns the number of
    354     /// arc-disjoint paths found.
     372    /// the source node to the given node \c t in the digraph.
     373    /// Otherwise it returns the number of arc-disjoint paths found.
    355374    ///
    356375    /// \pre \ref init() must be called before using this function.
    357     int findFlow(int k = 2) {
     376    int findFlow(const Node& t, int k = 2) {
     377      _target = t;
     378      _dijkstra =
     379        new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
     380                              _source, _target );
     381
    358382      // Find shortest paths
    359383      _path_num = 0;
    360384      while (_path_num < k) {
     
    380404
    381405    /// \brief Compute the paths from the flow.
    382406    ///
    383     /// This function computes the paths from the flow.
     407    /// This function computes the paths from the found minimum cost flow,
     408    /// which is the union of some arc-disjoint paths.
    384409    ///
    385410    /// \pre \ref init() and \ref findFlow() must be called before using
    386411    /// this function.
    387412    void findPaths() {
    388       // Create the residual flow map (the union of the paths not found
    389       // so far)
    390413      FlowMap res_flow(_graph);
    391414      for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
    392415
     
    413436
    414437    /// @{
    415438
    416     /// \brief Return a const reference to the arc map storing the
     439    /// \brief Return the total length of the found paths.
     440    ///
     441    /// This function returns the total length of the found paths, i.e.
     442    /// the total cost of the found flow.
     443    /// The complexity of the function is O(e).
     444    ///
     445    /// \pre \ref run() or \ref findFlow() must be called before using
     446    /// this function.
     447    Length totalLength() const {
     448      Length c = 0;
     449      for (ArcIt e(_graph); e != INVALID; ++e)
     450        c += (*_flow)[e] * _length[e];
     451      return c;
     452    }
     453
     454    /// \brief Return the flow value on the given arc.
     455    ///
     456    /// This function returns the flow value on the given arc.
     457    /// It is \c 1 if the arc is involved in one of the found arc-disjoint
     458    /// paths, otherwise it is \c 0.
     459    ///
     460    /// \pre \ref run() or \ref findFlow() must be called before using
     461    /// this function.
     462    int flow(const Arc& arc) const {
     463      return (*_flow)[arc];
     464    }
     465
     466    /// \brief Return a const reference to an arc map storing the
    417467    /// found flow.
    418468    ///
    419     /// This function returns a const reference to the arc map storing
     469    /// This function returns a const reference to an arc map storing
    420470    /// the flow that is the union of the found arc-disjoint paths.
    421471    ///
    422472    /// \pre \ref run() or \ref findFlow() must be called before using
     
    425475      return *_flow;
    426476    }
    427477
    428     /// \brief Return a const reference to the node map storing the
    429     /// found potentials (the dual solution).
    430     ///
    431     /// This function returns a const reference to the node map storing
    432     /// the found potentials that provide the dual solution of the
    433     /// underlying minimum cost flow problem.
    434     ///
    435     /// \pre \ref run() or \ref findFlow() must be called before using
    436     /// this function.
    437     const PotentialMap& potentialMap() const {
    438       return *_potential;
    439     }
    440 
    441     /// \brief Return the flow on the given arc.
    442     ///
    443     /// This function returns the flow on the given arc.
    444     /// It is \c 1 if the arc is involved in one of the found paths,
    445     /// otherwise it is \c 0.
    446     ///
    447     /// \pre \ref run() or \ref findFlow() must be called before using
    448     /// this function.
    449     int flow(const Arc& arc) const {
    450       return (*_flow)[arc];
    451     }
    452 
    453478    /// \brief Return the potential of the given node.
    454479    ///
    455480    /// This function returns the potential of the given node.
     481    /// The node potentials provide the dual solution of the
     482    /// underlying \ref min_cost_flow "minimum cost flow problem".
    456483    ///
    457484    /// \pre \ref run() or \ref findFlow() must be called before using
    458485    /// this function.
     
    460487      return (*_potential)[node];
    461488    }
    462489
    463     /// \brief Return the total length (cost) of the found paths (flow).
     490    /// \brief Return a const reference to a node map storing the
     491    /// found potentials (the dual solution).
    464492    ///
    465     /// This function returns the total length (cost) of the found paths
    466     /// (flow). The complexity of the function is O(e).
     493    /// This function returns a const reference to a node map storing
     494    /// the found potentials that provide the dual solution of the
     495    /// underlying \ref min_cost_flow "minimum cost flow problem".
    467496    ///
    468497    /// \pre \ref run() or \ref findFlow() must be called before using
    469498    /// this function.
    470     Length totalLength() const {
    471       Length c = 0;
    472       for (ArcIt e(_graph); e != INVALID; ++e)
    473         c += (*_flow)[e] * _length[e];
    474       return c;
     499    const PotentialMap& potentialMap() const {
     500      return *_potential;
    475501    }
    476502
    477503    /// \brief Return the number of the found paths.
     
    488514    ///
    489515    /// This function returns a const reference to the specified path.
    490516    ///
    491     /// \param i The function returns the \c i-th path.
     517    /// \param i The function returns the <tt>i</tt>-th path.
    492518    /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
    493519    ///
    494520    /// \pre \ref run() or \ref findPaths() must be called before using
  • test/suurballe_test.cc

    diff --git a/test/suurballe_test.cc b/test/suurballe_test.cc
    a b  
    2222#include <lemon/lgf_reader.h>
    2323#include <lemon/path.h>
    2424#include <lemon/suurballe.h>
     25#include <lemon/concepts/digraph.h>
    2526
    2627#include "test_tools.h"
    2728
     
    2930
    3031char test_lgf[] =
    3132  "@nodes\n"
    32   "label supply1 supply2 supply3\n"
    33   "1     0        20      27\n"
    34   "2     0       -4        0\n"
    35   "3     0        0        0\n"
    36   "4     0        0        0\n"
    37   "5     0        9        0\n"
    38   "6     0       -6        0\n"
    39   "7     0        0        0\n"
    40   "8     0        0        0\n"
    41   "9     0        3        0\n"
    42   "10    0       -2        0\n"
    43   "11    0        0        0\n"
    44   "12    0       -20     -27\n"
     33  "label\n"
     34  "1\n"
     35  "2\n"
     36  "3\n"
     37  "4\n"
     38  "5\n"
     39  "6\n"
     40  "7\n"
     41  "8\n"
     42  "9\n"
     43  "10\n"
     44  "11\n"
     45  "12\n"
    4546  "@arcs\n"
    46   "      cost capacity lower1 lower2\n"
    47   " 1  2  70  11       0      8\n"
    48   " 1  3 150   3       0      1\n"
    49   " 1  4  80  15       0      2\n"
    50   " 2  8  80  12       0      0\n"
    51   " 3  5 140   5       0      3\n"
    52   " 4  6  60  10       0      1\n"
    53   " 4  7  80   2       0      0\n"
    54   " 4  8 110   3       0      0\n"
    55   " 5  7  60  14       0      0\n"
    56   " 5 11 120  12       0      0\n"
    57   " 6  3   0   3       0      0\n"
    58   " 6  9 140   4       0      0\n"
    59   " 6 10  90   8       0      0\n"
    60   " 7  1  30   5       0      0\n"
    61   " 8 12  60  16       0      4\n"
    62   " 9 12  50   6       0      0\n"
    63   "10 12  70  13       0      5\n"
    64   "10  2 100   7       0      0\n"
    65   "10  7  60  10       0      0\n"
    66   "11 10  20  14       0      6\n"
    67   "12 11  30  10       0      0\n"
     47  "      length\n"
     48  " 1  2  70\n"
     49  " 1  3 150\n"
     50  " 1  4  80\n"
     51  " 2  8  80\n"
     52  " 3  5 140\n"
     53  " 4  6  60\n"
     54  " 4  7  80\n"
     55  " 4  8 110\n"
     56  " 5  7  60\n"
     57  " 5 11 120\n"
     58  " 6  3   0\n"
     59  " 6  9 140\n"
     60  " 6 10  90\n"
     61  " 7  1  30\n"
     62  " 8 12  60\n"
     63  " 9 12  50\n"
     64  "10 12  70\n"
     65  "10  2 100\n"
     66  "10  7  60\n"
     67  "11 10  20\n"
     68  "12 11  30\n"
    6869  "@attributes\n"
    6970  "source  1\n"
    7071  "target 12\n"
    7172  "@end\n";
    7273
     74// Check the interface of Suurballe
     75void checkSuurballeCompile()
     76{
     77  typedef int VType;
     78  typedef concepts::Digraph Digraph;
     79
     80  typedef Digraph::Node Node;
     81  typedef Digraph::Arc Arc;
     82  typedef concepts::ReadMap<Arc, VType> LengthMap;
     83 
     84  typedef Suurballe<Digraph, LengthMap> SuurballeType;
     85
     86  Digraph g;
     87  Node n;
     88  Arc e;
     89  LengthMap len;
     90  SuurballeType::FlowMap flow(g);
     91  SuurballeType::PotentialMap pi(g);
     92
     93  SuurballeType suurb_test(g, len);
     94  const SuurballeType& const_suurb_test = suurb_test;
     95
     96  suurb_test
     97    .flowMap(flow)
     98    .potentialMap(pi);
     99
     100  int k;
     101  k = suurb_test.run(n, n);
     102  k = suurb_test.run(n, n, k);
     103  suurb_test.init(n);
     104  k = suurb_test.findFlow(n);
     105  k = suurb_test.findFlow(n, k);
     106  suurb_test.findPaths();
     107 
     108  int f;
     109  VType c;
     110  c = const_suurb_test.totalLength();
     111  f = const_suurb_test.flow(e);
     112  const SuurballeType::FlowMap& fm =
     113    const_suurb_test.flowMap();
     114  c = const_suurb_test.potential(n);
     115  const SuurballeType::PotentialMap& pm =
     116    const_suurb_test.potentialMap();
     117  k = const_suurb_test.pathNum();
     118  Path<Digraph> p = const_suurb_test.path(k);
     119 
     120  ignore_unused_variable_warning(fm);
     121  ignore_unused_variable_warning(pm);
     122}
     123
    73124// Check the feasibility of the flow
    74125template <typename Digraph, typename FlowMap>
    75126bool checkFlow( const Digraph& gr, const FlowMap& flow,
     
    118169bool checkPath( const Digraph& gr, const Path& path,
    119170                typename Digraph::Node s, typename Digraph::Node t)
    120171{
    121   // Check the "Complementary Slackness" optimality condition
    122172  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
    123173  Node n = s;
    124174  for (int i = 0; i < path.length(); ++i) {
     
    136186  // Read the test digraph
    137187  ListDigraph digraph;
    138188  ListDigraph::ArcMap<int> length(digraph);
    139   Node source, target;
     189  Node s, t;
    140190
    141191  std::istringstream input(test_lgf);
    142192  DigraphReader<ListDigraph>(digraph, input).
    143     arcMap("cost", length).
    144     node("source", source).
    145     node("target", target).
     193    arcMap("length", length).
     194    node("source", s).
     195    node("target", t).
    146196    run();
    147197
    148198  // Find 2 paths
    149199  {
    150     Suurballe<ListDigraph> suurballe(digraph, length, source, target);
    151     check(suurballe.run(2) == 2, "Wrong number of paths");
    152     check(checkFlow(digraph, suurballe.flowMap(), source, target, 2),
     200    Suurballe<ListDigraph> suurballe(digraph, length);
     201    check(suurballe.run(s, t) == 2, "Wrong number of paths");
     202    check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
    153203          "The flow is not feasible");
    154204    check(suurballe.totalLength() == 510, "The flow is not optimal");
    155205    check(checkOptimality(digraph, length, suurballe.flowMap(),
    156206                          suurballe.potentialMap()),
    157207          "Wrong potentials");
    158208    for (int i = 0; i < suurballe.pathNum(); ++i)
    159       check(checkPath(digraph, suurballe.path(i), source, target),
    160             "Wrong path");
     209      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
    161210  }
    162211
    163212  // Find 3 paths
    164213  {
    165     Suurballe<ListDigraph> suurballe(digraph, length, source, target);
    166     check(suurballe.run(3) == 3, "Wrong number of paths");
    167     check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
     214    Suurballe<ListDigraph> suurballe(digraph, length);
     215    check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
     216    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
    168217          "The flow is not feasible");
    169218    check(suurballe.totalLength() == 1040, "The flow is not optimal");
    170219    check(checkOptimality(digraph, length, suurballe.flowMap(),
    171220                          suurballe.potentialMap()),
    172221          "Wrong potentials");
    173222    for (int i = 0; i < suurballe.pathNum(); ++i)
    174       check(checkPath(digraph, suurballe.path(i), source, target),
    175             "Wrong path");
     223      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
    176224  }
    177225
    178226  // Find 5 paths (only 3 can be found)
    179227  {
    180     Suurballe<ListDigraph> suurballe(digraph, length, source, target);
    181     check(suurballe.run(5) == 3, "Wrong number of paths");
    182     check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
     228    Suurballe<ListDigraph> suurballe(digraph, length);
     229    check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
     230    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
    183231          "The flow is not feasible");
    184232    check(suurballe.totalLength() == 1040, "The flow is not optimal");
    185233    check(checkOptimality(digraph, length, suurballe.flowMap(),
    186234                          suurballe.potentialMap()),
    187235          "Wrong potentials");
    188236    for (int i = 0; i < suurballe.pathNum(); ++i)
    189       check(checkPath(digraph, suurballe.path(i), source, target),
    190             "Wrong path");
     237      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
    191238  }
    192239
    193240  return 0;
  • tools/lgf-gen.cc

    diff --git a/tools/lgf-gen.cc b/tools/lgf-gen.cc
    a b  
    480480      Node b=g.v(*ei);
    481481      g.erase(*ei);
    482482      ConstMap<Arc,int> cegy(1);
    483       Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
    484       int k=sur.run(2);
     483      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
     484      int k=sur.run(a,b,2);
    485485      if(k<2 || sur.totalLength()>d)
    486486        g.addEdge(a,b);
    487487      else cnt++;
     
    511511      Edge ne;
    512512      if(e==INVALID) {
    513513        ConstMap<Arc,int> cegy(1);
    514         Suurballe<ListGraph,ConstMap<Arc,int> >
    515           sur(g,cegy,pi->a,pi->b);
    516         int k=sur.run(2);
     514        Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
     515        int k=sur.run(pi->a,pi->b,2);
    517516        if(k<2 || sur.totalLength()>d)
    518517          {
    519518            ne=g.addEdge(pi->a,pi->b);