| 255 | */ |
| 256 | template <class Tannotation, class Tedge_iterator> |
| 257 | void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths) |
| 258 | { |
| 259 | typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet; |
| 260 | Tedge_iterator iter(this->job); |
| 261 | uint16_t size = this->job.Size(); |
| 262 | AnnoSet annos; |
| 263 | paths.resize(size, nullptr); |
| 264 | for (NodeID node = 0; node < size; ++node) { |
| 265 | Tannotation *anno = new Tannotation(node, node == source_node); |
| 266 | anno->UpdateAnnotation(); |
| 267 | annos.insert(anno); |
| 268 | paths[node] = anno; |
| 269 | } |
| 270 | while (!annos.empty()) { |
| 271 | typename AnnoSet::iterator i = annos.begin(); |
| 272 | Tannotation *source = *i; |
| 273 | annos.erase(i); |
| 274 | NodeID from = source->GetNode(); |
| 275 | iter.SetNode(source_node, from); |
| 276 | for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) { |
| 277 | if (to == from) continue; // Not a real edge but a consumption sign. |
| 278 | const Edge &edge = this->job[from][to]; |
| 279 | uint capacity = edge.base.capacity; |
| 280 | if (this->max_saturation != UINT_MAX) { |
| 281 | capacity *= this->max_saturation; |
| 282 | capacity /= 100; |
| 283 | if (capacity == 0) capacity = 1; |
| 284 | } |
| 285 | /* Prioritize the fastest route for passengers, mail and express cargo, |
| 286 | * and the shortest route for other classes of cargo. |
| 287 | * In-between stops are punished with a 1 tile or 1 day penalty. */ |
| 288 | bool express = IsCargoInClass(this->job.Cargo(), CargoClass::Passengers) || |
| 289 | IsCargoInClass(this->job.Cargo(), CargoClass::Mail) || |
| 290 | IsCargoInClass(this->job.Cargo(), CargoClass::Express); |
| 291 | uint distance = DistanceMaxPlusManhattan(this->job[from].base.xy, this->job[to].base.xy) + 1; |
| 292 | /* Compute a default travel time from the distance and an average speed of 1 tile/day. */ |
| 293 | uint time = (edge.base.TravelTime() != 0) ? edge.base.TravelTime() + Ticks::DAY_TICKS : distance * Ticks::DAY_TICKS; |
| 294 | uint distance_anno = express ? time : distance; |
| 295 | |
| 296 | Tannotation *dest = static_cast<Tannotation *>(paths[to]); |
| 297 | if (dest->IsBetter(source, capacity, capacity - edge.Flow(), distance_anno)) { |
| 298 | annos.erase(dest); |
| 299 | dest->Fork(source, capacity, capacity - edge.Flow(), distance_anno); |
| 300 | dest->UpdateAnnotation(); |
| 301 | annos.insert(dest); |
| 302 | } |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | /** |
| 308 | * Clean up paths that lead nowhere and the root path. |
nothing calls this directly
no test coverage detected