Skip to content

Commit 640b0c6

Browse files
authored
Feat: Transit with abstract access (#214)
* feat: TransitWithAbstractAccessModule * refractoring
1 parent 44fb3f1 commit 640b0c6

29 files changed

Lines changed: 1728 additions & 131 deletions

core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java

Lines changed: 125 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
import org.eqasim.core.simulation.modes.feeder_drt.MultiModeFeederDrtModule;
2020
import org.eqasim.core.simulation.modes.feeder_drt.config.MultiModeFeederDrtConfigGroup;
2121
import org.eqasim.core.simulation.modes.feeder_drt.mode_choice.EqasimFeederDrtModeChoiceModule;
22+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.TransitWithAbstractAccessModule;
23+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.TransitWithAbstractAbstractAccessModuleConfigGroup;
24+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.TransitWithAbstractAccessQSimModule;
25+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.mode_choice.TransitWithAbstractAccessModeChoiceModule;
26+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.routing.AbstractAccessRouteFactory;
27+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.routing.DefaultAbstractAccessRoute;
2228
import org.eqasim.core.simulation.termination.EqasimTerminationConfigGroup;
2329
import org.eqasim.core.simulation.termination.EqasimTerminationModule;
2430
import org.eqasim.core.simulation.termination.mode_share.ModeShareModule;
@@ -55,81 +61,87 @@ public class EqasimConfigurator {
5561
private final Map<String, List<BiConsumer<Controler, QSimComponentsConfig>>> optionalQSimComponentConfigurationSteps = new HashMap<>();
5662
private final Map<String, ConfigGroup> optionalConfigGroups = new HashMap<>();
5763

58-
public EqasimConfigurator() {
59-
configGroups.addAll(Arrays.asList( //
60-
new SwissRailRaptorConfigGroup(), //
61-
new EqasimConfigGroup(), //
62-
new DiscreteModeChoiceConfigGroup() //
63-
));
64-
65-
modules.addAll(Arrays.asList( //
66-
new SwissRailRaptorModule(), //
67-
new EqasimTransitModule(), //
68-
new DiscreteModeChoiceModule(), //
69-
new EqasimComponentsModule(), //
70-
new EpsilonModule() //
71-
));
72-
73-
qsimModules.addAll(Arrays.asList( //
74-
new EqasimTransitQSimModule(), //
75-
new EqasimTrafficQSimModule() //
76-
));
77-
78-
this.registerOptionalConfigGroup(new MultiModeDrtConfigGroup(),
79-
Collections.singleton(new MultiModeDrtModule()),
80-
Collections.emptyList(),
81-
Collections.singletonList((controller, components) ->
82-
DvrpQSimComponents.activateAllModes((MultiModal<?>) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components)));
83-
84-
this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule()));
85-
this.registerOptionalConfigGroup(new EqasimTerminationConfigGroup(), List.of(new EqasimTerminationModule(), new ModeShareModule()));
86-
this.registerOptionalConfigGroup(new MultiModeFeederDrtConfigGroup(), List.of(new MultiModeFeederDrtModule(), new EqasimFeederDrtModeChoiceModule()));
87-
}
88-
89-
public ConfigGroup[] getConfigGroups() {
90-
return configGroups.toArray(ConfigGroup[]::new);
91-
}
92-
93-
public List<AbstractModule> getModules() {
94-
return modules;
95-
}
96-
97-
public List<AbstractQSimModule> getQSimModules() {
98-
return qsimModules;
99-
}
100-
101-
public void configureController(Controler controller) {
102-
103-
// The optional modules are added after the non-optional ones because we consider that their bindings have less priority
104-
this.optionalModules.entrySet().stream()
105-
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
106-
.map(Map.Entry::getValue)
107-
.flatMap(Collection::stream)
108-
.forEach(controller::addOverridingModule);
109-
110-
for (AbstractModule module : getModules()) {
111-
controller.addOverridingModule(module);
112-
}
113-
114-
this.optionalQSimModules.entrySet().stream()
115-
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
116-
.map(Map.Entry::getValue)
117-
.flatMap(Collection::stream)
118-
.forEach(controller::addOverridingQSimModule);
119-
120-
for (AbstractQSimModule module : getQSimModules()) {
121-
controller.addOverridingQSimModule(module);
122-
}
123-
124-
controller.configureQSimComponents(components -> {
125-
optionalQSimComponentConfigurationSteps.entrySet().stream()
126-
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
127-
.map(Map.Entry::getValue)
128-
.flatMap(Collection::stream)
129-
.forEach(step -> step.accept(controller, components));
130-
EqasimTransitQSimModule.configure(components, controller.getConfig());
131-
});
132-
}
64+
public EqasimConfigurator() {
65+
configGroups.addAll(Arrays.asList( //
66+
new SwissRailRaptorConfigGroup(), //
67+
new EqasimConfigGroup(), //
68+
new DiscreteModeChoiceConfigGroup() //
69+
));
70+
71+
modules.addAll(Arrays.asList( //
72+
new SwissRailRaptorModule(), //
73+
new EqasimTransitModule(), //
74+
new DiscreteModeChoiceModule(), //
75+
new EqasimComponentsModule(), //
76+
new EpsilonModule() //
77+
));
78+
79+
qsimModules.addAll(Arrays.asList( //
80+
new EqasimTransitQSimModule(), //
81+
new EqasimTrafficQSimModule() //
82+
));
83+
84+
this.registerOptionalConfigGroup(new MultiModeDrtConfigGroup(),
85+
Collections.singleton(new MultiModeDrtModule()),
86+
Collections.emptyList(),
87+
Collections.singletonList((controller, components) ->
88+
DvrpQSimComponents.activateAllModes((MultiModal<?>) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components)));
89+
90+
this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule()));
91+
this.registerOptionalConfigGroup(new EqasimTerminationConfigGroup(), List.of(new EqasimTerminationModule(), new ModeShareModule()));
92+
this.registerOptionalConfigGroup(new MultiModeFeederDrtConfigGroup(), List.of(new MultiModeFeederDrtModule(), new EqasimFeederDrtModeChoiceModule()));
93+
this.registerOptionalConfigGroup(
94+
new TransitWithAbstractAbstractAccessModuleConfigGroup(),
95+
List.of(new TransitWithAbstractAccessModule(),
96+
new TransitWithAbstractAccessModeChoiceModule()),
97+
List.of(new TransitWithAbstractAccessQSimModule()),
98+
Collections.singletonList((controller, components) -> TransitWithAbstractAccessQSimModule.configure(components, controller.getConfig())));
99+
}
100+
101+
public ConfigGroup[] getConfigGroups() {
102+
return configGroups.toArray(ConfigGroup[]::new);
103+
}
104+
105+
public List<AbstractModule> getModules() {
106+
return modules;
107+
}
108+
109+
public List<AbstractQSimModule> getQSimModules() {
110+
return qsimModules;
111+
}
112+
113+
public void configureController(Controler controller) {
114+
115+
// The optional modules are added after the non-optional ones because we consider that their bindings have less priority
116+
this.optionalModules.entrySet().stream()
117+
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
118+
.map(Map.Entry::getValue)
119+
.flatMap(Collection::stream)
120+
.forEach(controller::addOverridingModule);
121+
122+
for (AbstractModule module : getModules()) {
123+
controller.addOverridingModule(module);
124+
}
125+
126+
this.optionalQSimModules.entrySet().stream()
127+
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
128+
.map(Map.Entry::getValue)
129+
.flatMap(Collection::stream)
130+
.forEach(controller::addOverridingQSimModule);
131+
132+
for (AbstractQSimModule module : getQSimModules()) {
133+
controller.addOverridingQSimModule(module);
134+
}
135+
136+
controller.configureQSimComponents(components -> {
137+
optionalQSimComponentConfigurationSteps.entrySet().stream()
138+
.filter(e -> controller.getConfig().getModules().containsKey(e.getKey()))
139+
.map(Map.Entry::getValue)
140+
.flatMap(Collection::stream)
141+
.forEach(step -> step.accept(controller, components));
142+
EqasimTransitQSimModule.configure(components, controller.getConfig());
143+
});
144+
}
133145

