| [698] | 1 | /* -*- mode: C++; indent-tabs-mode: nil; -*- | 
|---|
 | 2 |  * | 
|---|
 | 3 |  * This file is a part of LEMON, a generic C++ optimization library. | 
|---|
 | 4 |  * | 
|---|
| [877] | 5 |  * Copyright (C) 2003-2010 | 
|---|
| [698] | 6 |  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport | 
|---|
 | 7 |  * (Egervary Research Group on Combinatorial Optimization, EGRES). | 
|---|
 | 8 |  * | 
|---|
 | 9 |  * Permission to use, modify and distribute this software is granted | 
|---|
 | 10 |  * provided that this copyright notice appears in all copies. For | 
|---|
 | 11 |  * precise terms see the accompanying LICENSE file. | 
|---|
 | 12 |  * | 
|---|
 | 13 |  * This software is provided "AS IS" with no warranty of any kind, | 
|---|
 | 14 |  * express or implied, and with no claim as to its suitability for any | 
|---|
 | 15 |  * purpose. | 
|---|
 | 16 |  * | 
|---|
 | 17 |  */ | 
|---|
 | 18 |  | 
|---|
 | 19 | #include <lemon/concepts/digraph.h> | 
|---|
 | 20 | #include <lemon/smart_graph.h> | 
|---|
 | 21 | #include <lemon/list_graph.h> | 
|---|
 | 22 | #include <lemon/lgf_reader.h> | 
|---|
 | 23 | #include <lemon/bellman_ford.h> | 
|---|
 | 24 | #include <lemon/path.h> | 
|---|
 | 25 |  | 
|---|
 | 26 | #include "graph_test.h" | 
|---|
 | 27 | #include "test_tools.h" | 
|---|
 | 28 |  | 
|---|
 | 29 | using namespace lemon; | 
|---|
 | 30 |  | 
|---|
 | 31 | char test_lgf[] = | 
|---|
 | 32 |   "@nodes\n" | 
|---|
 | 33 |   "label\n" | 
|---|
 | 34 |   "0\n" | 
|---|
 | 35 |   "1\n" | 
|---|
 | 36 |   "2\n" | 
|---|
 | 37 |   "3\n" | 
|---|
 | 38 |   "4\n" | 
|---|
 | 39 |   "@arcs\n" | 
|---|
 | 40 |   "    length\n" | 
|---|
 | 41 |   "0 1 3\n" | 
|---|
 | 42 |   "1 2 -3\n" | 
|---|
 | 43 |   "1 2 -5\n" | 
|---|
 | 44 |   "1 3 -2\n" | 
|---|
 | 45 |   "0 2 -1\n" | 
|---|
 | 46 |   "1 2 -4\n" | 
|---|
 | 47 |   "0 3 2\n" | 
|---|
 | 48 |   "4 2 -5\n" | 
|---|
 | 49 |   "2 3 1\n" | 
|---|
 | 50 |   "@attributes\n" | 
|---|
 | 51 |   "source 0\n" | 
|---|
 | 52 |   "target 3\n"; | 
|---|
 | 53 |  | 
|---|
 | 54 |  | 
|---|
 | 55 | void checkBellmanFordCompile() | 
