Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update MATSim #77

Merged
merged 21 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a1d8abf
Add test inputs
steffenaxer Dec 23, 2023
718d27f
Add test
steffenaxer Dec 23, 2023
be9290b
ev: fix missing drive discharging events due to concurrent access to …
michalmac Dec 27, 2023
c926974
Merge pull request #3016 from matsim-org/edrtDeterminism
michalmac Dec 27, 2023
db13d2c
ev: reduce amount of collected events in DriveDischargingHandler
michalmac Dec 27, 2023
9b6ef87
Merge pull request #3017 from matsim-org/simplify-drive-discharge-han…
michalmac Dec 27, 2023
136b4f1
build(deps): bump log4j.version from 2.22.0 to 2.22.1
dependabot[bot] Dec 27, 2023
edb23db
Merge pull request #3018 from matsim-org/dependabot/maven/log4j.versi…
michalmac Dec 27, 2023
ff36933
ev: do not use iterator for polling from queue
michalmac Dec 27, 2023
03fb135
core: use pattern matching for instanceof in Event.getAttributes()
michalmac Dec 27, 2023
ac39700
core: implement HasVehicleId in VehicleLeavesTrafficEvent
michalmac Dec 27, 2023
47d5d30
core: simplify getAttributes() in core events
michalmac Dec 27, 2023
72ea799
ev: simplify DriveDischargingHandler
michalmac Dec 27, 2023
7e682d9
Merge pull request #3019 from matsim-org/refactor-events-in-ev
michalmac Dec 27, 2023
a821e9f
add maxShiftStartDelay and log message when a shift is deleted due to…
TomE168 Dec 28, 2023
fac46a4
Merge branch 'master' into tekuhlen_fix_shiftRemovalWhenStartTime<Tim…
nkuehnel Dec 28, 2023
dff1441
change name of parameter "maxUnscheduledShiftDelay"
TomE168 Dec 28, 2023
abc9ee9
Merge remote-tracking branch 'origin/tekuhlen_fix_shiftRemovalWhenSta…
TomE168 Dec 28, 2023
e925b42
change comment of parameter "maxUnscheduledShiftDelay"
TomE168 Dec 28, 2023
2196635
change log warning message
TomE168 Dec 28, 2023
f8d7750
Merge pull request #3021 from moia-oss/tekuhlen_fix_shiftRemovalWhenS…
nkuehnel Dec 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.matsim.core.config.ConfigGroup;

import java.net.URL;
import java.util.Map;