134146
protected void registerOptionalConfigGroup(ConfigGroup configGroup) {
135147
registerOptionalConfigGroup(configGroup, new ArrayList<>());
@@ -147,41 +159,42 @@ protected void registerOptionalConfigGroup(ConfigGroup configGroup, Collection<A
147159
this.optionalModules.putIfAbsent(configGroup.getName(), new ArrayList<>());
148160
this.optionalModules.get(configGroup.getName()).addAll(modules);
149161

150-
this.optionalQSimModules.putIfAbsent(configGroup.getName(), new ArrayList<>());
151-
this.optionalQSimModules.get(configGroup.getName()).addAll(qsimModules);
152-
153-
this.optionalQSimComponentConfigurationSteps.putIfAbsent(configGroup.getName(), new ArrayList<>());
154-
this.optionalQSimComponentConfigurationSteps.get(configGroup.getName()).addAll(componentsConsumers);
155-
}
156-
157-
public void addOptionalConfigGroups(Config config) {
158-
for(ConfigGroup configGroup: optionalConfigGroups.values()) {
159-
if(config.getModules().get(configGroup.getName()) != null) {
160-
config.addModule(configGroup);
161-
}
162-
}
163-
}
164-
165-
public void configureScenario(Scenario scenario) {
166-
scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, new DrtRouteFactory());
167-
}
168-
169-
public void adjustScenario(Scenario scenario) {
170-
for (Household household : scenario.getHouseholds().getHouseholds().values()) {
171-
for (Id<Person> memberId : household.getMemberIds()) {
172-
Person person = scenario.getPopulation().getPersons().get(memberId);
173-
174-
if (person != null) {
175-
copyAttribute(household, person, "bikeAvailability");
176-
copyAttribute(household, person, "spRegion");
177-
}
178-
}
179-
}
180-
}
181-
182-
static protected void copyAttribute(Household household, Person person, String attribute) {
183-
if (household.getAttributes().getAsMap().containsKey(attribute)) {
184-
person.getAttributes().putAttribute(attribute, household.getAttributes().getAttribute(attribute));
185-
}
186-
}
162+
this.optionalQSimModules.putIfAbsent(configGroup.getName(), new ArrayList<>());
163+
this.optionalQSimModules.get(configGroup.getName()).addAll(qsimModules);
164+
165+
this.optionalQSimComponentConfigurationSteps.putIfAbsent(configGroup.getName(), new ArrayList<>());
166+
this.optionalQSimComponentConfigurationSteps.get(configGroup.getName()).addAll(componentsConsumers);
167+
}
168+
169+
public void addOptionalConfigGroups(Config config) {
170+
for (ConfigGroup configGroup : optionalConfigGroups.values()) {
171+
if (config.getModules().get(configGroup.getName()) != null) {
172+
config.addModule(configGroup);
173+
}
174+
}
175+
}
176+
177+
public void configureScenario(Scenario scenario) {
178+
scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, new DrtRouteFactory());
179+
scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DefaultAbstractAccessRoute.class, new AbstractAccessRouteFactory());
180+
}
181+
182+
public void adjustScenario(Scenario scenario) {
183+
for (Household household : scenario.getHouseholds().getHouseholds().values()) {
184+
for (Id<Person> memberId : household.getMemberIds()) {
185+
Person person = scenario.getPopulation().getPersons().get(memberId);
186+
187+
if (person != null) {
188+
copyAttribute(household, person, "bikeAvailability");
189+
copyAttribute(household, person, "spRegion");
190+
}
191+
}
192+
}
193+
}
194+
195+
static protected void copyAttribute(Household household, Person person, String attribute) {
196+
if (household.getAttributes().getAsMap().containsKey(attribute)) {
197+
person.getAttributes().putAttribute(attribute, household.getAttributes().getAttribute(attribute));
198+
}
199+
}
187200
}