|---|
 | 56 | { | 
|---|
 | 57 |   typedef int Value; | 
|---|
 | 58 |   typedef concepts::Digraph Digraph; | 
|---|
 | 59 |   typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap; | 
|---|
 | 60 |   typedef BellmanFord<Digraph, LengthMap> BF; | 
|---|
 | 61 |   typedef Digraph::Node Node; | 
|---|
 | 62 |   typedef Digraph::Arc Arc; | 
|---|
 | 63 |  | 
|---|
 | 64 |   Digraph gr; | 
|---|
 | 65 |   Node s, t, n; | 
|---|
 | 66 |   Arc e; | 
|---|
 | 67 |   Value l; | 
|---|
| [790] | 68 |   int k=3; | 
|---|
| [698] | 69 |   bool b; | 
|---|
 | 70 |   BF::DistMap d(gr); | 
|---|
 | 71 |   BF::PredMap p(gr); | 
|---|
 | 72 |   LengthMap length; | 
|---|
 | 73 |   concepts::Path<Digraph> pp; | 
|---|
 | 74 |  | 
|---|
 | 75 |   { | 
|---|
 | 76 |     BF bf_test(gr,length); | 
|---|
 | 77 |     const BF& const_bf_test = bf_test; | 
|---|
 | 78 |  | 
|---|
 | 79 |     bf_test.run(s); | 
|---|
 | 80 |     bf_test.run(s,k); | 
|---|
 | 81 |  | 
|---|
 | 82 |     bf_test.init(); | 
|---|
 | 83 |     bf_test.addSource(s); | 
|---|
 | 84 |     bf_test.addSource(s, 1); | 
|---|
 | 85 |     b = bf_test.processNextRound(); | 
|---|
 | 86 |     b = bf_test.processNextWeakRound(); | 
|---|
 | 87 |  | 
|---|
 | 88 |     bf_test.start(); | 
|---|
 | 89 |     bf_test.checkedStart(); | 
|---|
 | 90 |     bf_test.limitedStart(k); | 
|---|
 | 91 |  | 
|---|
 | 92 |     l  = const_bf_test.dist(t); | 
|---|
 | 93 |     e  = const_bf_test.predArc(t); | 
|---|
 | 94 |     s  = const_bf_test.predNode(t); | 
|---|
 | 95 |     b  = const_bf_test.reached(t); | 
|---|
 | 96 |     d  = const_bf_test.distMap(); | 
|---|
 | 97 |     p  = const_bf_test.predMap(); | 
|---|
 | 98 |     pp = const_bf_test.path(t); | 
|---|
| [781] | 99 |     pp = const_bf_test.negativeCycle(); | 
|---|
| [877] | 100 |  | 
|---|
| [698] | 101 |     for (BF::ActiveIt it(const_bf_test); it != INVALID; ++it) {} | 
|---|
 | 102 |   } | 
|---|
 | 103 |   { | 
|---|
 | 104 |     BF::SetPredMap<concepts::ReadWriteMap<Node,Arc> > | 
|---|
 | 105 |       ::SetDistMap<concepts::ReadWriteMap<Node,Value> > | 
|---|
 | 106 |       ::SetOperationTraits<BellmanFordDefaultOperationTraits<Value> > | 
|---|
 | 107 |       ::Create bf_test(gr,length); | 
|---|
 | 108 |  | 
|---|
 | 109 |     LengthMap length_map; | 
|---|
 | 110 |     concepts::ReadWriteMap<Node,Arc> pred_map; | 
|---|
 | 111 |     concepts::ReadWriteMap<Node,Value> dist_map; | 
|---|
| [877] | 112 |  | 
|---|
| [698] | 113 |     bf_test | 
|---|
 | 114 |       .lengthMap(length_map) | 
|---|
 | 115 |       .predMap(pred_map) | 
|---|
 | 116 |       .distMap(dist_map); | 
|---|
 | 117 |  | 
|---|
 | 118 |     bf_test.run(s); | 
|---|
 | 119 |     bf_test.run(s,k); | 
|---|
 | 120 |  | 
|---|
 | 121 |     bf_test.init(); | 
|---|
 | 122 |     bf_test.addSource(s); | 
|---|
 | 123 |     bf_test.addSource(s, 1); | 
|---|
 | 124 |     b = bf_test.processNextRound(); | 
|---|
 | 125 |     b = bf_test.processNextWeakRound(); | 
|---|
 | 126 |  | 
|---|
 | 127 |     bf_test.start(); | 
|---|
 | 128 |     bf_test.checkedStart(); | 
|---|
 | 129 |     bf_test.limitedStart(k); | 
|---|
 | 130 |  | 
|---|
 | 131 |     l  = bf_test.dist(t); | 
|---|
 | 132 |     e  = bf_test.predArc(t); | 
|---|
 | 133 |     s  = bf_test.predNode(t); | 
|---|
 | 134 |     b  = bf_test.reached(t); | 
|---|
 | 135 |     pp = bf_test.path(t); | 
|---|
| [781] | 136 |     pp = bf_test.negativeCycle(); | 
|---|
| [698] | 137 |   } | 
|---|
 | 138 | } | 
|---|
 | 139 |  | 
|---|
 | 140 | void checkBellmanFordFunctionCompile() | 
