From 5816d00a3b9fe4156372efdb11ee6c8eee9286eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 10 Sep 2024 16:53:43 +0200 Subject: [PATCH] add person filter --- .../policies/PolicyConfigGroup.java | 3 ++ .../policies/PolicyExtension.java | 9 ++--- .../ile_de_france/policies/PolicyFactory.java | 2 +- .../policies/PolicyPersonFilter.java | 36 +++++++++++++++++++ .../city_tax/CityTaxPolicyFactory.java | 11 +++--- .../city_tax/CityTaxUtilityPenalty.java | 8 +++-- .../LimitedTrafficZonePolicyFactory.java | 9 ++--- .../policies/routing/FixedRoutingPenalty.java | 7 ++-- .../TransitDiscountPolicyFactory.java | 9 ++--- .../TransitDiscountUtilityPenalty.java | 8 +++-- 10 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyPersonFilter.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyConfigGroup.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyConfigGroup.java index 2107dc313..3b9728d31 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyConfigGroup.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyConfigGroup.java @@ -12,4 +12,7 @@ protected PolicyConfigGroup(String name) { @Parameter public boolean active = true; + + @Parameter + public String personFilter; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyExtension.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyExtension.java index 8796ae7b3..ca1465110 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyExtension.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyExtension.java @@ -23,6 +23,7 @@ import org.eqasim.ile_de_france.policies.transit_discount.TransitDiscountPolicyExtension; import org.eqasim.ile_de_france.policies.transit_discount.TransitDiscountPolicyFactory; import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutilityFactory; @@ -81,7 +82,7 @@ protected void installEqasimExtension() { @Provides @Singleton - Map providePolicies(Map factories) { + Map providePolicies(Map factories, Population population) { PoliciesConfigGroup policyConfig = PoliciesConfigGroup.get(getConfig()); Map policies = new HashMap<>(); @@ -100,8 +101,10 @@ Map providePolicies(Map factories) { throw new IllegalStateException("Duplicate policy name: " + policy.policyName); } + PolicyPersonFilter filter = PolicyPersonFilter.create(population, policy); + policies.put(policy.policyName, - factories.get(policy.getName()).createPolicy(policy.policyName)); + factories.get(policy.getName()).createPolicy(policy.policyName, filter)); } } } @@ -133,7 +136,6 @@ PolicyUtilityEstimator providePolicyUtilityEstimatorForTransit(Map policies) { List penalties = new LinkedList<>(); @@ -149,7 +151,6 @@ UtilityPenalty provideUtilityPenalty(Map policies) { } @Provides - @Singleton RoutingPenalty provideRoutingPenalty(Map policies) { List penalties = new LinkedList<>(); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyFactory.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyFactory.java index e3a6f882a..691a3a103 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyFactory.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyFactory.java @@ -1,5 +1,5 @@ package org.eqasim.ile_de_france.policies; public interface PolicyFactory { - Policy createPolicy(String name); + Policy createPolicy(String name, PolicyPersonFilter personFilter); } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyPersonFilter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyPersonFilter.java new file mode 100644 index 000000000..60ae6b7d3 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/PolicyPersonFilter.java @@ -0,0 +1,36 @@ +package org.eqasim.ile_de_france.policies; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdSet; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Population; + +public class PolicyPersonFilter { + private final IdSet selection; + + PolicyPersonFilter(IdSet selection) { + this.selection = selection; + } + + public boolean applies(Id personId) { + return selection == null ? true : selection.contains(personId); + } + + static public PolicyPersonFilter create(Population population, PolicyConfigGroup policy) { + if (policy.personFilter != null && policy.personFilter.length() > 0) { + IdSet selection = new IdSet<>(Person.class); + + for (Person person : population.getPersons().values()) { + Boolean indicator = (Boolean) person.getAttributes().getAttribute(policy.personFilter); + + if (indicator != null && indicator) { + selection.add(person.getId()); + } + } + + return new PolicyPersonFilter(selection); + } else { + return new PolicyPersonFilter(null); + } + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxPolicyFactory.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxPolicyFactory.java index bbb2e8a23..9102d50a0 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxPolicyFactory.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxPolicyFactory.java @@ -9,6 +9,7 @@ import org.eqasim.ile_de_france.policies.PoliciesConfigGroup; import org.eqasim.ile_de_france.policies.Policy; import org.eqasim.ile_de_france.policies.PolicyFactory; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.eqasim.ile_de_france.policies.routing.FixedRoutingPenalty; import org.eqasim.ile_de_france.policies.routing.PolicyLinkFinder; import org.eqasim.ile_de_france.policies.routing.PolicyLinkFinder.Predicate; @@ -34,12 +35,12 @@ public CityTaxPolicyFactory(Config config, Network network, IDFModeParameters mo } @Override - public Policy createPolicy(String name) { + public Policy createPolicy(String name, PolicyPersonFilter personFilter) { for (ConfigGroup item : PoliciesConfigGroup.get(config).getParameterSets(CityTaxPolicyFactory.POLICY_NAME)) { CityTaxConfigGroup policyItem = (CityTaxConfigGroup) item; if (policyItem.policyName.equals(name)) { - return createPolicy(policyItem); + return createPolicy(policyItem, personFilter); } } @@ -47,7 +48,7 @@ public Policy createPolicy(String name) { "Configuration not found for policy " + name + " of type " + CityTaxPolicyFactory.POLICY_NAME); } - private Policy createPolicy(CityTaxConfigGroup enterConfig) { + private Policy createPolicy(CityTaxConfigGroup enterConfig, PolicyPersonFilter personFilter) { logger.info("Creating policy " + enterConfig.policyName + " of type " + CityTaxPolicyFactory.POLICY_NAME); logger.info(" Perimeters: " + enterConfig.perimetersPath); logger.info(" Tax level: " + enterConfig.tax_EUR + " EUR"); @@ -60,8 +61,8 @@ private Policy createPolicy(CityTaxConfigGroup enterConfig) { logger.info(" Affected entering links: " + linkIds.size()); return new DefaultPolicy( - new FixedRoutingPenalty(linkIds, calculateEnterTaxPenalty(enterConfig.tax_EUR, modeParameters)), - new CityTaxUtilityPenalty(linkIds, modeParameters, enterConfig.tax_EUR)); + new FixedRoutingPenalty(linkIds, calculateEnterTaxPenalty(enterConfig.tax_EUR, modeParameters), personFilter), + new CityTaxUtilityPenalty(linkIds, modeParameters, enterConfig.tax_EUR, personFilter)); } private double calculateEnterTaxPenalty(double enterTax_EUR, IDFModeParameters parameters) { diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxUtilityPenalty.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxUtilityPenalty.java index 467bd7ae8..405fe9c78 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxUtilityPenalty.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/city_tax/CityTaxUtilityPenalty.java @@ -3,6 +3,7 @@ import java.util.List; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.eqasim.ile_de_france.policies.mode_choice.UtilityPenalty; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.IdSet; @@ -18,17 +19,20 @@ public class CityTaxUtilityPenalty implements UtilityPenalty { private final IDFModeParameters parameters; private final IdSet taxedLinkIds; private final double enterTax_EUR; + private final PolicyPersonFilter personFilter; - public CityTaxUtilityPenalty(IdSet taxedLinkIds, IDFModeParameters parameters, double enterTax_EUR) { + public CityTaxUtilityPenalty(IdSet taxedLinkIds, IDFModeParameters parameters, double enterTax_EUR, + PolicyPersonFilter personFilter) { this.taxedLinkIds = taxedLinkIds; this.parameters = parameters; this.enterTax_EUR = enterTax_EUR; + this.personFilter = personFilter; } @Override public double calculatePenalty(String mode, Person person, DiscreteModeChoiceTrip trip, List elements) { - if (mode.equals(TransportMode.car)) { + if (mode.equals(TransportMode.car) && personFilter.applies(person.getId())) { return parameters.betaCost_u_MU * estimateTax_EUR(elements); } else { return 0.0; diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/limited_traffic_zone/LimitedTrafficZonePolicyFactory.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/limited_traffic_zone/LimitedTrafficZonePolicyFactory.java index 3ce3b9893..0df0a6506 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/limited_traffic_zone/LimitedTrafficZonePolicyFactory.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/limited_traffic_zone/LimitedTrafficZonePolicyFactory.java @@ -8,6 +8,7 @@ import org.eqasim.ile_de_france.policies.PoliciesConfigGroup; import org.eqasim.ile_de_france.policies.Policy; import org.eqasim.ile_de_france.policies.PolicyFactory; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.eqasim.ile_de_france.policies.routing.FixedRoutingPenalty; import org.eqasim.ile_de_france.policies.routing.PolicyLinkFinder; import org.eqasim.ile_de_france.policies.routing.PolicyLinkFinder.Predicate; @@ -32,13 +33,13 @@ public LimitedTrafficZonePolicyFactory(Config config, Network network) { } @Override - public Policy createPolicy(String name) { + public Policy createPolicy(String name, PolicyPersonFilter personFilter) { for (ConfigGroup item : PoliciesConfigGroup.get(config) .getParameterSets(LimitedTrafficZonePolicyFactory.POLICY_NAME)) { LimitedTrafficZoneConfigGroup policyItem = (LimitedTrafficZoneConfigGroup) item; if (policyItem.policyName.equals(name)) { - return createPolicy(policyItem); + return createPolicy(policyItem, personFilter); } } @@ -46,7 +47,7 @@ public Policy createPolicy(String name) { + LimitedTrafficZonePolicyFactory.POLICY_NAME); } - private Policy createPolicy(LimitedTrafficZoneConfigGroup ltzConfig) { + private Policy createPolicy(LimitedTrafficZoneConfigGroup ltzConfig, PolicyPersonFilter personFilter) { logger.info( "Creating policy " + ltzConfig.policyName + " of type " + LimitedTrafficZonePolicyFactory.POLICY_NAME); logger.info(" Perimeters: " + ltzConfig.perimetersPath); @@ -57,6 +58,6 @@ private Policy createPolicy(LimitedTrafficZoneConfigGroup ltzConfig) { logger.info(" Affected entering links: " + linkIds.size()); - return new DefaultPolicy(new FixedRoutingPenalty(linkIds, enterPenalty), null); + return new DefaultPolicy(new FixedRoutingPenalty(linkIds, enterPenalty, personFilter), null); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/routing/FixedRoutingPenalty.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/routing/FixedRoutingPenalty.java index 22e198447..c8be85c76 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/routing/FixedRoutingPenalty.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/routing/FixedRoutingPenalty.java @@ -1,5 +1,6 @@ package org.eqasim.ile_de_france.policies.routing; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.matsim.api.core.v01.IdSet; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; @@ -7,14 +8,16 @@ public class FixedRoutingPenalty implements RoutingPenalty { private final IdSet linkIds; private final double penalty; + private final PolicyPersonFilter personFilter; - public FixedRoutingPenalty(IdSet linkIds, double penalty) { + public FixedRoutingPenalty(IdSet linkIds, double penalty, PolicyPersonFilter personFilter) { this.linkIds = linkIds; this.penalty = penalty; + this.personFilter = personFilter; } @Override public double getLinkPenalty(Link link, Person person, double time) { - return linkIds.contains(link.getId()) ? penalty : 0.0; + return linkIds.contains(link.getId()) && personFilter.applies(person.getId()) ? penalty : 0.0; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountPolicyFactory.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountPolicyFactory.java index 6d0ab16a4..ac0bab9f6 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountPolicyFactory.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountPolicyFactory.java @@ -8,6 +8,7 @@ import org.eqasim.ile_de_france.policies.PoliciesConfigGroup; import org.eqasim.ile_de_france.policies.Policy; import org.eqasim.ile_de_france.policies.PolicyFactory; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; @@ -27,13 +28,13 @@ public TransitDiscountPolicyFactory(Config config, CostModel costModel, IDFModeP } @Override - public Policy createPolicy(String name) { + public Policy createPolicy(String name, PolicyPersonFilter personFilter) { for (ConfigGroup item : PoliciesConfigGroup.get(config) .getParameterSets(TransitDiscountPolicyFactory.POLICY_NAME)) { TransitDiscountConfigGroup policyItem = (TransitDiscountConfigGroup) item; if (policyItem.policyName.equals(name)) { - return createPolicy(policyItem); + return createPolicy(policyItem, personFilter); } } @@ -41,12 +42,12 @@ public Policy createPolicy(String name) { "Configuration not found for policy " + name + " of type " + TransitDiscountPolicyFactory.POLICY_NAME); } - private Policy createPolicy(TransitDiscountConfigGroup discountConfig) { + private Policy createPolicy(TransitDiscountConfigGroup discountConfig, PolicyPersonFilter personFilter) { logger.info("Creating policy " + discountConfig.policyName + " of type " + TransitDiscountPolicyFactory.POLICY_NAME); logger.info(" Price factor: " + discountConfig.priceFactor); return new DefaultPolicy(null, - new TransitDiscountUtilityPenalty(costModel, modeParameters, discountConfig.priceFactor)); + new TransitDiscountUtilityPenalty(costModel, modeParameters, discountConfig.priceFactor, personFilter)); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountUtilityPenalty.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountUtilityPenalty.java index 47353548f..685801b2d 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountUtilityPenalty.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/policies/transit_discount/TransitDiscountUtilityPenalty.java @@ -4,6 +4,7 @@ import org.eqasim.core.simulation.mode_choice.cost.CostModel; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.policies.PolicyPersonFilter; import org.eqasim.ile_de_france.policies.mode_choice.UtilityPenalty; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Person; @@ -14,17 +15,20 @@ public class TransitDiscountUtilityPenalty implements UtilityPenalty { private final CostModel costModel; private final IDFModeParameters modeParameters; private final double costFactor; + private final PolicyPersonFilter personFilter; - public TransitDiscountUtilityPenalty(CostModel costModel, IDFModeParameters modeParameters, double costFactor) { + public TransitDiscountUtilityPenalty(CostModel costModel, IDFModeParameters modeParameters, double costFactor, + PolicyPersonFilter personFilter) { this.costModel = costModel; this.modeParameters = modeParameters; this.costFactor = costFactor; + this.personFilter = personFilter; } @Override public double calculatePenalty(String mode, Person person, DiscreteModeChoiceTrip trip, List elements) { - if (mode.equals(TransportMode.pt)) { + if (mode.equals(TransportMode.pt) && personFilter.applies(person.getId())) { double initialCost = costModel.calculateCost_MU(person, trip, elements); double updatedCost = initialCost * costFactor; return modeParameters.betaCost_u_MU * (updatedCost - initialCost);