core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/PtPredictor.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@
1515
import com.google.inject.name.Named;
1616

1717
public class PtPredictor extends CachedVariablePredictor<PtVariables> {
18-
private CostModel costModel;
18+
private final CostModel costModel;
1919

2020
@Inject
2121
public PtPredictor(@Named("pt") CostModel costModel) {
2222
this.costModel = costModel;
2323
}
2424

25+
protected CostModel getCostModel() {
26+
return this.costModel;
27+
}
28+
2529
@Override
2630
public PtVariables predict(Person person, DiscreteModeChoiceTrip trip, List<? extends PlanElement> elements) {
2731
/*
@@ -39,8 +43,7 @@ public PtVariables predict(Person person, DiscreteModeChoiceTrip trip, List<? ex
3943
double accessEgressTime_min = 0.0;
4044

4145
for (PlanElement element : elements) {
42-
if (element instanceof Leg) {
43-
Leg leg = (Leg) element;
46+
if (element instanceof Leg leg) {
4447

4548
switch (leg.getMode()) {
4649
case TransportMode.walk:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.eqasim.core.simulation.modes.transit_with_abstract_access;
2+
3+
import com.google.inject.Inject;
4+
5+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.events.AbstractAccessDepartureEvent;
6+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.routing.AbstractAccessRoute;
7+
import org.eqasim.core.simulation.modes.transit_with_abstract_access.routing.TransitWithAbstractAccessRoutingModule;
8+
import org.matsim.api.core.v01.Id;
9+
import org.matsim.api.core.v01.network.Link;
10+
import org.matsim.api.core.v01.population.Leg;
11+
import org.matsim.core.api.experimental.events.EventsManager;
12+
import org.matsim.core.mobsim.framework.MobsimAgent;
13+
import org.matsim.core.mobsim.framework.PlanAgent;
14+
import org.matsim.core.mobsim.qsim.interfaces.DepartureHandler;
15+
16+
public class AbstractAccessDepartureEventCreator implements DepartureHandler {
17+
18+
private final EventsManager eventsManager;
19+
@Inject
20+
public AbstractAccessDepartureEventCreator(EventsManager eventsManager) {
21+
this.eventsManager = eventsManager;
22+
}
23+
24+
@Override
25+
public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> linkId) {
26+
if(agent.getMode().equals(TransitWithAbstractAccessRoutingModule.ABSTRACT_ACCESS_LEG_MODE_NAME)) {
27+
Leg leg = (Leg) ((PlanAgent) agent).getCurrentPlanElement();
28+
AbstractAccessRoute abstractAccessRoute = (AbstractAccessRoute) leg.getRoute();
29+
this.eventsManager.processEvent(new AbstractAccessDepartureEvent(now, agent.getId(), abstractAccessRoute.getAbstractAccessItemId(), abstractAccessRoute.getStartLinkId(), abstractAccessRoute.getEndLinkId(), abstractAccessRoute.isLeavingAccessCenter(), abstractAccessRoute.isRouted(), abstractAccessRoute.getDistance()));
30+
}
31+
return false;
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.eqasim.core.simulation.modes.transit_with_abstract_access;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import org.matsim.core.config.ReflectiveConfigGroup;
5+
6+
public class TransitWithAbstractAbstractAccessModuleConfigGroup extends ReflectiveConfigGroup {
7+
8+
public static final String GROUP_NAME = "transitWithAbstractAccess";
9+
10+
private static final String ACCESS_ITEMS_FILE_PATH = "accessItemsFilePath";
11+
12+
13+
private static final String MODE_NAME = "modeName";
14+
15+
@NotNull
16+
private String accessItemsFilePath;
17+
18+
@NotNull
19+
private String modeName;
20+
21+
public TransitWithAbstractAbstractAccessModuleConfigGroup() {
22+
super(GROUP_NAME);
23+
}
24+
25+
@StringSetter(ACCESS_ITEMS_FILE_PATH)
26+
public void setAccessItemsFilePath(String accessItemsFilePath) {
27+
this.accessItemsFilePath = accessItemsFilePath;
28+
}
29+
30+
@StringGetter(ACCESS_ITEMS_FILE_PATH)
31+
public String getAccessItemsFilePath() {
32+
return this.accessItemsFilePath;
33+
}
34+
35+
@StringSetter(MODE_NAME)
36+
public void setModeName(String modeName) {
37+
this.modeName = modeName;
38+
}
39+
40+
@StringGetter(MODE_NAME)
41+
public String getModeName() {
42+
return this.modeName;
43+
}
44+
}

0 commit comments

Comments
 (0)