|---|
 | 141 | { | 
|---|
 | 142 |   typedef int Value; | 
|---|
 | 143 |   typedef concepts::Digraph Digraph; | 
|---|
 | 144 |   typedef Digraph::Arc Arc; | 
|---|
 | 145 |   typedef Digraph::Node Node; | 
|---|
 | 146 |   typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap; | 
|---|
 | 147 |  | 
|---|
 | 148 |   Digraph g; | 
|---|
 | 149 |   bool b; | 
|---|
 | 150 |   bellmanFord(g,LengthMap()).run(Node()); | 
|---|
 | 151 |   b = bellmanFord(g,LengthMap()).run(Node(),Node()); | 
|---|
 | 152 |   bellmanFord(g,LengthMap()) | 
|---|
 | 153 |     .predMap(concepts::ReadWriteMap<Node,Arc>()) | 
|---|
 | 154 |     .distMap(concepts::ReadWriteMap<Node,Value>()) | 
|---|
 | 155 |     .run(Node()); | 
|---|
 | 156 |   b=bellmanFord(g,LengthMap()) | 
|---|
 | 157 |     .predMap(concepts::ReadWriteMap<Node,Arc>()) | 
|---|
 | 158 |     .distMap(concepts::ReadWriteMap<Node,Value>()) | 
|---|
 | 159 |     .path(concepts::Path<Digraph>()) | 
|---|
 | 160 |     .dist(Value()) | 
|---|
 | 161 |     .run(Node(),Node()); | 
|---|
 | 162 | } | 
|---|
 | 163 |  | 
|---|
 | 164 |  | 
|---|
 | 165 | template <typename Digraph, typename Value> | 
|---|
 | 166 | void checkBellmanFord() { | 
|---|
 | 167 |   TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); | 
|---|
 | 168 |   typedef typename Digraph::template ArcMap<Value> LengthMap; | 
|---|
 | 169 |  | 
|---|
 | 170 |   Digraph gr; | 
|---|
 | 171 |   Node s, t; | 
|---|
 | 172 |   LengthMap length(gr); | 
|---|
 | 173 |  | 
|---|
 | 174 |   std::istringstream input(test_lgf); | 
|---|
 | 175 |   digraphReader(gr, input). | 
|---|
 | 176 |     arcMap("length", length). | 
|---|
 | 177 |     node("source", s). | 
|---|
 | 178 |     node("target", t). | 
|---|
 | 179 |     run(); | 
|---|
 | 180 |  | 
|---|
 | 181 |   BellmanFord<Digraph, LengthMap> | 
|---|
 | 182 |     bf(gr, length); | 
|---|
 | 183 |   bf.run(s); | 
|---|
 | 184 |   Path<Digraph> p = bf.path(t); | 
|---|
 | 185 |  | 
|---|
 | 186 |   check(bf.reached(t) && bf.dist(t) == -1, "Bellman-Ford found a wrong path."); | 
|---|
 | 187 |   check(p.length() == 3, "path() found a wrong path."); | 
|---|
 | 188 |   check(checkPath(gr, p), "path() found a wrong path."); | 
|---|
 | 189 |   check(pathSource(gr, p) == s, "path() found a wrong path."); | 
|---|
 | 190 |   check(pathTarget(gr, p) == t, "path() found a wrong path."); | 
|---|
| [877] | 191 |  | 
|---|
| [698] | 192 |   ListPath<Digraph> path; | 
|---|
 | 193 |   Value dist; | 
|---|
 | 194 |   bool reached = bellmanFord(gr,length).path(path).dist(dist).run(s,t); | 
|---|
 | 195 |  | 
|---|
 | 196 |   check(reached && dist == -1, "Bellman-Ford found a wrong path."); | 
|---|
 | 197 |   check(path.length() == 3, "path() found a wrong path."); | 
|---|
 | 198 |   check(checkPath(gr, path), "path() found a wrong path."); | 
|---|
 | 199 |   check(pathSource(gr, path) == s, "path() found a wrong path."); | 
|---|
 | 200 |   check(pathTarget(gr, path) == t, "path() found a wrong path."); | 
|---|
 | 201 |  | 
|---|
 | 202 |   for(ArcIt e(gr); e!=INVALID; ++e) { | 
|---|
 | 203 |     Node u=gr.source(e); | 
|---|
 | 204 |     Node v=gr.target(e); | 
|---|
 | 205 |     check(!bf.reached(u) || (bf.dist(v) - bf.dist(u) <= length[e]), | 
|---|
 | 206 |           "Wrong output. dist(target)-dist(source)-arc_length=" << | 
|---|
 | 207 |           bf.dist(v) - bf.dist(u) - length[e]); | 
|---|
 | 208 |   } | 
|---|
 | 209 |  | 
