gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add negativeCycle() function to BellmanFord (#51)
0 2 0
default
2 files changed with 84 insertions and 38 deletions:
↑ Collapse diff ↑
Ignore white space 12 line context
... ...
@@ -767,50 +767,40 @@
767 767
    /// \pre Either \ref run() or \ref init() must be called before
768 768
    /// using this function.
769 769
    bool reached(Node v) const {
770 770
      return (*_dist)[v] != OperationTraits::infinity();
771 771
    }
772 772

	
773
    // TODO: implement negative cycle
774
//    /// \brief Gives back a negative cycle.
775
//    ///    
776
//    /// This function gives back a negative cycle.
777
//    /// If the algorithm have not found yet negative cycle it will give back
778
//    /// an empty path.
779
//    Path negativeCycle() {
780
//      typename Digraph::template NodeMap<int> state(*digraph, 0);
781
//      for (ActiveIt it(*this); it != INVALID; ++it) {
782
//        if (state[it] == 0) {
783
//          for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
784
//            if (state[t] == 0) {
785
//              state[t] = 1;
786
//            } else if (state[t] == 2) {
787
//              break;
788
//            } else {
789
//              p.clear();
790
//              typename Path::Builder b(p);
791
//              b.setStartNode(t);
792
//              b.pushFront(predArc(t));
793
//              for(Node s = predNode(t); s != t; s = predNode(s)) {
794
//                b.pushFront(predArc(s));
795
//              }
796
//              b.commit();
797
//              return true;
798
//            }
799
//          }
800
//          for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
801
//            if (state[t] == 1) {
802
//              state[t] = 2;
803
//            } else {
804
//              break;
805
//            }
806
//          }
807
//        }
808
//      }
809
//      return false;
810
//    }
773
    /// \brief Gives back a negative cycle.
774
    ///    
775
    /// This function gives back a directed cycle with negative total
776
    /// length if the algorithm has already found one.
777
    /// Otherwise it gives back an empty path.
778
    lemon::Path<Digraph> negativeCycle() {
779
      typename Digraph::template NodeMap<int> state(*_gr, -1);
780
      lemon::Path<Digraph> cycle;
781
      for (int i = 0; i < int(_process.size()); ++i) {
782
        if (state[_process[i]] != -1) continue;
783
        for (Node v = _process[i]; (*_pred)[v] != INVALID;
784
             v = _gr->source((*_pred)[v])) {
785
          if (state[v] == i) {
786
            cycle.addFront((*_pred)[v]);
787
            for (Node u = _gr->source((*_pred)[v]); u != v;
788
                 u = _gr->source((*_pred)[u])) {
789
              cycle.addFront((*_pred)[u]);
790
            }
791
            return cycle;
792
          }
793
          else if (state[v] >= 0) {
794
            break;
795
          }
796
          state[v] = i;
797
        }
798
      }
799
      return cycle;
800
    }
811 801
    
812 802
    ///@}
813 803
  };
814 804
 
815 805
  /// \brief Default traits class of bellmanFord() function.
816 806
  ///
Ignore white space 12 line context
... ...
@@ -217,11 +217,67 @@
217 217
              bf.dist(v) - bf.dist(u) - length[e]);
218 218
      }
219 219
    }
220 220
  }
221 221
}
222 222

	
223
void checkBellmanFordNegativeCycle() {
224
  DIGRAPH_TYPEDEFS(SmartDigraph);
225

	
226
  SmartDigraph gr;
227
  IntArcMap length(gr);
228
  
229
  Node n1 = gr.addNode();
230
  Node n2 = gr.addNode();
231
  Node n3 = gr.addNode();
232
  Node n4 = gr.addNode();
233
  
234
  Arc a1 = gr.addArc(n1, n2);
235
  Arc a2 = gr.addArc(n2, n2);
236
  
237
  length[a1] = 2;
238
  length[a2] = -1;
239
  
240
  {
241
    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
242
    bf.run(n1);
243
    StaticPath<SmartDigraph> p = bf.negativeCycle();
244
    check(p.length() == 1 && p.front() == p.back() && p.front() == a2,
245
          "Wrong negative cycle.");
246
  }
247
 
248
  length[a2] = 0;
249
  
250
  {
251
    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
252
    bf.run(n1);
253
    check(bf.negativeCycle().empty(),
254
          "Negative cycle should not be found.");
255
  }
256
  
257
  length[gr.addArc(n1, n3)] = 5;
258
  length[gr.addArc(n4, n3)] = 1;
259
  length[gr.addArc(n2, n4)] = 2;
260
  length[gr.addArc(n3, n2)] = -4;
261
  
262
  {
263
    BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
264
    bf.init();
265
    bf.addSource(n1);
266
    for (int i = 0; i < 4; ++i) {
267
      check(bf.negativeCycle().empty(),
268
            "Negative cycle should not be found.");
269
      bf.processNextRound();
270
    }
271
    StaticPath<SmartDigraph> p = bf.negativeCycle();
272
    check(p.length() == 3, "Wrong negative cycle.");
273
    check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1,
274
          "Wrong negative cycle.");
275
  }
276
}
277

	
223 278
int main() {
224 279
  checkBellmanFord<ListDigraph, int>();
225 280
  checkBellmanFord<SmartDigraph, double>();
281
  checkBellmanFordNegativeCycle();
226 282
  return 0;
227 283
}
0 comments (0 inline)