diff --git a/src/main/java/org/matsim/run/scoring/Category.java b/src/main/java/org/matsim/run/scoring/Category.java index 8922b686..93c5894d 100644 --- a/src/main/java/org/matsim/run/scoring/Category.java +++ b/src/main/java/org/matsim/run/scoring/Category.java @@ -1,6 +1,10 @@ package org.matsim.run.scoring; +import org.matsim.core.config.ReflectiveConfigGroup; +import org.matsim.utils.objectattributes.attributable.Attributes; + import java.util.*; +import java.util.regex.Pattern; /** * Categorize values into groups. @@ -21,14 +25,58 @@ public final class Category { */ private final Map grouped; + + /** + * Regular expressions for each category. + */ + private final Map regex; + /** * Range categories. */ private final List ranges; + /** + * Create categories from config parameters. + */ + public static Map fromConfigParams(Collection params) { + + Map> categories = new HashMap<>(); + + // Collect all values + for (ReflectiveConfigGroup parameter : params) { + for (Map.Entry kv : parameter.getParams().entrySet()) { + categories.computeIfAbsent(kv.getKey(), k -> new HashSet<>()).add(kv.getValue()); + } + } + + return categories.entrySet().stream() + .collect(HashMap::new, (m, e) -> m.put(e.getKey(), new Category(e.getValue())), HashMap::putAll); + } + + /** + * Match attributes from an object with parameters defined in config. + */ + public static boolean matchAttributesWithConfig(Attributes attr, ReflectiveConfigGroup config, Map categories) { + + for (Map.Entry e : config.getParams().entrySet()) { + // might be null if not defined + Object objValue = attr.getAttribute(e.getKey()); + String category = categories.get(e.getKey()).categorize(objValue); + + // compare as string + if (!Objects.toString(category).equals(e.getValue())) + return false; + } + + return true; + } + + public Category(Set values) { this.values = values; this.grouped = new HashMap<>(); + this.regex = new HashMap<>(); for (String v : values) { if (v.contains(",")) { String[] grouped = v.split(","); @@ -36,6 +84,10 @@ public Category(Set values) { this.grouped.put(g, v); } } + + if (v.startsWith("/") && v.endsWith("/")) { + this.regex.put(v, Pattern.compile(v.substring(1, v.length() - 1), Pattern.CASE_INSENSITIVE)); + } } boolean range = this.values.stream().allMatch(v -> v.contains("-") || v.contains("+")); @@ -85,6 +137,12 @@ public String categorize(Object value) { return v; else if (grouped.containsKey(v)) return grouped.get(v); + else { + for (Map.Entry kv : regex.entrySet()) { + if (kv.getValue().matcher(v).matches()) + return kv.getKey(); + } + } try { double d = Double.parseDouble(v); diff --git a/src/main/java/org/matsim/run/scoring/IndividualPersonScoringParameters.java b/src/main/java/org/matsim/run/scoring/IndividualPersonScoringParameters.java index 68b54f40..10e9138e 100644 --- a/src/main/java/org/matsim/run/scoring/IndividualPersonScoringParameters.java +++ b/src/main/java/org/matsim/run/scoring/IndividualPersonScoringParameters.java @@ -81,25 +81,10 @@ public IndividualPersonScoringParameters(Scenario scenario) { this.scoring = ConfigUtils.addOrGetModule(scenario.getConfig(), AdvancedScoringConfigGroup.class); this.transitConfig = scenario.getConfig().transit(); this.globalAvgIncome = computeAvgIncome(scenario.getPopulation()); - this.categories = buildCategories(this.scoring); + this.categories = Category.fromConfigParams(this.scoring.getScoringParameters()); this.cache = new IdMap<>(Person.class, scenario.getPopulation().getPersons().size()); } - static Map buildCategories(AdvancedScoringConfigGroup scoring) { - - Map> categories = new HashMap<>(); - - // Collect all values - for (AdvancedScoringConfigGroup.ScoringParameters parameter : scoring.getScoringParameters()) { - for (Map.Entry kv : parameter.getParams().entrySet()) { - categories.computeIfAbsent(kv.getKey(), k -> new HashSet<>()).add(kv.getValue()); - } - } - - return categories.entrySet().stream() - .collect(HashMap::new, (m, e) -> m.put(e.getKey(), new Category(e.getValue())), HashMap::putAll); - } - static DistanceGroup[] calcDistanceGroups(List dists, DoubleList distUtils) { // Nothing to do if no distance groups are defined. @@ -223,7 +208,7 @@ public ScoringParameters getScoringParameters(Person person) { for (AdvancedScoringConfigGroup.ScoringParameters parameter : scoring.getScoringParameters()) { - if (parameter.matchObject(person.getAttributes(), categories)) { + if (Category.matchAttributesWithConfig(person.getAttributes(), parameter, categories)) { for (Map.Entry mode : parameter.getModeParams().entrySet()) { DistanceGroupModeUtilityParameters.DeltaBuilder b = diff --git a/src/main/sh/start.sh b/src/main/sh/start.sh index 83bf1d06..7eec67fd 100644 --- a/src/main/sh/start.sh +++ b/src/main/sh/start.sh @@ -16,4 +16,4 @@ export RUN_NAME="$name" echo "Starting run $name" echo "$*" -sbatch --export=ALL --job-name matsim-"$name" job.sh +sbatch --parsable --export=ALL --job-name matsim-"$name" job.sh