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

A more generic EpsilonModule, now in ccore #190

Merged
merged 4 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -9,6 +9,7 @@
import org.eqasim.core.components.transit.EqasimTransitModule;
import org.eqasim.core.components.transit.EqasimTransitQSimModule;
import org.eqasim.core.simulation.calibration.CalibrationConfigGroup;
import org.eqasim.core.simulation.mode_choice.epsilon.EpsilonModule;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.population.Person;
Expand Down Expand Up @@ -54,7 +55,8 @@ public EqasimConfigurator() {
new SwissRailRaptorModule(), //
new EqasimTransitModule(), //
new DiscreteModeChoiceModule(), //
new EqasimComponentsModule() //
new EqasimComponentsModule(),
new EpsilonModule()//
));

qsimModules.addAll(Arrays.asList( //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@
import org.matsim.api.core.v01.population.Person;

public abstract class AbstractEpsilonProvider implements EpsilonProvider {
private final MessageDigest digest;
private final double maximumValue;
private final long randomSeed;

public AbstractEpsilonProvider(long randomSeed) {
this.randomSeed = randomSeed;
}

protected double getUniformEpsilon(Id<Person> personId, int tripIndex, String mode) {

MessageDigest digest;
double maximumValue;
try {
this.digest = MessageDigest.getInstance("SHA-512");
this.maximumValue = BigInteger.valueOf(2).pow(digest.getDigestLength() * 8).doubleValue();
this.randomSeed = randomSeed;
digest = MessageDigest.getInstance("SHA-512");
maximumValue = BigInteger.valueOf(2).pow(digest.getDigestLength() * 8).doubleValue();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Cannot find SHA-512 algorithm. Providing epsilons is not possible.");
}
}

protected double getUniformEpsilon(Id<Person> personId, int tripIndex, String mode) {
digest.reset();

digest.update(ByteBuffer //
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.eqasim.core.simulation.mode_choice.epsilon;

import org.eqasim.core.components.config.EqasimConfigGroup;
import org.matsim.contribs.discrete_mode_choice.modules.SelectorModule;
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import org.matsim.core.config.CommandLine;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;

import java.util.Map;

public class AdaptConfigForEpsilon {

public static void main(String[] args) throws CommandLine.ConfigurationException {
CommandLine commandLine = new CommandLine.Builder(args).requireOptions("input-config-path", "output-config-path").build();

Config config = ConfigUtils.loadConfig(commandLine.getOptionStrict("input-config-path"), new EqasimConfigGroup(), new DiscreteModeChoiceConfigGroup());
commandLine.applyConfiguration(config);

DiscreteModeChoiceConfigGroup discreteModeChoiceConfigGroup = (DiscreteModeChoiceConfigGroup) config.getModules().get(DiscreteModeChoiceConfigGroup.GROUP_NAME);
discreteModeChoiceConfigGroup.setSelector(SelectorModule.MAXIMUM);

EqasimConfigGroup eqasimConfigGroup = (EqasimConfigGroup) config.getModules().get(EqasimConfigGroup.GROUP_NAME);


for(Map.Entry<String, String> entry: eqasimConfigGroup.getEstimators().entrySet()) {
if(entry.getValue().startsWith(EpsilonModule.EPSILON_UTILITY_PREFIX)) {
continue;
}
eqasimConfigGroup.setEstimator(entry.getKey(), EpsilonModule.EPSILON_UTILITY_PREFIX + entry.getValue());
}

ConfigUtils.writeConfig(config, commandLine.getOptionStrict("output-config-path"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.eqasim.core.simulation.mode_choice.epsilon;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Provides;
import org.apache.log4j.Logger;
import org.eqasim.core.components.config.EqasimConfigGroup;
import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension;
import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator;
import org.matsim.core.config.groups.GlobalConfigGroup;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class EpsilonModule extends AbstractEqasimExtension {

public static final Logger logger = Logger.getLogger(EpsilonModule.class);

public static final String EPSILON_UTILITY_PREFIX = "epsilon_";
@Provides
public GumbelEpsilonProvider provideGumbelEpsilonProvider(GlobalConfigGroup config) {
return new GumbelEpsilonProvider(config.getRandomSeed(), 1.0);
}

@Override
protected void installEqasimExtension() {
bind(EpsilonProvider.class).to(GumbelEpsilonProvider.class);


EqasimConfigGroup eqasimConfigGroup = (EqasimConfigGroup) getConfig().getModules().get(EqasimConfigGroup.GROUP_NAME);
Set<String> processed = new HashSet<>();
for(Map.Entry<String, String > entry: eqasimConfigGroup.getEstimators().entrySet()) {
String mode = entry.getKey();
String utilityEstimator = entry.getValue();
if(utilityEstimator.startsWith(EPSILON_UTILITY_PREFIX)) {
if(processed.contains(utilityEstimator)) {
logger.warn(String.format("The epsilon utility estimator '%s' is used for more than one mode. The seed of the epsilon generator will rely on the first mode", utilityEstimator));
continue;
}
processed.add(utilityEstimator);
String baseEstimator = utilityEstimator.substring(EPSILON_UTILITY_PREFIX.length());
bindUtilityEstimator(utilityEstimator).toProvider(new Provider<>() {
@Inject
private Map<String, Provider<UtilityEstimator>> factory;

@Inject
private EpsilonProvider epsilonProvider;

@Override
public UtilityEstimator get() {
UtilityEstimator delegate = factory.get(baseEstimator).get();
return new EpsilonAdapter(mode, delegate, epsilonProvider);
}
});
}
}
}
}
11 changes: 11 additions & 0 deletions core/src/test/java/org/eqasim/TestSimulationPipeline.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.eqasim.core.simulation.analysis.EqasimAnalysisModule;
import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension;
import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule;
import org.eqasim.core.simulation.mode_choice.epsilon.AdaptConfigForEpsilon;
import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters;
import org.eqasim.core.tools.*;
import org.eqasim.core.simulation.modes.drt.utils.AdaptConfigForDrt;
Expand Down Expand Up @@ -193,6 +194,16 @@ public void testDrt() throws MalformedURLException, CommandLine.ConfigurationExc
runMelunSimulation("melun_test/input/config_drt.xml", "melun_test/output_drt", List.of("drt_a", "drt_b"));
}

@Test
public void testEpsilon() throws CommandLine.ConfigurationException {
AdaptConfigForEpsilon.main(new String[] {
"--input-config-path", "melun_test/input/config.xml",
"--output-config-path", "melun_test/input/config_epsilon.xml"
});

runMelunSimulation("melun_test/input/config_epsilon.xml", "melun_test/output_epsilon", Collections.emptyList());
}

@Test
public void testPipeline() throws Exception {
runMelunSimulation("melun_test/input/config.xml", "melun_test/output", Collections.emptyList());
Expand Down

This file was deleted.

Loading