-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add more functionality for advanced scoring options
- Loading branch information
Showing
14 changed files
with
641 additions
and
297 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
src/main/java/org/matsim/run/scoring/AdvancedScoringConfigGroup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package org.matsim.run.scoring; | ||
|
||
import org.matsim.core.config.ConfigGroup; | ||
import org.matsim.core.config.ReflectiveConfigGroup; | ||
import org.matsim.utils.objectattributes.attributable.Attributes; | ||
|
||
import java.util.*; | ||
|
||
/** | ||
* Stores scoring parameters for {@link AdvancedScoringModule}. | ||
*/ | ||
public final class AdvancedScoringConfigGroup extends ReflectiveConfigGroup { | ||
|
||
private static final String GROUP_NAME = "advancedScoring"; | ||
|
||
private final List<ScoringParameters> scoringParameters = new ArrayList<>(); | ||
|
||
@Parameter | ||
@Comment("The distance groups if marginal utility of distance is adjusted. In meters.") | ||
public List<Integer> distGroups; | ||
|
||
@Parameter | ||
@Comment("Enable income dependent marginal utility of money.") | ||
public boolean incomeDependent = true; | ||
|
||
|
||
// TODO: maybe option to re-assign variations or use them from attributes | ||
|
||
public AdvancedScoringConfigGroup() { | ||
super(GROUP_NAME); | ||
} | ||
|
||
/** | ||
* Return the defined scoring parameters. | ||
*/ | ||
public List<ScoringParameters> getScoringParameters() { | ||
return Collections.unmodifiableList(scoringParameters); | ||
} | ||
|
||
@Override | ||
public ConfigGroup createParameterSet(String type) { | ||
if (type.equals(ScoringParameters.GROUP_NAME)) { | ||
return new ScoringParameters(); | ||
} else { | ||
throw new IllegalArgumentException("Unsupported parameter set type: " + type); | ||
} | ||
} | ||
|
||
@Override | ||
public void addParameterSet(ConfigGroup set) { | ||
if (set instanceof ScoringParameters p) { | ||
super.addParameterSet(set); | ||
scoringParameters.add(p); | ||
} else { | ||
throw new IllegalArgumentException("Unsupported parameter set class: " + set); | ||
} | ||
} | ||
|
||
public static final class ScoringParameters extends ReflectiveConfigGroup { | ||
|
||
private static final String GROUP_NAME = "scoringParameters"; | ||
|
||
/** | ||
* Params per mode. | ||
*/ | ||
private final Map<String, ModeParams> modeParams = new HashMap<>(); | ||
|
||
// TODO: option to match as list | ||
|
||
public ScoringParameters() { | ||
super(GROUP_NAME, true); | ||
} | ||
|
||
/** | ||
* Checks if the given attributes match the config. If true these parameters are applicable to tbe object. | ||
*/ | ||
public boolean matchObject(Attributes attr) { | ||
|
||
// TODO: special case int <-> double and numbers | ||
// boolean values | ||
// allow lists | ||
|
||
// TODO: matching is not yet correct | ||
// TODO: add test | ||
|
||
for (Map.Entry<String, String> e : this.getParams().entrySet()) { | ||
// might be null if not defined | ||
Object objValue = attr.getAttribute(e.getKey()); | ||
|
||
// compare as string | ||
if (!Objects.toString(objValue).equals(e.getValue())) | ||
return false; | ||
|
||
} | ||
|
||
return true; | ||
} | ||
|
||
public Map<String, ModeParams> getModeParams() { | ||
return modeParams; | ||
} | ||
|
||
@Override | ||
public ConfigGroup createParameterSet(final String type) { | ||
return switch (type) { | ||
case ModeParams.GROUP_NAME -> new ModeParams(); | ||
default -> throw new IllegalArgumentException(type); | ||
}; | ||
} | ||
|
||
@Override | ||
public void addParameterSet(ConfigGroup set) { | ||
if (set instanceof ModeParams p) { | ||
super.addParameterSet(set); | ||
modeParams.put(p.mode, p); | ||
} else { | ||
throw new IllegalArgumentException("Unsupported parameter set class: " + set); | ||
} | ||
} | ||
|
||
/** | ||
* Retrieve mode parameters. | ||
*/ | ||
public ModeParams getOrCreateModeParams(String mode) { | ||
if (!modeParams.containsKey(mode)) { | ||
ModeParams p = new ModeParams(); | ||
p.mode = mode; | ||
|
||
addParameterSet(p); | ||
return p; | ||
} | ||
|
||
return modeParams.get(mode); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Stores mode specific parameters and also attributes to whom to apply this specification. | ||
*/ | ||
public static final class ModeParams extends ReflectiveConfigGroup { | ||
|
||
private static final String GROUP_NAME = "modeParams"; | ||
|
||
@Parameter | ||
@Comment("The mode for which the parameters are defined.") | ||
public String mode; | ||
|
||
@Parameter | ||
@Comment("[utils/leg] alternative-specific constant.") | ||
public double deltaConstant; | ||
|
||
@Parameter | ||
@Comment("Variation of the constant across individuals.") | ||
public VariationType varConstant = VariationType.fixed; | ||
|
||
@Parameter | ||
@Comment("[utils/day] if the mode is used at least once.") | ||
public double deltaDailyConstant; | ||
|
||
@Parameter | ||
@Comment("Variation of the daily constant across individuals.") | ||
public VariationType varDailyConstant = VariationType.fixed; | ||
|
||
@Parameter | ||
@Comment("[utils/m] for each distance group.") | ||
public List<Double> deltaUtilsDistance; | ||
|
||
public ModeParams() { | ||
super(GROUP_NAME); | ||
} | ||
} | ||
|
||
public enum VariationType { | ||
fixed, normal | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/main/java/org/matsim/run/scoring/AdvancedScoringModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.matsim.run.scoring; | ||
|
||
import com.google.inject.Key; | ||
import jakarta.inject.Singleton; | ||
import org.matsim.core.config.ConfigUtils; | ||
import org.matsim.core.controler.AbstractModule; | ||
import org.matsim.core.controler.listener.ControlerListener; | ||
import org.matsim.core.scoring.functions.ScoringParametersForPerson; | ||
|
||
/** | ||
* Module to bind components needed for advanced scoring functionality configured by {@link AdvancedScoringConfigGroup}. | ||
*/ | ||
public class AdvancedScoringModule extends AbstractModule { | ||
|
||
@Override | ||
public void install() { | ||
|
||
ConfigUtils.addOrGetModule(getConfig(), AdvancedScoringConfigGroup.class); | ||
|
||
bind(ScoringParametersForPerson.class).to(IndividualPersonScoringParameters.class).in(Singleton.class); | ||
|
||
addControlerListenerBinding().to(AdvancedScoringOutputWriter.class).in(Singleton.class); | ||
|
||
bindScoringFunctionFactory().to(AdvancedScoringFunctionFactory.class).in(Singleton.class); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/main/java/org/matsim/run/scoring/AdvancedScoringOutputWriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package org.matsim.run.scoring; | ||
|
||
import com.google.inject.Inject; | ||
import it.unimi.dsi.fastutil.objects.Object2DoubleMap; | ||
import org.apache.commons.csv.CSVFormat; | ||
import org.apache.commons.csv.CSVPrinter; | ||
import org.matsim.api.core.v01.population.Person; | ||
import org.matsim.core.controler.OutputDirectoryHierarchy; | ||
import org.matsim.core.controler.events.IterationEndsEvent; | ||
import org.matsim.core.controler.listener.IterationEndsListener; | ||
import org.matsim.core.scoring.functions.ScoringParametersForPerson; | ||
import org.matsim.core.utils.io.IOUtils; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
|
||
/** | ||
* This class writes person specific information from {@link IndividualPersonScoringParameters} to the output. | ||
*/ | ||
public class AdvancedScoringOutputWriter implements IterationEndsListener { | ||
|
||
|
||
@Inject | ||
private ScoringParametersForPerson scoring; | ||
|
||
private boolean outputWritten = false; | ||
|
||
@Override | ||
public void notifyIterationEnds(IterationEndsEvent event) { | ||
|
||
if (outputWritten) | ||
return; | ||
|
||
if (!(scoring instanceof IndividualPersonScoringParameters params)) | ||
return; | ||
|
||
OutputDirectoryHierarchy io = event.getServices().getControlerIO(); | ||
|
||
String output = io.getOutputFilename("person_util_variations.csv"); | ||
|
||
// Write scoring information for each person | ||
try (CSVPrinter csv = new CSVPrinter(IOUtils.getBufferedWriter(output), CSVFormat.DEFAULT)) { | ||
|
||
csv.print("person"); | ||
csv.printRecord(params.header); | ||
|
||
for (Person person : event.getServices().getScenario().getPopulation().getPersons().values()) { | ||
|
||
Object2DoubleMap<String> values = params.info.get(person.getId()); | ||
if (values == null) { | ||
continue; | ||
} | ||
|
||
csv.print(person.getId()); | ||
for (String s : params.header) { | ||
csv.print(values.getDouble(s)); | ||
} | ||
csv.println(); | ||
} | ||
|
||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
|
||
params.header.clear(); | ||
params.info.clear(); | ||
|
||
outputWritten = true; | ||
} | ||
} |
70 changes: 0 additions & 70 deletions
70
src/main/java/org/matsim/run/scoring/DetailedPersonScoringParameters.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.matsim.run.scoring; | ||
|
||
/** | ||
* Store distance group | ||
* | ||
* @param dist lower bound for distance group | ||
* @param constant added constant | ||
* @param util_m utility per meter, i.e. slope of linear function | ||
*/ | ||
record DistanceGroup(double dist, double constant, double util_m) implements Comparable<DistanceGroup> { | ||
@Override | ||
public int compareTo(DistanceGroup o) { | ||
return Double.compare(dist, o.dist); | ||
} | ||
} |
Oops, something went wrong.