Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file RODFNet.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Eric Nicolay
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @date Thu, 16.03.2006
20 : ///
21 : // A DFROUTER-network
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <cassert>
26 : #include <iostream>
27 : #include <map>
28 : #include <queue>
29 : #include <vector>
30 : #include <iterator>
31 : #include "RODFNet.h"
32 : #include "RODFDetector.h"
33 : #include "RODFRouteDesc.h"
34 : #include "RODFDetectorFlow.h"
35 : #include "RODFEdge.h"
36 : #include <cmath>
37 : #include <utils/common/MsgHandler.h>
38 : #include <utils/common/ToString.h>
39 : #include <utils/common/UtilExceptions.h>
40 : #include <utils/geom/GeomHelper.h>
41 :
42 :
43 : // ===========================================================================
44 : // method definitions
45 : // ===========================================================================
46 436 : RODFNet::RODFNet(bool amInHighwayMode) :
47 436 : RONet(), myAmInHighwayMode(amInHighwayMode),
48 436 : mySourceNumber(0), mySinkNumber(0), myInBetweenNumber(0), myInvalidNumber(0),
49 436 : myMaxSpeedFactorPKW(1),
50 436 : myMaxSpeedFactorLKW(1),
51 436 : myAvgSpeedFactorPKW(1),
52 436 : myAvgSpeedFactorLKW(1) {
53 436 : myDisallowedEdges = OptionsCont::getOptions().getStringVector("disallowed-edges");
54 436 : myAllowedVClass = getVehicleClassID(OptionsCont::getOptions().getString("vclass"));
55 436 : myKeepTurnarounds = OptionsCont::getOptions().getBool("keep-turnarounds");
56 436 : }
57 :
58 :
59 872 : RODFNet::~RODFNet() {
60 1308 : }
61 :
62 :
63 : bool
64 6896 : RODFNet::isAllowed(const ROEdge* const edge) const {
65 6166 : return (!edge->isInternal() && !edge->isWalkingArea() && !edge->isCrossing() &&
66 6166 : (edge->getPermissions() & myAllowedVClass) == myAllowedVClass &&
67 6164 : find(myDisallowedEdges.begin(), myDisallowedEdges.end(), edge->getID()) == myDisallowedEdges.end());
68 :
69 : }
70 :
71 :
72 : void
73 200 : RODFNet::buildApproachList() {
74 3753 : for (const auto& rit : getEdgeMap()) {
75 3553 : ROEdge* const ce = rit.second;
76 3553 : if (!isAllowed(ce)) {
77 746 : continue;
78 : }
79 6150 : for (ROEdge* const help : ce->getSuccessors()) {
80 3343 : if (!isAllowed(help)) {
81 : // blocked edges will not be used
82 22 : continue;
83 : }
84 3321 : if (!myKeepTurnarounds && help->getToJunction() == ce->getFromJunction()) {
85 : // do not use turnarounds
86 98 : continue;
87 : }
88 : // add the connection help->ce to myApproachingEdges
89 3223 : myApproachingEdges[help].push_back(ce);
90 : // add the connection ce->help to myApproachingEdges
91 3223 : myApproachedEdges[ce].push_back(help);
92 : }
93 : }
94 200 : }
95 :
96 :
97 : void
98 332 : RODFNet::buildDetectorEdgeDependencies(RODFDetectorCon& detcont) const {
99 : myDetectorsOnEdges.clear();
100 : myDetectorEdges.clear();
101 332 : const std::vector<RODFDetector*>& dets = detcont.getDetectors();
102 3212 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
103 2880 : ROEdge* e = getDetectorEdge(**i);
104 2880 : myDetectorsOnEdges[e].push_back((*i)->getID());
105 2880 : myDetectorEdges[(*i)->getID()] = e;
106 : }
107 332 : }
108 :
109 :
110 : void
111 164 : RODFNet::computeTypes(RODFDetectorCon& detcont,
112 : bool sourcesStrict) const {
113 328 : PROGRESS_BEGIN_MESSAGE(TL("Computing detector types"));
114 164 : const std::vector< RODFDetector*>& dets = detcont.getDetectors();
115 : // build needed information. first
116 164 : buildDetectorEdgeDependencies(detcont);
117 : // compute detector types then
118 1532 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
119 1368 : if (isSource(**i, detcont, sourcesStrict)) {
120 319 : (*i)->setType(SOURCE_DETECTOR);
121 319 : mySourceNumber++;
122 : }
123 1368 : if (isDestination(**i, detcont)) {
124 236 : (*i)->setType(SINK_DETECTOR);
125 236 : mySinkNumber++;
126 : }
127 1368 : if ((*i)->getType() == TYPE_NOT_DEFINED) {
128 843 : (*i)->setType(BETWEEN_DETECTOR);
129 843 : myInBetweenNumber++;
130 : }
131 : }
132 : // recheck sources
133 1532 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
134 1368 : if ((*i)->getType() == SOURCE_DETECTOR && isFalseSource(**i, detcont)) {
135 18 : (*i)->setType(DISCARDED_DETECTOR);
136 18 : myInvalidNumber++;
137 18 : mySourceNumber--;
138 : }
139 : }
140 : // print results
141 164 : PROGRESS_DONE_MESSAGE();
142 164 : WRITE_MESSAGE(TL("Computed detector types:"));
143 328 : WRITE_MESSAGEF(TL(" % source detectors"), toString(mySourceNumber));
144 328 : WRITE_MESSAGEF(TL(" % sink detectors"), toString(mySinkNumber));
145 328 : WRITE_MESSAGEF(TL(" % in-between detectors"), toString(myInBetweenNumber));
146 328 : WRITE_MESSAGEF(TL(" % invalid detectors"), toString(myInvalidNumber));
147 164 : }
148 :
149 :
150 : bool
151 2999 : RODFNet::hasInBetweenDetectorsOnly(ROEdge* edge,
152 : const RODFDetectorCon& detectors) const {
153 : assert(myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end());
154 : const std::vector<std::string>& detIDs = myDetectorsOnEdges.find(edge)->second;
155 : std::vector<std::string>::const_iterator i;
156 5259 : for (i = detIDs.begin(); i != detIDs.end(); ++i) {
157 3684 : const RODFDetector& det = detectors.getDetector(*i);
158 3684 : if (det.getType() != BETWEEN_DETECTOR) {
159 : return false;
160 : }
161 : }
162 : return true;
163 : }
164 :
165 :
166 : bool
167 1424 : RODFNet::hasSourceDetector(ROEdge* edge,
168 : const RODFDetectorCon& detectors) const {
169 : assert(myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end());
170 : const std::vector<std::string>& detIDs = myDetectorsOnEdges.find(edge)->second;
171 : std::vector<std::string>::const_iterator i;
172 3064 : for (i = detIDs.begin(); i != detIDs.end(); ++i) {
173 1674 : const RODFDetector& det = detectors.getDetector(*i);
174 1674 : if (det.getType() == SOURCE_DETECTOR) {
175 : return true;
176 : }
177 : }
178 : return false;
179 : }
180 :
181 :
182 :
183 : void
184 1232 : RODFNet::computeRoutesFor(ROEdge* edge, RODFRouteDesc& base, int /*no*/,
185 : bool keepUnfoundEnds,
186 : bool keepShortestOnly,
187 : ROEdgeVector& /*visited*/,
188 : const RODFDetector& det, RODFRouteCont& into,
189 : const RODFDetectorCon& detectors,
190 : int maxFollowingLength,
191 : ROEdgeVector& seen) const {
192 : std::vector<RODFRouteDesc> unfoundEnds;
193 : std::priority_queue<RODFRouteDesc, std::vector<RODFRouteDesc>, DFRouteDescByTimeComperator> toSolve;
194 : std::map<ROEdge*, ROEdgeVector > dets2Follow;
195 1232 : dets2Follow[edge] = ROEdgeVector();
196 1232 : base.passedNo = 0;
197 1232 : double minDist = OptionsCont::getOptions().getFloat("min-route-length");
198 1232 : toSolve.push(base);
199 6772 : while (!toSolve.empty()) {
200 5540 : RODFRouteDesc current = toSolve.top();
201 5540 : toSolve.pop();
202 5540 : ROEdge* last = *(current.edges2Pass.end() - 1);
203 5540 : if (hasDetector(last)) {
204 4407 : if (dets2Follow.find(last) == dets2Follow.end()) {
205 2970 : dets2Follow[last] = ROEdgeVector();
206 : }
207 4993 : for (ROEdgeVector::reverse_iterator i = current.edges2Pass.rbegin() + 1; i != current.edges2Pass.rend(); ++i) {
208 3761 : if (hasDetector(*i)) {
209 3175 : dets2Follow[*i].push_back(last);
210 : break;
211 : }
212 : }
213 : }
214 :
215 : // do not process an edge twice
216 5540 : if (find(seen.begin(), seen.end(), last) != seen.end() && keepShortestOnly) {
217 116 : continue;
218 : }
219 5424 : seen.push_back(last);
220 : // end if the edge has no further connections
221 5424 : if (!hasApproached(last)) {
222 : // ok, no further connections to follow
223 583 : current.factor = 1.;
224 583 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
225 583 : if (minDist < cdist) {
226 579 : into.addRouteDesc(current);
227 : }
228 583 : continue;
229 583 : }
230 : // check for passing detectors:
231 : // if the current last edge is not the one the detector is placed on ...
232 : bool addNextNoFurther = false;
233 4841 : if (last != getDetectorEdge(det)) {
234 : // ... if there is a detector ...
235 3667 : if (hasDetector(last)) {
236 2999 : if (!hasInBetweenDetectorsOnly(last, detectors)) {
237 : // ... and it's not an in-between-detector
238 : // -> let's add this edge and the following, but not any further
239 : addNextNoFurther = true;
240 1424 : current.lastDetectorEdge = last;
241 1424 : current.duration2Last = (SUMOTime) current.duration_2;
242 1424 : current.distance2Last = current.distance;
243 1424 : current.endDetectorEdge = last;
244 1424 : if (hasSourceDetector(last, detectors)) {
245 : ///!!! //toDiscard.push_back(current);
246 : }
247 1424 : current.factor = 1.;
248 1424 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
249 1424 : if (minDist < cdist) {
250 1420 : into.addRouteDesc(current);
251 : }
252 1424 : continue;
253 1424 : } else {
254 : // ... if it's an in-between-detector
255 : // -> mark the current route as to be continued
256 1575 : current.passedNo = 0;
257 1575 : current.duration2Last = (SUMOTime) current.duration_2;
258 1575 : current.distance2Last = current.distance;
259 1575 : current.lastDetectorEdge = last;
260 : }
261 : }
262 : }
263 : // check for highway off-ramps
264 3417 : if (myAmInHighwayMode) {
265 : // if it's beside the highway...
266 0 : if (last->getSpeedLimit() < 19.4 && last != getDetectorEdge(det)) {
267 : // ... and has more than one following edge
268 0 : if (myApproachedEdges.find(last)->second.size() > 1) {
269 : // -> let's add this edge and the following, but not any further
270 : addNextNoFurther = true;
271 : }
272 :
273 : }
274 : }
275 : // check for missing end connections
276 : if (!addNextNoFurther) {
277 : // ... if this one would be processed, but already too many edge
278 : // without a detector occurred
279 3417 : if (current.passedNo > maxFollowingLength) {
280 : // mark not to process any further
281 0 : WRITE_WARNINGF(TL("Could not close route for '%'"), det.getID());
282 0 : unfoundEnds.push_back(current);
283 0 : current.factor = 1.;
284 0 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
285 0 : if (minDist < cdist) {
286 0 : into.addRouteDesc(current);
287 : }
288 0 : continue;
289 0 : }
290 : }
291 : // ... else: loop over the next edges
292 : const ROEdgeVector& appr = myApproachedEdges.find(last)->second;
293 : bool hadOne = false;
294 7818 : for (int i = 0; i < (int)appr.size(); i++) {
295 4401 : if (find(current.edges2Pass.begin(), current.edges2Pass.end(), appr[i]) != current.edges2Pass.end()) {
296 : // do not append an edge twice (do not build loops)
297 93 : continue;
298 : }
299 4308 : RODFRouteDesc t(current);
300 4308 : t.duration_2 += (appr[i]->getLength() / appr[i]->getSpeedLimit()); //!!!
301 4308 : t.distance += appr[i]->getLength();
302 4308 : t.edges2Pass.push_back(appr[i]);
303 4308 : if (!addNextNoFurther) {
304 4308 : t.passedNo++;
305 4308 : toSolve.push(t);
306 : } else {
307 0 : if (!hadOne) {
308 0 : t.factor = (double) 1. / (double) appr.size();
309 0 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
310 0 : if (minDist < cdist) {
311 0 : into.addRouteDesc(t);
312 : }
313 : hadOne = true;
314 : }
315 : }
316 : }
317 : }
318 : //
319 1232 : if (!keepUnfoundEnds) {
320 : std::vector<RODFRouteDesc>::iterator i;
321 : ConstROEdgeVector lastDetEdges;
322 1232 : for (i = unfoundEnds.begin(); i != unfoundEnds.end(); ++i) {
323 0 : if (find(lastDetEdges.begin(), lastDetEdges.end(), (*i).lastDetectorEdge) == lastDetEdges.end()) {
324 0 : lastDetEdges.push_back((*i).lastDetectorEdge);
325 : } else {
326 0 : bool ok = into.removeRouteDesc(*i);
327 : assert(ok);
328 : UNUSED_PARAMETER(ok); // only used for assertion
329 : }
330 : }
331 1232 : } else {
332 : // !!! patch the factors
333 : }
334 1232 : while (!toSolve.empty()) {
335 : // RODFRouteDesc d = toSolve.top();
336 0 : toSolve.pop();
337 : // delete d;
338 : }
339 1232 : }
340 :
341 :
342 : void
343 168 : RODFNet::buildRoutes(RODFDetectorCon& detcont, bool keepUnfoundEnds, bool includeInBetween,
344 : bool keepShortestOnly, int maxFollowingLength) const {
345 : // build needed information first
346 168 : buildDetectorEdgeDependencies(detcont);
347 : // then build the routes
348 : std::map<ROEdge*, RODFRouteCont* > doneEdges;
349 168 : const std::vector< RODFDetector*>& dets = detcont.getDetectors();
350 1680 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
351 1512 : ROEdge* e = getDetectorEdge(**i);
352 1512 : if (doneEdges.find(e) != doneEdges.end()) {
353 : // use previously build routes
354 280 : (*i)->addRoutes(new RODFRouteCont(*doneEdges[e]));
355 280 : continue;
356 : }
357 : ROEdgeVector seen;
358 1232 : RODFRouteCont* routes = new RODFRouteCont();
359 1232 : doneEdges[e] = routes;
360 : RODFRouteDesc rd;
361 1232 : rd.edges2Pass.push_back(e);
362 1232 : rd.duration_2 = (e->getLength() / e->getSpeedLimit()); //!!!;
363 1232 : rd.endDetectorEdge = nullptr;
364 1232 : rd.lastDetectorEdge = nullptr;
365 1232 : rd.distance = e->getLength();
366 1232 : rd.distance2Last = 0;
367 1232 : rd.duration2Last = 0;
368 :
369 1232 : rd.overallProb = 0;
370 :
371 : ROEdgeVector visited;
372 1232 : visited.push_back(e);
373 1232 : computeRoutesFor(e, rd, 0, keepUnfoundEnds, keepShortestOnly,
374 : visited, **i, *routes, detcont, maxFollowingLength, seen);
375 : //!!!routes->removeIllegal(illegals);
376 1232 : (*i)->addRoutes(routes);
377 :
378 : // add routes to in-between detectors if wished
379 1232 : if (includeInBetween) {
380 : // go through the routes
381 : const std::vector<RODFRouteDesc>& r = routes->get();
382 12 : for (std::vector<RODFRouteDesc>::const_iterator j = r.begin(); j != r.end(); ++j) {
383 : const RODFRouteDesc& mrd = *j;
384 6 : double duration = mrd.duration_2;
385 6 : double distance = mrd.distance;
386 : // go through each route's edges
387 : ROEdgeVector::const_iterator routeend = mrd.edges2Pass.end();
388 18 : for (ROEdgeVector::const_iterator k = mrd.edges2Pass.begin(); k != routeend; ++k) {
389 : // check whether any detectors lies on the current edge
390 12 : if (myDetectorsOnEdges.find(*k) == myDetectorsOnEdges.end()) {
391 0 : duration -= (*k)->getLength() / (*k)->getSpeedLimit();
392 0 : distance -= (*k)->getLength();
393 0 : continue;
394 : }
395 : // go through the detectors
396 24 : for (const std::string& l : myDetectorsOnEdges.find(*k)->second) {
397 12 : const RODFDetector& m = detcont.getDetector(l);
398 12 : if (m.getType() == BETWEEN_DETECTOR) {
399 : RODFRouteDesc nrd;
400 : copy(k, routeend, back_inserter(nrd.edges2Pass));
401 4 : nrd.duration_2 = duration;//!!!;
402 4 : nrd.endDetectorEdge = mrd.endDetectorEdge;
403 4 : nrd.lastDetectorEdge = mrd.lastDetectorEdge;
404 4 : nrd.distance = distance;
405 4 : nrd.distance2Last = mrd.distance2Last;
406 4 : nrd.duration2Last = mrd.duration2Last;
407 4 : nrd.overallProb = mrd.overallProb;
408 4 : nrd.factor = mrd.factor;
409 4 : ((RODFDetector&) m).addRoute(nrd);
410 : }
411 : }
412 12 : duration -= (*k)->getLength() / (*k)->getSpeedLimit();
413 12 : distance -= (*k)->getLength();
414 : }
415 : }
416 : }
417 :
418 2464 : }
419 168 : }
420 :
421 :
422 : void
423 0 : RODFNet::revalidateFlows(const RODFDetector* detector,
424 : RODFDetectorFlows& flows,
425 : SUMOTime startTime, SUMOTime endTime,
426 : SUMOTime stepOffset) {
427 : {
428 0 : if (flows.knows(detector->getID())) {
429 0 : const std::vector<FlowDef>& detFlows = flows.getFlowDefs(detector->getID());
430 0 : for (std::vector<FlowDef>::const_iterator j = detFlows.begin(); j != detFlows.end(); ++j) {
431 0 : if ((*j).qPKW > 0 || (*j).qLKW > 0) {
432 : return;
433 : }
434 : }
435 : }
436 : }
437 : // ok, there is no information for the whole time;
438 : // lets find preceding detectors and rebuild the flows if possible
439 0 : WRITE_WARNINGF(TL("Detector '%' has no flows.\n Trying to rebuild."), detector->getID());
440 : // go back and collect flows
441 : ROEdgeVector previous;
442 : {
443 : std::vector<IterationEdge> missing;
444 : IterationEdge ie;
445 0 : ie.depth = 0;
446 0 : ie.edge = getDetectorEdge(*detector);
447 0 : missing.push_back(ie);
448 : bool maxDepthReached = false;
449 0 : while (!missing.empty() && !maxDepthReached) {
450 0 : IterationEdge last = missing.back();
451 : missing.pop_back();
452 0 : ROEdgeVector approaching = myApproachingEdges[last.edge];
453 0 : for (ROEdgeVector::const_iterator j = approaching.begin(); j != approaching.end(); ++j) {
454 0 : if (hasDetector(*j)) {
455 0 : previous.push_back(*j);
456 : } else {
457 0 : ie.depth = last.depth + 1;
458 0 : ie.edge = *j;
459 0 : missing.push_back(ie);
460 0 : if (ie.depth > 5) {
461 : maxDepthReached = true;
462 : }
463 : }
464 : }
465 0 : }
466 0 : if (maxDepthReached) {
467 0 : WRITE_WARNING(TL(" Could not build list of previous flows."));
468 : }
469 0 : }
470 : // Edges with previous detectors are now in "previous";
471 : // compute following
472 : ROEdgeVector latter;
473 : {
474 : std::vector<IterationEdge> missing;
475 0 : for (ROEdgeVector::const_iterator k = previous.begin(); k != previous.end(); ++k) {
476 : IterationEdge ie;
477 0 : ie.depth = 0;
478 0 : ie.edge = *k;
479 0 : missing.push_back(ie);
480 : }
481 : bool maxDepthReached = false;
482 0 : while (!missing.empty() && !maxDepthReached) {
483 0 : IterationEdge last = missing.back();
484 : missing.pop_back();
485 0 : ROEdgeVector approached = myApproachedEdges[last.edge];
486 0 : for (ROEdgeVector::const_iterator j = approached.begin(); j != approached.end(); ++j) {
487 0 : if (*j == getDetectorEdge(*detector)) {
488 0 : continue;
489 : }
490 0 : if (hasDetector(*j)) {
491 0 : latter.push_back(*j);
492 : } else {
493 : IterationEdge ie;
494 0 : ie.depth = last.depth + 1;
495 0 : ie.edge = *j;
496 0 : missing.push_back(ie);
497 0 : if (ie.depth > 5) {
498 : maxDepthReached = true;
499 : }
500 : }
501 : }
502 0 : }
503 0 : if (maxDepthReached) {
504 0 : WRITE_WARNING(TL(" Could not build list of latter flows."));
505 : return;
506 : }
507 0 : }
508 : // Edges with latter detectors are now in "latter";
509 :
510 : // lets not validate them by now - surely this should be done
511 : // for each time step: collect incoming flows; collect outgoing;
512 : std::vector<FlowDef> mflows;
513 : int index = 0;
514 0 : for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
515 : // collect incoming
516 : FlowDef inFlow;
517 : inFlow.qLKW = 0;
518 : inFlow.qPKW = 0;
519 : inFlow.vLKW = 0;
520 : inFlow.vPKW = 0;
521 : // !! time difference is missing
522 0 : for (const ROEdge* const e : previous) {
523 0 : const std::vector<FlowDef>& eflows = static_cast<const RODFEdge*>(e)->getFlows();
524 0 : if (eflows.size() != 0) {
525 0 : const FlowDef& srcFD = eflows[index];
526 0 : inFlow.qLKW += srcFD.qLKW;
527 0 : inFlow.qPKW += srcFD.qPKW;
528 0 : inFlow.vLKW += srcFD.vLKW;
529 0 : inFlow.vPKW += srcFD.vPKW;
530 : }
531 : }
532 0 : inFlow.vLKW /= (double) previous.size();
533 0 : inFlow.vPKW /= (double) previous.size();
534 : // collect outgoing
535 : FlowDef outFlow;
536 : outFlow.qLKW = 0;
537 : outFlow.qPKW = 0;
538 : outFlow.vLKW = 0;
539 : outFlow.vPKW = 0;
540 : // !! time difference is missing
541 0 : for (const ROEdge* const e : latter) {
542 0 : const std::vector<FlowDef>& eflows = static_cast<const RODFEdge*>(e)->getFlows();
543 0 : if (eflows.size() != 0) {
544 0 : const FlowDef& srcFD = eflows[index];
545 0 : outFlow.qLKW += srcFD.qLKW;
546 0 : outFlow.qPKW += srcFD.qPKW;
547 0 : outFlow.vLKW += srcFD.vLKW;
548 0 : outFlow.vPKW += srcFD.vPKW;
549 : }
550 : }
551 0 : outFlow.vLKW /= (double) latter.size();
552 0 : outFlow.vPKW /= (double) latter.size();
553 : //
554 : FlowDef mFlow;
555 0 : mFlow.qLKW = inFlow.qLKW - outFlow.qLKW;
556 0 : mFlow.qPKW = inFlow.qPKW - outFlow.qPKW;
557 0 : mFlow.vLKW = (inFlow.vLKW + outFlow.vLKW) / (double) 2.;
558 0 : mFlow.vPKW = (inFlow.vPKW + outFlow.vPKW) / (double) 2.;
559 0 : mflows.push_back(mFlow);
560 : }
561 0 : static_cast<RODFEdge*>(getDetectorEdge(*detector))->setFlows(mflows);
562 0 : flows.setFlows(detector->getID(), mflows);
563 0 : }
564 :
565 :
566 : void
567 0 : RODFNet::revalidateFlows(const RODFDetectorCon& detectors,
568 : RODFDetectorFlows& flows,
569 : SUMOTime startTime, SUMOTime endTime,
570 : SUMOTime stepOffset) {
571 0 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
572 0 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
573 : // check whether there is at least one entry with a flow larger than zero
574 0 : revalidateFlows(*i, flows, startTime, endTime, stepOffset);
575 : }
576 0 : }
577 :
578 :
579 :
580 : void
581 7 : RODFNet::removeEmptyDetectors(RODFDetectorCon& detectors,
582 : RODFDetectorFlows& flows) {
583 7 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
584 106 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end();) {
585 : bool remove = true;
586 : // check whether there is at least one entry with a flow larger than zero
587 99 : if (flows.knows((*i)->getID())) {
588 : remove = false;
589 : }
590 : if (remove) {
591 21 : WRITE_MESSAGEF(TL("Removed detector '%' because no flows for him exist."), (*i)->getID());
592 7 : flows.removeFlow((*i)->getID());
593 7 : detectors.removeDetector((*i)->getID());
594 : i = dets.begin();
595 : } else {
596 : i++;
597 : }
598 : }
599 7 : }
600 :
601 :
602 :
603 : void
604 7 : RODFNet::reportEmptyDetectors(RODFDetectorCon& detectors,
605 : RODFDetectorFlows& flows) {
606 7 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
607 70 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
608 : bool remove = true;
609 : // check whether there is at least one entry with a flow larger than zero
610 63 : if (flows.knows((*i)->getID())) {
611 : remove = false;
612 : }
613 : if (remove) {
614 21 : WRITE_MESSAGEF(TL("Detector '%' has no flow."), (*i)->getID());
615 : }
616 : }
617 7 : }
618 :
619 :
620 :
621 : ROEdge*
622 27265 : RODFNet::getDetectorEdge(const RODFDetector& det) const {
623 54530 : const std::string edgeName = SUMOXMLDefinitions::getEdgeIDFromLane(det.getLaneID());
624 : ROEdge* ret = getEdge(edgeName);
625 27265 : if (ret == nullptr) {
626 0 : throw ProcessError("Edge '" + edgeName + "' used by detector '" + det.getID() + "' is not known.");
627 : }
628 27265 : return ret;
629 : }
630 :
631 :
632 : bool
633 3407 : RODFNet::hasApproaching(ROEdge* edge) const {
634 : return myApproachingEdges.find(edge) != myApproachingEdges.end()
635 6099 : && myApproachingEdges.find(edge)->second.size() != 0;
636 : }
637 :
638 :
639 : bool
640 8195 : RODFNet::hasApproached(ROEdge* edge) const {
641 : return myApproachedEdges.find(edge) != myApproachedEdges.end()
642 15493 : && myApproachedEdges.find(edge)->second.size() != 0;
643 : }
644 :
645 :
646 : bool
647 1472550 : RODFNet::hasDetector(ROEdge* edge) const {
648 : return myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
649 1472550 : && myDetectorsOnEdges.find(edge)->second.size() != 0;
650 : }
651 :
652 :
653 : const std::vector<std::string>&
654 0 : RODFNet::getDetectorList(ROEdge* edge) const {
655 0 : return myDetectorsOnEdges.find(edge)->second;
656 : }
657 :
658 :
659 : double
660 0 : RODFNet::getAbsPos(const RODFDetector& det) const {
661 1680 : if (det.getPos() >= 0) {
662 : return det.getPos();
663 : }
664 1236 : return getDetectorEdge(det)->getLength() + det.getPos();
665 : }
666 :
667 : bool
668 1368 : RODFNet::isSource(const RODFDetector& det, const RODFDetectorCon& detectors,
669 : bool strict) const {
670 : ROEdgeVector seen;
671 2736 : return isSource(det, getDetectorEdge(det), seen, detectors, strict);
672 1368 : }
673 :
674 : bool
675 289 : RODFNet::isFalseSource(const RODFDetector& det, const RODFDetectorCon& detectors) const {
676 : ROEdgeVector seen;
677 578 : return isFalseSource(det, getDetectorEdge(det), seen, detectors);
678 289 : }
679 :
680 : bool
681 1368 : RODFNet::isDestination(const RODFDetector& det, const RODFDetectorCon& detectors) const {
682 : ROEdgeVector seen;
683 2736 : return isDestination(det, getDetectorEdge(det), seen, detectors);
684 1368 : }
685 :
686 :
687 : bool
688 3457 : RODFNet::isSource(const RODFDetector& det, ROEdge* edge,
689 : ROEdgeVector& seen,
690 : const RODFDetectorCon& detectors,
691 : bool strict) const {
692 3457 : if (seen.size() == 1000) { // !!!
693 0 : WRITE_WARNINGF(TL("Quitting checking for being a source for detector '%' due to seen edge limit."), det.getID());
694 0 : return false;
695 : }
696 3457 : if (edge == getDetectorEdge(det)) {
697 : // maybe there is another detector at the same edge
698 : // get the list of this/these detector(s)
699 : const std::vector<std::string>& detsOnEdge = myDetectorsOnEdges.find(edge)->second;
700 3210 : for (std::vector<std::string>::const_iterator i = detsOnEdge.begin(); i != detsOnEdge.end(); ++i) {
701 1892 : if ((*i) == det.getID()) {
702 1352 : continue;
703 : }
704 540 : const RODFDetector& sec = detectors.getDetector(*i);
705 540 : if (getAbsPos(sec) < getAbsPos(det)) {
706 : // ok, there is another detector on the same edge and it is
707 : // before this one -> no source
708 : return false;
709 : }
710 : }
711 : }
712 : // it's a source if no edges are approaching the edge
713 3407 : if (!hasApproaching(edge)) {
714 715 : if (edge != getDetectorEdge(det)) {
715 543 : if (hasDetector(edge)) {
716 : return false;
717 : }
718 : }
719 : return true;
720 : }
721 2692 : if (edge != getDetectorEdge(det)) {
722 : // ok, we are at one of the edges in front
723 1546 : if (myAmInHighwayMode) {
724 0 : if (edge->getSpeedLimit() >= 19.4) {
725 0 : if (hasDetector(edge)) {
726 : // we are still on the highway and there is another detector
727 : return false;
728 : }
729 : // the next is a hack for the A100 scenario...
730 : // We have to look into further edges herein edges
731 : const ROEdgeVector& appr = myApproachingEdges.find(edge)->second;
732 : int noFalse = 0;
733 : int noSkipped = 0;
734 0 : for (int i = 0; i < (int)appr.size(); i++) {
735 0 : if (hasDetector(appr[i])) {
736 0 : noFalse++;
737 : }
738 : }
739 0 : if (noFalse + noSkipped == (int)appr.size()) {
740 : return false;
741 : }
742 : }
743 : }
744 : }
745 :
746 2692 : if (myAmInHighwayMode) {
747 0 : if (edge->getSpeedLimit() < 19.4 && edge != getDetectorEdge(det)) {
748 : // we have left the highway already
749 : // -> the detector will be a highway source
750 0 : if (!hasDetector(edge)) {
751 : return true;
752 : }
753 : }
754 : }
755 : if (myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
756 2692 : &&
757 2230 : myDetectorEdges.find(det.getID())->second != edge) {
758 : return false;
759 : }
760 :
761 : // let's check the edges in front
762 : const ROEdgeVector& appr = myApproachingEdges.find(edge)->second;
763 : int numOk = 0;
764 : int numFalse = 0;
765 : int numSkipped = 0;
766 1608 : seen.push_back(edge);
767 3808 : for (int i = 0; i < (int)appr.size(); i++) {
768 2200 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
769 2200 : if (!had) {
770 2089 : if (isSource(det, appr[i], seen, detectors, strict)) {
771 346 : numOk++;
772 : } else {
773 1743 : numFalse++;
774 : }
775 : } else {
776 111 : numSkipped++;
777 : }
778 : }
779 1608 : if (strict) {
780 0 : return numOk + numSkipped == (int)appr.size();
781 : }
782 1608 : return numFalse + numSkipped != (int)appr.size();
783 : }
784 :
785 :
786 : bool
787 2821 : RODFNet::isDestination(const RODFDetector& det, ROEdge* edge, ROEdgeVector& seen,
788 : const RODFDetectorCon& detectors) const {
789 2821 : if (seen.size() == 1000) { // !!!
790 0 : WRITE_WARNINGF(TL("Quitting checking for being a destination for detector '%' due to seen edge limit."), det.getID());
791 0 : return false;
792 : }
793 2821 : if (edge == getDetectorEdge(det)) {
794 : // maybe there is another detector at the same edge
795 : // get the list of this/these detector(s)
796 : const std::vector<std::string>& detsOnEdge = myDetectorsOnEdges.find(edge)->second;
797 3174 : for (std::vector<std::string>::const_iterator i = detsOnEdge.begin(); i != detsOnEdge.end(); ++i) {
798 1856 : if ((*i) == det.getID()) {
799 1334 : continue;
800 : }
801 522 : const RODFDetector& sec = detectors.getDetector(*i);
802 522 : if (getAbsPos(sec) > getAbsPos(det)) {
803 : // ok, there is another detector on the same edge and it is
804 : // after this one -> no destination
805 : return false;
806 : }
807 : }
808 : }
809 2771 : if (!hasApproached(edge)) {
810 314 : if (edge != getDetectorEdge(det)) {
811 261 : if (hasDetector(edge)) {
812 : return false;
813 : }
814 : }
815 : return true;
816 : }
817 2457 : if (edge != getDetectorEdge(det)) {
818 : // ok, we are at one of the edges coming behind
819 1192 : if (myAmInHighwayMode) {
820 0 : if (edge->getSpeedLimit() >= 19.4) {
821 0 : if (hasDetector(edge)) {
822 : // we are still on the highway and there is another detector
823 : return false;
824 : }
825 : }
826 : }
827 : }
828 :
829 2457 : if (myAmInHighwayMode) {
830 0 : if (edge->getSpeedLimit() < 19.4 && edge != getDetectorEdge(det)) {
831 0 : if (hasDetector(edge)) {
832 : return true;
833 : }
834 0 : if (myApproachedEdges.find(edge)->second.size() > 1) {
835 : return true;
836 : }
837 :
838 : }
839 : }
840 :
841 : if (myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
842 2457 : &&
843 2298 : myDetectorEdges.find(det.getID())->second != edge) {
844 : return false;
845 : }
846 : const ROEdgeVector& appr = myApproachedEdges.find(edge)->second;
847 : bool isall = true;
848 1424 : seen.push_back(edge);
849 2878 : for (int i = 0; i < (int)appr.size() && isall; i++) {
850 1454 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
851 1454 : if (!had) {
852 1453 : if (!isDestination(det, appr[i], seen, detectors)) {
853 : isall = false;
854 : }
855 : }
856 : }
857 : return isall;
858 : }
859 :
860 : bool
861 1315 : RODFNet::isFalseSource(const RODFDetector& det, ROEdge* edge, ROEdgeVector& seen,
862 : const RODFDetectorCon& detectors) const {
863 1315 : if (seen.size() == 1000) { // !!!
864 0 : WRITE_WARNINGF(TL("Quitting checking for being a false source for detector '%' due to seen edge limit."), det.getID());
865 0 : return false;
866 : }
867 1315 : seen.push_back(edge);
868 1315 : if (edge != getDetectorEdge(det)) {
869 : // ok, we are at one of the edges coming behind
870 1026 : if (hasDetector(edge)) {
871 : const std::vector<std::string>& dets = myDetectorsOnEdges.find(edge)->second;
872 602 : for (std::vector<std::string>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
873 602 : if (detectors.getDetector(*i).getType() == SINK_DETECTOR) {
874 : return false;
875 : }
876 448 : if (detectors.getDetector(*i).getType() == BETWEEN_DETECTOR) {
877 : return false;
878 : }
879 18 : if (detectors.getDetector(*i).getType() == SOURCE_DETECTOR) {
880 : return true;
881 : }
882 : }
883 : } else {
884 424 : if (myAmInHighwayMode && edge->getSpeedLimit() < 19.) {
885 : return false;
886 : }
887 : }
888 : }
889 :
890 713 : if (myApproachedEdges.find(edge) == myApproachedEdges.end()) {
891 : return false;
892 : }
893 :
894 : const ROEdgeVector& appr = myApproachedEdges.find(edge)->second;
895 : bool isall = false;
896 1783 : for (int i = 0; i < (int)appr.size() && !isall; i++) {
897 : //printf("checking %s->\n", appr[i].c_str());
898 1118 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
899 1118 : if (!had) {
900 1026 : if (isFalseSource(det, appr[i], seen, detectors)) {
901 : isall = true;
902 : }
903 : }
904 : }
905 : return isall;
906 : }
907 :
908 :
909 : void
910 104 : RODFNet::buildEdgeFlowMap(const RODFDetectorFlows& flows,
911 : const RODFDetectorCon& detectors,
912 : SUMOTime startTime, SUMOTime endTime,
913 : SUMOTime stepOffset) {
914 : std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
915 : double speedFactorSumPKW = 0;
916 : double speedFactorSumLKW = 0;
917 : double speedFactorCountPKW = 0;
918 : double speedFactorCountLKW = 0;
919 1006 : for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
920 902 : ROEdge* into = (*i).first;
921 902 : const double maxSpeedPKW = into->getVClassMaxSpeed(SVC_PASSENGER);
922 902 : const double maxSpeedLKW = into->getVClassMaxSpeed(SVC_TRUCK);
923 :
924 : const std::vector<std::string>& dets = (*i).second;
925 : std::map<double, std::vector<std::string> > cliques;
926 : std::vector<std::string>* maxClique = nullptr;
927 1955 : for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
928 1053 : if (!flows.knows(*j)) {
929 154 : continue;
930 : }
931 899 : const RODFDetector& det = detectors.getDetector(*j);
932 : bool found = false;
933 899 : for (auto& k : cliques) {
934 82 : if (fabs(k.first - det.getPos()) < 1) {
935 82 : k.second.push_back(*j);
936 82 : if (maxClique == nullptr || k.second.size() > maxClique->size()) {
937 : maxClique = &k.second;
938 : }
939 : found = true;
940 : break;
941 : }
942 : }
943 899 : if (!found) {
944 817 : cliques[det.getPos()].push_back(*j);
945 817 : maxClique = &cliques[det.getPos()];
946 : }
947 : }
948 902 : if (maxClique == nullptr) {
949 : continue;
950 : }
951 : std::vector<FlowDef> mflows; // !!! reserve
952 310610 : for (SUMOTime t = startTime; t < endTime; t += stepOffset) {
953 : FlowDef fd;
954 309793 : fd.qPKW = 0;
955 309793 : fd.qLKW = 0;
956 309793 : fd.vLKW = 0;
957 309793 : fd.vPKW = 0;
958 309793 : fd.fLKW = 0;
959 309793 : fd.isLKW = 0;
960 309793 : mflows.push_back(fd);
961 : }
962 1716 : for (std::vector<std::string>::iterator l = maxClique->begin(); l != maxClique->end(); ++l) {
963 : bool didWarn = false;
964 899 : const std::vector<FlowDef>& dflows = flows.getFlowDefs(*l);
965 : int index = 0;
966 402872 : for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
967 401973 : const FlowDef& srcFD = dflows[index];
968 : FlowDef& fd = mflows[index];
969 401973 : fd.qPKW += srcFD.qPKW;
970 401973 : fd.qLKW += srcFD.qLKW;
971 401973 : fd.vLKW += srcFD.vLKW / (double) maxClique->size();
972 401973 : fd.vPKW += srcFD.vPKW / (double) maxClique->size();
973 401973 : fd.fLKW += srcFD.fLKW / (double) maxClique->size();
974 401973 : fd.isLKW += srcFD.isLKW / (double) maxClique->size();
975 401973 : const double speedFactorPKW = srcFD.vPKW / 3.6 / maxSpeedPKW;
976 401973 : const double speedFactorLKW = srcFD.vLKW / 3.6 / maxSpeedLKW;
977 401973 : myMaxSpeedFactorPKW = MAX2(myMaxSpeedFactorPKW, speedFactorPKW);
978 401973 : myMaxSpeedFactorLKW = MAX2(myMaxSpeedFactorLKW, speedFactorLKW);
979 401973 : speedFactorCountPKW += srcFD.qPKW;
980 401973 : speedFactorCountLKW += srcFD.qLKW;
981 401973 : speedFactorSumPKW += srcFD.qPKW * speedFactorPKW;
982 401973 : speedFactorSumLKW += srcFD.qLKW * speedFactorLKW;
983 401973 : if (!didWarn && srcFD.vPKW > 0 && srcFD.vPKW < 255 && srcFD.vPKW / 3.6 > into->getSpeedLimit()) {
984 3012 : WRITE_MESSAGE("Detected PKW speed (" + toString(srcFD.vPKW / 3.6, 3) + ") higher than allowed speed (" + toString(into->getSpeedLimit(), 3) + ") at '" + (*l) + "' on edge '" + into->getID() + "'.");
985 : didWarn = true;
986 : }
987 401220 : if (!didWarn && srcFD.vLKW > 0 && srcFD.vLKW < 255 && srcFD.vLKW / 3.6 > into->getSpeedLimit()) {
988 32 : WRITE_MESSAGE("Detected LKW speed (" + toString(srcFD.vLKW / 3.6, 3) + ") higher than allowed speed (" + toString(into->getSpeedLimit(), 3) + ") at '" + (*l) + "' on edge '" + into->getID() + "'.");
989 : didWarn = true;
990 : }
991 : }
992 : }
993 817 : static_cast<RODFEdge*>(into)->setFlows(mflows);
994 817 : }
995 : // @note: this assumes that the speedFactors are independent of location and time
996 104 : if (speedFactorCountPKW > 0) {
997 99 : myAvgSpeedFactorPKW = speedFactorSumPKW / speedFactorCountPKW;
998 198 : WRITE_MESSAGEF(TL("Average speedFactor for PKW is % maximum speedFactor is %."), toString(myAvgSpeedFactorPKW), toString(myMaxSpeedFactorPKW));
999 : }
1000 104 : if (speedFactorCountLKW > 0) {
1001 25 : myAvgSpeedFactorLKW = speedFactorSumLKW / speedFactorCountLKW;
1002 50 : WRITE_MESSAGEF(TL("Average speedFactor for LKW is % maximum speedFactor is %."), toString(myAvgSpeedFactorLKW), toString(myMaxSpeedFactorLKW));
1003 : }
1004 :
1005 104 : }
1006 :
1007 :
1008 : void
1009 0 : RODFNet::buildDetectorDependencies(RODFDetectorCon& detectors) {
1010 : // !!! this will not work when several detectors are lying on the same edge on different positions
1011 :
1012 :
1013 0 : buildDetectorEdgeDependencies(detectors);
1014 : // for each detector, compute the lists of predecessor and following detectors
1015 : std::map<std::string, ROEdge*>::const_iterator i;
1016 0 : for (i = myDetectorEdges.begin(); i != myDetectorEdges.end(); ++i) {
1017 0 : const RODFDetector& det = detectors.getDetector((*i).first);
1018 0 : if (!det.hasRoutes()) {
1019 0 : continue;
1020 : }
1021 : // mark current detectors
1022 : std::vector<RODFDetector*> last;
1023 : {
1024 0 : const std::vector<std::string>& detNames = myDetectorsOnEdges.find((*i).second)->second;
1025 0 : for (std::vector<std::string>::const_iterator j = detNames.begin(); j != detNames.end(); ++j) {
1026 0 : last.push_back(&detectors.getModifiableDetector(*j));
1027 : }
1028 : }
1029 : // iterate over the current detector's routes
1030 0 : const std::vector<RODFRouteDesc>& routes = det.getRouteVector();
1031 0 : for (std::vector<RODFRouteDesc>::const_iterator j = routes.begin(); j != routes.end(); ++j) {
1032 : const ROEdgeVector& edges2Pass = (*j).edges2Pass;
1033 0 : for (ROEdgeVector::const_iterator k = edges2Pass.begin() + 1; k != edges2Pass.end(); ++k) {
1034 0 : if (myDetectorsOnEdges.find(*k) != myDetectorsOnEdges.end()) {
1035 : const std::vector<std::string>& detNames = myDetectorsOnEdges.find(*k)->second;
1036 : // ok, consecutive detector found
1037 0 : for (std::vector<RODFDetector*>::iterator l = last.begin(); l != last.end(); ++l) {
1038 : // mark as follower of current
1039 0 : for (std::vector<std::string>::const_iterator m = detNames.begin(); m != detNames.end(); ++m) {
1040 0 : detectors.getModifiableDetector(*m).addPriorDetector(*l);
1041 0 : (*l)->addFollowingDetector(&detectors.getDetector(*m));
1042 : }
1043 : }
1044 : last.clear();
1045 0 : for (std::vector<std::string>::const_iterator m = detNames.begin(); m != detNames.end(); ++m) {
1046 0 : last.push_back(&detectors.getModifiableDetector(*m));
1047 : }
1048 : }
1049 : }
1050 : }
1051 0 : }
1052 0 : }
1053 :
1054 :
1055 : void
1056 0 : RODFNet::mesoJoin(RODFDetectorCon& detectors, RODFDetectorFlows& flows) {
1057 0 : buildDetectorEdgeDependencies(detectors);
1058 : std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
1059 0 : for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
1060 : const std::vector<std::string>& dets = (*i).second;
1061 : std::map<double, std::vector<std::string> > cliques;
1062 : // compute detector cliques
1063 0 : for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
1064 0 : const RODFDetector& det = detectors.getDetector(*j);
1065 : bool found = false;
1066 0 : for (std::map<double, std::vector<std::string> >::iterator k = cliques.begin(); !found && k != cliques.end(); ++k) {
1067 0 : if (fabs((*k).first - det.getPos()) < 10.) {
1068 0 : (*k).second.push_back(*j);
1069 : found = true;
1070 : }
1071 : }
1072 0 : if (!found) {
1073 0 : cliques[det.getPos()] = std::vector<std::string>();
1074 0 : cliques[det.getPos()].push_back(*j);
1075 : }
1076 : }
1077 : // join detector cliques
1078 0 : for (std::map<double, std::vector<std::string> >::iterator m = cliques.begin(); m != cliques.end(); ++m) {
1079 0 : std::vector<std::string> clique = (*m).second;
1080 : // do not join if only one
1081 0 : if (clique.size() == 1) {
1082 : continue;
1083 : }
1084 : std::string nid;
1085 0 : for (std::vector<std::string>::iterator n = clique.begin(); n != clique.end(); ++n) {
1086 0 : std::cout << *n << " ";
1087 0 : if (n != clique.begin()) {
1088 0 : nid = nid + "_";
1089 : }
1090 0 : nid = nid + *n;
1091 : }
1092 : std::cout << ":" << nid << std::endl;
1093 0 : flows.mesoJoin(nid, (*m).second);
1094 0 : detectors.mesoJoin(nid, (*m).second);
1095 0 : }
1096 : }
1097 0 : }
1098 :
1099 :
1100 : /****************************************************************************/
|