Add negativeCycle() function to BellmanFord (#51)
authorPeter Kovacs <kpeter@inf.elte.hu>
Mon, 03 Aug 2009 00:54:04 +0200
changeset 74675325dfccf38
parent 745 f9746e45246e
child 747 6f7c1052d260
Add negativeCycle() function to BellmanFord (#51)
lemon/bellman_ford.h
test/bellman_ford_test.cc
     1.1 --- a/lemon/bellman_ford.h	Mon Aug 03 00:52:45 2009 +0200
     1.2 +++ b/lemon/bellman_ford.h	Mon Aug 03 00:54:04 2009 +0200
     1.3 @@ -770,44 +770,34 @@
     1.4        return (*_dist)[v] != OperationTraits::infinity();
     1.5      }
     1.6  
     1.7 -    // TODO: implement negative cycle
     1.8 -//    /// \brief Gives back a negative cycle.
     1.9 -//    ///    
    1.10 -//    /// This function gives back a negative cycle.
    1.11 -//    /// If the algorithm have not found yet negative cycle it will give back
    1.12 -//    /// an empty path.
    1.13 -//    Path negativeCycle() {
    1.14 -//      typename Digraph::template NodeMap<int> state(*digraph, 0);
    1.15 -//      for (ActiveIt it(*this); it != INVALID; ++it) {
    1.16 -//        if (state[it] == 0) {
    1.17 -//          for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
    1.18 -//            if (state[t] == 0) {
    1.19 -//              state[t] = 1;
    1.20 -//            } else if (state[t] == 2) {
    1.21 -//              break;
    1.22 -//            } else {
    1.23 -//              p.clear();
    1.24 -//              typename Path::Builder b(p);
    1.25 -//              b.setStartNode(t);
    1.26 -//              b.pushFront(predArc(t));
    1.27 -//              for(Node s = predNode(t); s != t; s = predNode(s)) {
    1.28 -//                b.pushFront(predArc(s));
    1.29 -//              }
    1.30 -//              b.commit();
    1.31 -//              return true;
    1.32 -//            }
    1.33 -//          }
    1.34 -//          for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
    1.35 -//            if (state[t] == 1) {
    1.36 -//              state[t] = 2;
    1.37 -//            } else {
    1.38 -//              break;
    1.39 -//            }
    1.40 -//          }
    1.41 -//        }
    1.42 -//      }
    1.43 -//      return false;
    1.44 -//    }
    1.45 +    /// \brief Gives back a negative cycle.
    1.46 +    ///    
    1.47 +    /// This function gives back a directed cycle with negative total
    1.48 +    /// length if the algorithm has already found one.
    1.49 +    /// Otherwise it gives back an empty path.
    1.50 +    lemon::Path<Digraph> negativeCycle() {
    1.51 +      typename Digraph::template NodeMap<int> state(*_gr, -1);
    1.52 +      lemon::Path<Digraph> cycle;
    1.53 +      for (int i = 0; i < int(_process.size()); ++i) {
    1.54 +        if (state[_process[i]] != -1) continue;
    1.55 +        for (Node v = _process[i]; (*_pred)[v] != INVALID;
    1.56 +             v = _gr->source((*_pred)[v])) {
    1.57 +          if (state[v] == i) {
    1.58 +            cycle.addFront((*_pred)[v]);
    1.59 +            for (Node u = _gr->source((*_pred)[v]); u != v;
    1.60 +                 u = _gr->source((*_pred)[u])) {
    1.61 +              cycle.addFront((*_pred)[u]);
    1.62 +            }
    1.63 +            return cycle;
    1.64 +          }
    1.65 +          else if (state[v] >= 0) {
    1.66 +            break;
    1.67 +          }
    1.68 +          state[v] = i;
    1.69 +        }
    1.70 +      }
    1.71 +      return cycle;
    1.72 +    }
    1.73      
    1.74      ///@}
    1.75    };
     2.1 --- a/test/bellman_ford_test.cc	Mon Aug 03 00:52:45 2009 +0200
     2.2 +++ b/test/bellman_ford_test.cc	Mon Aug 03 00:54:04 2009 +0200
     2.3 @@ -220,8 +220,64 @@
     2.4    }
     2.5  }
     2.6  
     2.7 +void checkBellmanFordNegativeCycle() {
     2.8 +  DIGRAPH_TYPEDEFS(SmartDigraph);
     2.9 +
    2.10 +  SmartDigraph gr;
    2.11 +  IntArcMap length(gr);
    2.12 +  
    2.13 +  Node n1 = gr.addNode();
    2.14 +  Node n2 = gr.addNode();
    2.15 +  Node n3 = gr.addNode();
    2.16 +  Node n4 = gr.addNode();
    2.17 +  
    2.18 +  Arc a1 = gr.addArc(n1, n2);
    2.19 +  Arc a2 = gr.addArc(n2, n2);
    2.20 +  
    2.21 +  length[a1] = 2;
    2.22 +  length[a2] = -1;
    2.23 +  
    2.24 +  {
    2.25 +    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
    2.26 +    bf.run(n1);
    2.27 +    StaticPath<SmartDigraph> p = bf.negativeCycle();
    2.28 +    check(p.length() == 1 && p.front() == p.back() && p.front() == a2,
    2.29 +          "Wrong negative cycle.");
    2.30 +  }
    2.31 + 
    2.32 +  length[a2] = 0;
    2.33 +  
    2.34 +  {
    2.35 +    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
    2.36 +    bf.run(n1);
    2.37 +    check(bf.negativeCycle().empty(),
    2.38 +          "Negative cycle should not be found.");
    2.39 +  }
    2.40 +  
    2.41 +  length[gr.addArc(n1, n3)] = 5;
    2.42 +  length[gr.addArc(n4, n3)] = 1;
    2.43 +  length[gr.addArc(n2, n4)] = 2;
    2.44 +  length[gr.addArc(n3, n2)] = -4;
    2.45 +  
    2.46 +  {
    2.47 +    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
    2.48 +    bf.init();
    2.49 +    bf.addSource(n1);
    2.50 +    for (int i = 0; i < 4; ++i) {
    2.51 +      check(bf.negativeCycle().empty(),
    2.52 +            "Negative cycle should not be found.");
    2.53 +      bf.processNextRound();
    2.54 +    }
    2.55 +    StaticPath<SmartDigraph> p = bf.negativeCycle();
    2.56 +    check(p.length() == 3, "Wrong negative cycle.");
    2.57 +    check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1,
    2.58 +          "Wrong negative cycle.");
    2.59 +  }
    2.60 +}
    2.61 +
    2.62  int main() {
    2.63    checkBellmanFord<ListDigraph, int>();
    2.64    checkBellmanFord<SmartDigraph, double>();
    2.65 +  checkBellmanFordNegativeCycle();
    2.66    return 0;
    2.67  }