|---|
 | 210 |   for(NodeIt v(gr); v!=INVALID; ++v) { | 
|---|
 | 211 |     if (bf.reached(v)) { | 
|---|
 | 212 |       check(v==s || bf.predArc(v)!=INVALID, "Wrong tree."); | 
|---|
 | 213 |       if (bf.predArc(v)!=INVALID ) { | 
|---|
 | 214 |         Arc e=bf.predArc(v); | 
|---|
 | 215 |         Node u=gr.source(e); | 
|---|
 | 216 |         check(u==bf.predNode(v),"Wrong tree."); | 
|---|
 | 217 |         check(bf.dist(v) - bf.dist(u) == length[e], | 
|---|
 | 218 |               "Wrong distance! Difference: " << | 
|---|
 | 219 |               bf.dist(v) - bf.dist(u) - length[e]); | 
|---|
 | 220 |       } | 
|---|
 | 221 |     } | 
|---|
 | 222 |   } | 
|---|
 | 223 | } | 
|---|
 | 224 |  | 
|---|
| [699] | 225 | void checkBellmanFordNegativeCycle() { | 
|---|
 | 226 |   DIGRAPH_TYPEDEFS(SmartDigraph); | 
|---|
 | 227 |  | 
|---|
 | 228 |   SmartDigraph gr; | 
|---|
 | 229 |   IntArcMap length(gr); | 
|---|
| [877] | 230 |  | 
|---|
| [699] | 231 |   Node n1 = gr.addNode(); | 
|---|
 | 232 |   Node n2 = gr.addNode(); | 
|---|
 | 233 |   Node n3 = gr.addNode(); | 
|---|
 | 234 |   Node n4 = gr.addNode(); | 
|---|
| [877] | 235 |  | 
|---|
| [699] | 236 |   Arc a1 = gr.addArc(n1, n2); | 
|---|
 | 237 |   Arc a2 = gr.addArc(n2, n2); | 
|---|
| [877] | 238 |  | 
|---|
| [699] | 239 |   length[a1] = 2; | 
|---|
 | 240 |   length[a2] = -1; | 
|---|
| [877] | 241 |  | 
|---|
| [699] | 242 |   { | 
|---|
 | 243 |     BellmanFord<SmartDigraph, IntArcMap> bf(gr, length); | 
|---|
 | 244 |     bf.run(n1); | 
|---|
 | 245 |     StaticPath<SmartDigraph> p = bf.negativeCycle(); | 
|---|
 | 246 |     check(p.length() == 1 && p.front() == p.back() && p.front() == a2, | 
|---|
 | 247 |           "Wrong negative cycle."); | 
|---|
 | 248 |   } | 
|---|
| [877] | 249 |  | 
|---|
| [699] | 250 |   length[a2] = 0; | 
|---|
| [877] | 251 |  | 
|---|
| [699] | 252 |   { | 
|---|
 | 253 |     BellmanFord<SmartDigraph, IntArcMap> bf(gr, length); | 
|---|
 | 254 |     bf.run(n1); | 
|---|
 | 255 |     check(bf.negativeCycle().empty(), | 
|---|
 | 256 |           "Negative cycle should not be found."); | 
|---|
 | 257 |   } | 
|---|
| [877] | 258 |  | 
|---|
| [699] | 259 |   length[gr.addArc(n1, n3)] = 5; | 
|---|
 | 260 |   length[gr.addArc(n4, n3)] = 1; | 
|---|
 | 261 |   length[gr.addArc(n2, n4)] = 2; | 
|---|
 | 262 |   length[gr.addArc(n3, n2)] = -4; | 
|---|
| [877] | 263 |  | 
|---|
| [699] | 264 |   { | 
|---|
 | 265 |     BellmanFord<SmartDigraph, IntArcMap> bf(gr, length); | 
|---|
 | 266 |     bf.init(); | 
|---|
 | 267 |     bf.addSource(n1); | 
|---|
 | 268 |     for (int i = 0; i < 4; ++i) { | 
|---|
 | 269 |       check(bf.negativeCycle().empty(), | 
|---|
 | 270 |             "Negative cycle should not be found."); | 
|---|
 | 271 |       bf.processNextRound(); | 
|---|
 | 272 |     } | 
|---|
 | 273 |     StaticPath<SmartDigraph> p = bf.negativeCycle(); | 
|---|
 | 274 |     check(p.length() == 3, "Wrong negative cycle."); | 
|---|
 | 275 |     check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1, | 
|---|
 | 276 |           "Wrong negative cycle."); | 
|---|
 | 277 |   } | 
|---|
 | 278 | } | 
|---|
 | 279 |  | 
|---|
| [698] | 280 | int main() { | 
|---|
 | 281 |   checkBellmanFord<ListDigraph, int>(); | 
|---|
 | 282 |   checkBellmanFord<SmartDigraph, double>(); | 
|---|
| [699] | 283 |   checkBellmanFordNegativeCycle(); | 
|---|
| [698] | 284 |   return 0; | 
|---|
 | 285 | } | 
|---|