1 25 41 package org.jgrapht.alg; 42 43 import java.util.*; 44 45 import org.jgrapht.*; 46 47 48 52 class BellmanFordIterator<V, E> 53 implements Iterator<List<V>> 54 { 55 56 58 61 protected final static String NEGATIVE_UNDIRECTED_EDGE = 62 "Negative" 63 + "edge-weights are not allowed in an unidrected graph!"; 64 65 67 70 protected Graph<V, E> graph; 71 72 75 protected V startVertex; 76 77 81 private List<V> prevImprovedVertices = new ArrayList<V>(); 82 83 private Map<V, BellmanFordPathElement<V, E>> prevVertexData; 84 85 private boolean startVertexEncountered = false; 86 87 91 private Map<V, BellmanFordPathElement<V, E>> vertexData; 92 93 95 99 protected BellmanFordIterator(Graph<V, E> graph, V startVertex) 100 { 101 assertBellmanFordIterator(graph, startVertex); 102 103 this.graph = graph; 104 this.startVertex = startVertex; 105 } 106 107 109 117 public BellmanFordPathElement<V, E> getPathElement(V endVertex) 118 { 119 return getSeenData(endVertex); 120 } 121 122 126 public boolean hasNext() 127 { 128 if (!this.startVertexEncountered) { 129 encounterStartVertex(); 130 } 131 132 return !(this.prevImprovedVertices.isEmpty()); 133 } 134 135 141 public List<V> next() 142 { 143 if (!this.startVertexEncountered) { 144 encounterStartVertex(); 145 } 146 147 if (hasNext()) { 148 List<V> improvedVertices = new ArrayList<V>(); 149 for (int i = this.prevImprovedVertices.size() - 1; i >= 0; i--) { 150 V vertex = this.prevImprovedVertices.get(i); 151 for ( 152 Iterator<? extends E> iter = edgesOfIterator(vertex); 153 iter.hasNext();) { 154 E edge = iter.next(); 155 V oppositeVertex = 156 Graphs.getOppositeVertex( 157 graph, 158 edge, 159 vertex); 160 if (getPathElement(oppositeVertex) != null) { 161 boolean relaxed = 162 relaxVertexAgain(oppositeVertex, edge); 163 if (relaxed) { 164 improvedVertices.add(oppositeVertex); 165 } 166 } else { 167 relaxVertex(oppositeVertex, edge); 168 improvedVertices.add(oppositeVertex); 169 } 170 } 171 } 172 173 savePassData(improvedVertices); 174 175 return improvedVertices; 176 } 177 178 throw new NoSuchElementException(); 179 } 180 181 186 public void remove() 187 { 188 throw new UnsupportedOperationException (); 189 } 190 191 197 protected void assertValidEdge(E edge) 198 { 199 if (this.graph instanceof UndirectedGraph) { 200 if (graph.getEdgeWeight(edge) < 0) { 201 throw new IllegalArgumentException (NEGATIVE_UNDIRECTED_EDGE); 202 } 203 } 204 } 205 206 217 protected double calculatePathCost(V vertex, E edge) 218 { 219 V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex); 220 221 BellmanFordPathElement<V, E> oppositePrevData = 223 getPrevSeenData(oppositeVertex); 224 225 double pathCost = graph.getEdgeWeight(edge); 226 227 if (!oppositePrevData.getVertex().equals(this.startVertex)) { 228 pathCost += oppositePrevData.getCost(); 231 } 232 233 return pathCost; 234 } 235 236 244 protected Iterator<E> edgesOfIterator(V vertex) 245 { 246 if (this.graph instanceof DirectedGraph) { 247 return 248 ((DirectedGraph<V, E>) this.graph).outgoingEdgesOf(vertex) 249 .iterator(); 250 } else { 251 return this.graph.edgesOf(vertex).iterator(); 252 } 253 } 254 255 263 protected BellmanFordPathElement<V, E> getPrevSeenData(V vertex) 264 { 265 return this.prevVertexData.get(vertex); 266 } 267 268 276 protected BellmanFordPathElement<V, E> getSeenData(V vertex) 277 { 278 return this.vertexData.get(vertex); 279 } 280 281 288 protected boolean isSeenVertex(V vertex) 289 { 290 return this.vertexData.containsKey(vertex); 291 } 292 293 299 protected BellmanFordPathElement<V, E> putPrevSeenData( 300 V vertex, 301 BellmanFordPathElement<V, E> data) 302 { 303 if (this.prevVertexData == null) { 304 this.prevVertexData = 305 new HashMap<V, BellmanFordPathElement<V, E>>(); 306 } 307 308 return this.prevVertexData.put(vertex, data); 309 } 310 311 321 protected BellmanFordPathElement<V, E> putSeenData( 322 V vertex, 323 BellmanFordPathElement<V, E> data) 324 { 325 if (this.vertexData == null) { 326 this.vertexData = new HashMap<V, BellmanFordPathElement<V, E>>(); 327 } 328 329 return this.vertexData.put(vertex, data); 330 } 331 332 private void assertBellmanFordIterator(Graph<V, E> graph, V startVertex) 333 { 334 if (!(graph.containsVertex(startVertex))) { 335 throw new IllegalArgumentException ( 336 "Graph must contain the start vertex!"); 337 } 338 } 339 340 349 private BellmanFordPathElement<V, E> createSeenData( 350 V vertex, 351 E edge, 352 double cost) 353 { 354 BellmanFordPathElement<V, E> prevPathElement = 355 getPrevSeenData( 356 Graphs.getOppositeVertex(graph, edge, vertex)); 357 358 BellmanFordPathElement<V, E> data = 359 new BellmanFordPathElement<V, E>( 360 graph, 361 prevPathElement, 362 edge, 363 cost); 364 365 return data; 366 } 367 368 private void encounterStartVertex() 369 { 370 BellmanFordPathElement<V, E> data = 371 new BellmanFordPathElement<V, E>( 372 this.startVertex); 373 374 this.prevImprovedVertices.add(this.startVertex); 376 377 putSeenData(this.startVertex, data); 378 putPrevSeenData(this.startVertex, data); 379 380 this.startVertexEncountered = true; 381 } 382 383 389 private void relaxVertex(V vertex, E edge) 390 { 391 assertValidEdge(edge); 392 393 double shortestPathCost = calculatePathCost(vertex, edge); 394 395 BellmanFordPathElement<V, E> data = 396 createSeenData(vertex, edge, 397 shortestPathCost); 398 399 putSeenData(vertex, data); 400 } 401 402 412 private boolean relaxVertexAgain(V vertex, E edge) 413 { 414 assertValidEdge(edge); 415 416 double candidateCost = calculatePathCost(vertex, edge); 417 418 BellmanFordPathElement<V, E> oppositePrevData = 420 getPrevSeenData( 421 Graphs.getOppositeVertex(graph, edge, vertex)); 422 423 BellmanFordPathElement<V, E> pathElement = getSeenData(vertex); 424 return pathElement.improve(oppositePrevData, edge, candidateCost); 425 } 426 427 private void savePassData(List<V> improvedVertices) 428 { 429 for (V vertex : improvedVertices) { 430 BellmanFordPathElement<V, E> orig = getSeenData(vertex); 431 BellmanFordPathElement<V, E> clonedData = 432 new BellmanFordPathElement<V, E>(orig); 433 putPrevSeenData(vertex, clonedData); 434 } 435 436 this.prevImprovedVertices = improvedVertices; 437 } 438 } 439 | Popular Tags |