21 package org.matsim.withinday.trafficmonitoring;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
30 import java.util.Queue;
32 import java.util.TreeMap;
33 import java.util.concurrent.BrokenBarrierException;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.CyclicBarrier;
37 import jakarta.inject.Inject;
38 import jakarta.inject.Singleton;
40 import org.apache.logging.log4j.LogManager;
41 import org.apache.logging.log4j.Logger;
124 private double now = Double.NEGATIVE_INFINITY ;
128 this(scenario, null);
141 if (analyzedModes == null || analyzedModes.size() == 0) {
142 this.filterModes =
false;
143 this.analyzedModes = null;
153 this.regularActiveTrips =
new HashMap<>();
154 this.travelTimeInfos =
new ConcurrentHashMap<>();
155 this.changedLinksByTime =
new TreeMap<>();
156 this.vehiclesToFilter =
new HashSet<>();
160 TravelTimeInfo travelTimeInfo =
new TravelTimeInfo();
161 this.travelTimeInfos.put(link.getId(), travelTimeInfo);
190 if (networkChangeEvents != null) {
199 if (freespeedChange != null) {
201 Map<Link,Double> newLinkSpeedsAtThisTime = changedLinksByTime.computeIfAbsent(startTime, k ->
new HashMap<>());
205 switch ( freespeedChange.
getType() ) {
206 case ABSOLUTE_IN_SI_UNITS:
207 newSpeed = freespeedChange.
getValue() ;
210 newSpeed = link.getFreespeed() * freespeedChange.
getValue() ;
212 case OFFSET_IN_SI_UNITS:
213 newSpeed = link.getFreespeed() + freespeedChange.
getValue() ;
218 if ( startTime > 0. ) {
219 log.debug(
"registering a change event for time=" + startTime
220 +
"; linkId=" + link.getId() ) ;
222 newLinkSpeedsAtThisTime.put( link, newSpeed ) ;
233 final double travelTime = this.travelTimeInfoProvider.
getTravelTimeInfo(link).travelTime;
243 throw new RuntimeException(
"using WithinDayTravelTime, but mobsim notifications not called between two resets. " 244 +
"Did you really add this as a mobsim listener?") ;
255 if (filterModes && vehiclesToFilter.contains(event.
getVehicleId()))
return;
258 double time =
event.getTime();
261 tripBin.enterTime = time;
263 this.regularActiveTrips.put(vehicleId, tripBin);
268 Id<Link> linkId =
event.getLinkId();
270 double time =
event.getTime();
272 TripBin tripBin = this.regularActiveTrips.remove(vehicleId);
273 if (tripBin != null) {
274 tripBin.leaveTime = time;
276 double tripTime = tripBin.leaveTime - tripBin.enterTime;
278 TravelTimeInfo travelTimeInfo = this.travelTimeInfoProvider.
getTravelTimeInfo(linkId);
279 travelTimeInfo.tripBins.add(tripBin);
280 travelTimeInfo.addedTravelTimes += tripTime;
281 travelTimeInfo.addedTrips++;
283 travelTimeInfo.checkActiveState();
284 travelTimeInfo.checkBinSize(tripTime);
306 this.regularActiveTrips.remove(vehicleId);
309 if (filterModes) this.vehiclesToFilter.remove(event.
getVehicleId());
329 if (e.getQueueSimulation() instanceof
QSim) {
330 double simStartTime = ((
QSim) e.getQueueSimulation()).getSimTimer().getSimStartTime();
336 this.nextInfoTime = (int)(Math.floor(simStartTime /
this.infoTimeStep) * this.
infoTimeStep);
341 double freeSpeedTravelTime = link.getLength() / link.getFreespeed();
343 TravelTimeInfo travelTimeInfo = this.travelTimeInfoProvider.
getTravelTimeInfo(link);
344 travelTimeInfo.travelTime = freeSpeedTravelTime;
345 travelTimeInfo.init(freeSpeedTravelTime);
365 while( !changedLinksByTime.isEmpty() && changedLinksByTime.firstKey() <= e.
getSimulationTime() ) {
366 Map<Link, Double> map = changedLinksByTime.pollFirstEntry().getValue();
367 for ( Map.Entry<
Link,Double> link2speed : map.entrySet() ) {
368 Link link = link2speed.getKey() ;
369 double freeSpeedTravelTime = link.
getLength() / link2speed.getValue() ;
373 "; network change event for link=" + link.
getId() +
374 "; new ttime="+ freeSpeedTravelTime );
376 TravelTimeInfo travelTimeInfo = this.travelTimeInfoProvider.
getTravelTimeInfo(link);
377 travelTimeInfo.init(freeSpeedTravelTime);
378 travelTimeInfo.checkActiveState();
429 this.startBarrier.await();
430 }
catch (InterruptedException | BrokenBarrierException ex) {
436 if (time >= this.nextInfoTime) {
439 activeLinks += runnable.getActiveLinksCount();
442 log.info(
"WithinDayTravelTime at " +
Time.
writeTime(time) +
" #links=" + activeLinks);
453 static class TravelTimeInfo {
456 List<TripBin> tripBins =
new ArrayList<>();
458 boolean isActive =
false;
461 double addedTravelTimes = 0.0;
462 double sumTravelTimes = 0.0;
464 double freeSpeedTravelTime = Double.MAX_VALUE;
465 double travelTime = Double.MAX_VALUE;
467 double dynamicBinSize = 0.0;
469 static Counter enlarge =
new Counter(
"WithinDayTravelTime: enlarged time bin size: ");
470 static Counter shrink =
new Counter(
"WithinDayTravelTime: shrunk time bin size: ");
472 void init(
double freeSpeedTravelTime) {
473 this.freeSpeedTravelTime = freeSpeedTravelTime;
474 this.dynamicBinSize = freeSpeedTravelTime * 2.5;
477 void checkActiveState() {
479 this.isActive =
true;
484 void checkBinSize(
double tripTime) {
485 if (tripTime > dynamicBinSize) {
486 dynamicBinSize = tripTime * 2;
488 }
else if (tripTime * 3 < dynamicBinSize) {
489 dynamicBinSize = tripTime * 3;
509 private void run(
double time) {
514 updateMeanTravelTimesRunnable.setTime(time);
517 this.startBarrier.await();
519 this.endBarrier.await();
520 }
catch (InterruptedException | BrokenBarrierException e) {
527 this.startBarrier =
new CyclicBarrier(numOfThreads + 1);
528 this.endBarrier =
new CyclicBarrier(numOfThreads + 1);
537 updateMeanTravelTimesRunnable.
setEndBarrier(this.endBarrier);
538 updateMeanTravelTimesRunnables[i] = updateMeanTravelTimesRunnable;
540 Thread thread =
new Thread(updateMeanTravelTimesRunnable);
541 thread.setName(
"UpdateMeanTravelTimes" + i);
542 thread.setDaemon(
true);
552 for (TravelTimeInfo travelTimeInfo : this.travelTimeInfos.values()) {
553 travelTimeInfo.runnable = updateMeanTravelTimesRunnables[roundRobin %
numOfThreads];
563 this.endBarrier.await();
564 }
catch (InterruptedException | BrokenBarrierException e) {
574 private volatile boolean simulationRunning =
true;
576 private CyclicBarrier startBarrier = null;
577 private CyclicBarrier endBarrier = null;
583 activeTravelTimeInfos =
new ArrayList<>();
587 this.startBarrier = cyclicBarrier;
591 this.endBarrier = cyclicBarrier;
599 this.activeTravelTimeInfos.add(travelTimeInfo);
603 return this.activeTravelTimeInfos.size();
607 this.simulationRunning =
false;
626 startBarrier.await();
632 if (!simulationRunning) {
637 Iterator<TravelTimeInfo> iter = activeTravelTimeInfos.iterator();
638 while (iter.hasNext()) {
639 TravelTimeInfo travelTimeInfo = iter.next();
640 calcBinTravelTime(this.time.
seconds(), travelTimeInfo);
647 if (travelTimeInfo.tripBins.size() == 0) {
648 travelTimeInfo.isActive =
false;
649 travelTimeInfo.travelTime = travelTimeInfo.freeSpeedTravelTime;
654 }
catch (InterruptedException | BrokenBarrierException e) {
661 double removedTravelTimes = 0.0;
663 List<TripBin> tripBins = travelTimeInfo.tripBins;
666 Iterator<TripBin> iter = tripBins.iterator();
667 while (iter.hasNext()) {
669 if (tripBin.leaveTime + travelTimeInfo.dynamicBinSize < time) {
670 double travelTime = tripBin.leaveTime - tripBin.enterTime;
671 removedTravelTimes += travelTime;
686 travelTimeInfo.sumTravelTimes = travelTimeInfo.sumTravelTimes - removedTravelTimes + travelTimeInfo.addedTravelTimes;
688 travelTimeInfo.addedTravelTimes = 0.0;
692 double meanTravelTime = travelTimeInfo.freeSpeedTravelTime;
693 if (!tripBins.isEmpty()) meanTravelTime = travelTimeInfo.sumTravelTimes / tripBins.size();
695 if (meanTravelTime < travelTimeInfo.freeSpeedTravelTime) {
698 travelTimeInfo.travelTime = travelTimeInfo.freeSpeedTravelTime;
700 travelTimeInfo.travelTime = meanTravelTime;
void handleEvent(VehicleEntersTrafficEvent event)
CyclicBarrier startBarrier
void reset(int iteration)
Map< Id< Vehicle >, TripBin > regularActiveTrips
TravelTimeInfo getTravelTimeInfo(final Id< Link > linkId)
WithinDayTravelTime(Scenario scenario, Set< String > analyzedModes)
void handleEvent(VehicleLeavesTrafficEvent event)
void setEndBarrier(CyclicBarrier cyclicBarrier)
Set< Id< Vehicle > > vehiclesToFilter
UpdateMeanTravelTimesRunnable [] updateMeanTravelTimesRunnables
void printInfo(double time)
final Set< String > analyzedModes
final void addNetworkChangeEvent(NetworkChangeEvent networkChangeEvent)
int getActiveLinksCount()
void addNetworkChangeEventToLocalDataStructure(NetworkChangeEvent networkChangeEvent)
static Queue< NetworkChangeEvent > getNetworkChangeEvents(Network network)
Id< Vehicle > getVehicleId()
void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent e)
double getSimulationTime()
final boolean filterModes
Id< Vehicle > getVehicleId()
UpdateMeanTravelTimesRunnable()
Map< Id< Link >, TravelTimeInfo > travelTimeInfos
void handleEvent(LinkLeaveEvent event)
void notifyMobsimBeforeCleanup(MobsimBeforeCleanupEvent e)
void initParallelThreads()
static final String writeTime(final double seconds, final String timeformat)
static OptionalTime defined(double seconds)
Map< Id< Link >, ? extends Link > getLinks()
void handleEvent(PersonStuckEvent event)
void addTravelTimeInfo(TravelTimeInfo travelTimeInfo)
double getSimulationTime()
void notifyMobsimAfterSimStep(MobsimAfterSimStepEvent e)
void notifyMobsimInitialized(MobsimInitializedEvent e)
TravelTimeInfoProvider travelTimeInfoProvider
void setStartBarrier(CyclicBarrier cyclicBarrier)
double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle)
static OptionalTime undefined()
Id< Vehicle > getVehicleId()
Collection< Link > getLinks()
final GlobalConfigGroup global()
Collection< TravelTimeInfo > activeTravelTimeInfos
void calcBinTravelTime(double time, TravelTimeInfo travelTimeInfo)
TreeMap< Double, Map< Link, Double > > changedLinksByTime
void handleEvent(LinkEnterEvent event)
void setTime(final double t)
ChangeValue getFreespeedChange()
static final void printCurrentThreadCpuTime()