/**
* @author nkuehnel / MOIA
Expand All @@ -30,6 +29,10 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter
@Comment("changeover duration in [seconds]")
public double changeoverDuration = 900;

@Parameter
@Comment("maximum delay of shift assignment after start time has passed in [seconds]. If a shift can not be assigned to a vehicle until the planned start of the shift plus the defined max delay, the shift is discarded. Defaults to 0")
public double maxUnscheduledShiftDelay = 0;

@Parameter
@Comment("Time of shift assignment (i.e. which vehicle carries out a specific shift) before start of shift in [seconds]")
public double shiftScheduleLookAhead = 1800;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,13 @@ private void startShifts(double timeStep) {

private void assignShifts(double timeStep) {
// Remove elapsed shifts
unscheduledShifts.removeIf(shift -> shift.getStartTime() < timeStep);
unscheduledShifts.removeIf(shift -> {
if (shift.getStartTime() + drtShiftParams.maxUnscheduledShiftDelay < timeStep ) {
logger.warn("Shift with ID " + shift.getId() + " could not be assigned and is being removed as start time is longer in the past than defined by maxUnscheduledShiftDelay.");
return true;
}
return false;
});

// Assign shifts
Set<DrtShift> assignableShifts = new LinkedHashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,44 @@
package org.matsim.contrib.drt.extension.edrt.run;

import java.net.URL;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.population.Plan;
import org.matsim.api.core.v01.population.Population;
import org.matsim.contrib.drt.extension.edrt.optimizer.EDrtVehicleDataEntryFactory;
import org.matsim.contrib.drt.prebooking.PrebookingParams;
import org.matsim.contrib.drt.prebooking.logic.ProbabilityBasedPrebookingLogic;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.DrtConfigs;
import org.matsim.contrib.drt.run.DrtControlerCreator;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler;
import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent;
import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler;
import org.matsim.contrib.dvrp.passenger.*;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.run.DvrpModule;
import org.matsim.contrib.dvrp.run.DvrpQSimComponents;
import org.matsim.contrib.ev.EvConfigGroup;
import org.matsim.contrib.ev.EvModule;
import org.matsim.contrib.ev.charging.*;
import org.matsim.contrib.ev.discharging.IdleDischargingHandler;
import org.matsim.contrib.ev.temperature.TemperatureService;
import org.matsim.contrib.evrp.EvDvrpFleetQSimModule;
import org.matsim.contrib.evrp.OperatingVehicleProvider;
import org.matsim.contrib.otfvis.OTFVisLiveModule;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.controler.Controler;
import org.matsim.core.mobsim.qsim.AbstractQSimModule;
import org.matsim.core.population.io.PopulationReader;
import org.matsim.core.population.io.PopulationWriter;
import org.matsim.core.router.TripStructureUtils;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.vis.otfvis.OTFVisConfigGroup;
Expand All @@ -51,36 +71,82 @@ void test() {
RunEDrtScenario.run(configUrl, false);
}

@Test
void testMultiModeDrtDeterminism() {
URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_multiModeEdrt_config.xml");

Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(),
new OTFVisConfigGroup(), new EvConfigGroup());


Controler controller = RunEDrtScenario.createControler(config, false);
config.controller().setLastIteration(2);

PassengerPickUpTracker tracker = new PassengerPickUpTracker();
tracker.install(controller);

controller.run();

assertEquals(2011, tracker.passengerPickupEvents);
}


@Test
void testWithPrebooking() {
URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_edrt_config.xml");

Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(),
new OTFVisConfigGroup(), new EvConfigGroup());

DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(config);
drtConfig.addParameterSet(new PrebookingParams());

Controler controller = RunEDrtScenario.createControler(config, false);
ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0);

PrebookingTracker tracker = new PrebookingTracker();
tracker.install(controller);

controller.run();

assertEquals(74, tracker.immediateScheduled);
assertEquals(198, tracker.prebookedScheduled);
assertEquals(116, tracker.immediateRejected);
assertEquals(7, tracker.prebookedRejected);
}


static private class PassengerPickUpTracker implements PassengerPickedUpEventHandler {
int passengerPickupEvents = 0;

void install(Controler controller) {
PassengerPickUpTracker thisTracker = this;

controller.addOverridingModule(new AbstractModule() {
@Override
public void install() {
addEventHandlerBinding().toInstance(thisTracker);
}
});
}

@Override
public void handleEvent(PassengerPickedUpEvent event) {
passengerPickupEvents++;
}

@Override
public void reset(int iteration) {
passengerPickupEvents=0;
}

}

static private class PrebookingTracker implements PassengerRequestRejectedEventHandler, PassengerRequestScheduledEventHandler {
int immediateScheduled = 0;
int prebookedScheduled = 0;
int immediateRejected = 0;
int prebookedRejected = 0;

@Override
public void handleEvent(PassengerRequestScheduledEvent event) {
if (event.getRequestId().toString().contains("prebooked")) {
Expand All @@ -98,10 +164,10 @@ public void handleEvent(PassengerRequestRejectedEvent event) {
immediateRejected++;
}
}

void install(Controler controller) {
PrebookingTracker thisTracker = this;

controller.addOverridingModule(new AbstractModule() {
@Override
public void install() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@

package org.matsim.contrib.ev.discharging;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.Event;
import org.matsim.api.core.v01.events.HasLinkId;
import org.matsim.api.core.v01.events.HasVehicleId;
import org.matsim.api.core.v01.events.LinkLeaveEvent;
import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent;
import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent;
Expand Down Expand Up @@ -80,7 +83,7 @@ private boolean isOnFirstLink() {
this.network = network;
this.eventsManager = eventsManager;
eVehicles = data.getElectricVehicles();
evDrives = new HashMap<>(eVehicles.size() / 10);
evDrives = new ConcurrentHashMap<>(eVehicles.size() / 10);
}

@Override
Expand All @@ -94,12 +97,16 @@ public void handleEvent(VehicleEntersTrafficEvent event) {

@Override
public void handleEvent(LinkLeaveEvent event) {
linkLeaveEvents.add(event);
if (evDrives.containsKey(event.getVehicleId())) {// handle only our EVs
linkLeaveEvents.add(event);
}
}

@Override
public void handleEvent(VehicleLeavesTrafficEvent event) {
trafficLeaveEvents.add(event);
if (evDrives.containsKey(event.getVehicleId())) {// handle only our EVs
trafficLeaveEvents.add(event);
}
}

@Override
Expand All @@ -118,40 +125,34 @@ public void setInternalInterface(InternalInterface internalInterface) {

@Override
public void doSimStep(double time) {
handleQueuedEvents(linkLeaveEvents, time, false);
handleQueuedEvents(trafficLeaveEvents, time, true);
}

private <E extends Event & HasVehicleId & HasLinkId> void handleQueuedEvents(Queue<E> queue, double time, boolean leftTraffic) {
// We want to process events in the main thread (instead of the event handling threads).
// This is to eliminate race conditions, where the battery is read/modified by many threads without proper synchronisation
var linkLeaveIterator = linkLeaveEvents.iterator();
while (linkLeaveIterator.hasNext()) {
var event = linkLeaveIterator.next();
while (!queue.isEmpty()) {
var event = queue.peek();
if (event.getTime() == time) {
// There is a potential race condition wrt processing events between doSimStep() and handleEvent().
// To ensure a deterministic behaviour, we only process events from the previous time step.
break;
}

EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime(), time);
if (evDrive != null) {
evDrive.movedOverNodeTime = event.getTime();
}
linkLeaveIterator.remove();
}

var trafficLeaveIterator = trafficLeaveEvents.iterator();
while (trafficLeaveIterator.hasNext()) {
var event = trafficLeaveIterator.next();
if (event.getTime() == time) {
break;
}

EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime(), time);
if (evDrive != null) {
var evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime(), time);
if (leftTraffic) {
evDrives.remove(evDrive.vehicleId);
} else {
evDrive.movedOverNodeTime = event.getTime();
}
trafficLeaveIterator.remove();
queue.remove();
}
}

private EvDrive dischargeVehicle(Id<Vehicle> vehicleId, Id<Link> linkId, double eventTime, double now) {
EvDrive evDrive = evDrives.get(vehicleId);
if (evDrive != null && !evDrive.isOnFirstLink()) {// handle only our EVs, except for the first link
if (!evDrive.isOnFirstLink()) {// skip the first link
Link link = network.getLinks().get(linkId);
double tt = eventTime - evDrive.movedOverNodeTime;
ElectricVehicle ev = evDrive.ev;
Expand Down
Loading