From 2e03c9b3ea5a4776d6dca51309bd1194bfe97f56 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 23 Jan 2024 15:50:49 +0100 Subject: [PATCH 1/3] include planType in GenericWorstPlanForRemovalSelector. Has still one compileError. --- .../GenericWorstPlanForRemovalSelector.java | 112 +++++++++++------- 1 file changed, 70 insertions(+), 42 deletions(-) diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 116cd309427..953a8d48123 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -25,54 +25,82 @@ import org.matsim.api.core.v01.population.BasicPlan; import org.matsim.api.core.v01.population.HasPlansAndId; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** - *

Selects the worst plan of a person (most likely for removal). + *

Selects the worst plan of a person (most likely for removal), but respects + * the set plan types in a way the no plan is selected that is the last one of + * its type.

+ *

(I would say that it can select the last of its type if it finds nothing else. However, this algo should only + * be used if an agent has more plans than maxPlansPerAgent, so make sure that that parameter is set large enough for + * your purposes. kai, oct'09)

*

Plans without a score are seen as worst and selected accordingly.

* * @author mrieser */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - private static final String UNDEFINED_TYPE = "undefined"; - - @Override - public T selectPlan(HasPlansAndId person) { - - T worst = null; - double worstScore = Double.POSITIVE_INFINITY; - for (T plan : person.getPlans()) { - - // if this plan has no score yet: - if (plan.getScore() == null || plan.getScore().isNaN() ) { - // say that the plan without score now is the "worst": - worst = plan; - - // make sure that this one remains the selected plan: - worstScore = Double.NEGATIVE_INFINITY; - - // otherwise do the usual logic to find the plan with the minimum score: - } else if (plan.getScore() < worstScore) { - worst = plan; - worstScore = plan.getScore(); - } - // (otherwise we just keep "worst=null") - - } - - if (worst == null) { - // there is exactly one plan, or we have of each plan-type exactly one. - // select the one with worst score globally, or the first one with score=null - for (T plan : person.getPlans()) { - if (plan.getScore() == null || plan.getScore().isNaN() ) { - return plan; - } - if (plan.getScore() < worstScore) { - worst = plan; - worstScore = plan.getScore(); - } - } - } - return worst; - } + private static final String UNDEFINED_TYPE = "undefined"; + + @Override + public T selectPlan(HasPlansAndId person) { + + // hashmap that returns "Integer" count for given plans type: + Map typeCounts = new ConcurrentHashMap(); + + // count how many plans per type an agent has: + for (T plan : person.getPlans()) { + String type = plan.getType(); + if ( type==null ) { + type = UNDEFINED_TYPE ; + } + typeCounts.merge( type, 1, ( a, b ) -> a + b ); + } + + T worst = null; + double worstScore = Double.POSITIVE_INFINITY; + for (T plan : person.getPlans()) { + + String type = plan.getType(); + if ( type==null ) { + type = UNDEFINED_TYPE; + } + if ( typeCounts.get( type ) > 1) { + // (if we have more than one plan of the same type:) + + // if this plan has no score yet: + if (plan.getScore() == null || plan.getScore().isNaN() ) { + // say that the plan without score now is the "worst": + worst = plan; + + // make sure that this one remains the selected plan: + worstScore = Double.NEGATIVE_INFINITY; + + // otherwise do the usual logic to find the plan with the minimum score: + } else if (plan.getScore() < worstScore) { + worst = plan; + worstScore = plan.getScore(); + } + } + // (otherwise we just keep "worst=null") + + } + + if (worst == null) { + // there is exactly one plan, or we have of each plan-type exactly one. + // select the one with worst score globally, or the first one with score=null + for (T plan : person.getPlans()) { + if (plan.getScore() == null || plan.getScore().isNaN() ) { + return plan; + } + if (plan.getScore() < worstScore) { + worst = plan; + worstScore = plan.getScore(); + } + } + } + return worst; + } } From 7b7e9842e8d21c027f5a97813f3ac94570d39633 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 25 Mar 2024 10:28:01 +0100 Subject: [PATCH 2/3] add "type" to BasicPlan since the generic plans handling infrastructure now contains (some of) the functionality for it. (Recall: The last plan of a type is not removed.) --- .../api/core/v01/population/BasicPlan.java | 15 ++++++++-- .../matsim/api/core/v01/population/Plan.java | 30 ++++++++----------- .../GenericWorstPlanForRemovalSelector.java | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java index e19d7bbea3a..c8263d2264a 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java @@ -21,10 +21,19 @@ package org.matsim.api.core.v01.population; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; + public interface BasicPlan { - public abstract void setScore(Double score); + void setScore( Double score ); + + Double getScore(); - public abstract Double getScore(); + /** + * Plan type, which may be used to ensure there is at least one plan of a certain type. + */ + default String getType() { + return GenericWorstPlanForRemovalSelector.UNDEFINED_TYPE; + } -} \ No newline at end of file +} diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java index 6329b62a626..ea9bc7d3e04 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/Plan.java @@ -38,33 +38,27 @@ */ public interface Plan extends MatsimPopulationObject, Customizable, BasicPlan, Attributable, Identifiable { - public abstract List getPlanElements(); + List getPlanElements(); - public abstract void addLeg(final Leg leg); + void addLeg( final Leg leg ); - public abstract void addActivity(final Activity act); + void addActivity( final Activity act ); - - /** - * Plan type, which may be used to ensure there is at least one plan of a certain type. - */ - public abstract String getType(); - - public abstract void setType(final String type); + void setType( final String type ); - public abstract void setPlanId(Id planId); + void setPlanId( Id planId ); - public abstract Id getId(); + Id getId(); - public abstract int getIterationCreated(); + int getIterationCreated(); - public abstract void setIterationCreated(int iteration); + void setIterationCreated( int iteration ); - public abstract String getPlanMutator(); + String getPlanMutator(); - public abstract void setPlanMutator(String planMutator); + void setPlanMutator( String planMutator ); - public abstract Person getPerson(); + Person getPerson(); /** * Sets the reference to the person. @@ -72,7 +66,7 @@ public interface Plan extends MatsimPopulationObject, Customizable, BasicPlan, A * sure that the bidirectional reference is set correctly if * you are using this method!. */ - public abstract void setPerson(Person person); + void setPerson( Person person ); } diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 953a8d48123..49d4971caa1 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -41,7 +41,7 @@ */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - private static final String UNDEFINED_TYPE = "undefined"; + public static final String UNDEFINED_TYPE = "undefined"; @Override public T selectPlan(HasPlansAndId person) { From 03a43ee29c039fbac7aed2fb5797c8f1272e8ff8 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 25 Mar 2024 15:39:39 +0100 Subject: [PATCH 3/3] Rename UNDEFINED_Type to UNDEFINED_PLAN_TYPE (is ok, because was private before) and move it to BasicPlan. --- .../org/matsim/api/core/v01/population/BasicPlan.java | 10 +++++----- .../selectors/GenericWorstPlanForRemovalSelector.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java index c8263d2264a..5bcf541d5a3 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/population/BasicPlan.java @@ -21,11 +21,11 @@ package org.matsim.api.core.v01.population; -import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; - public interface BasicPlan { - void setScore( Double score ); + String UNDEFINED_PLAN_TYPE = "undefined"; + + void setScore(Double score ); Double getScore(); @@ -33,7 +33,7 @@ public interface BasicPlan { * Plan type, which may be used to ensure there is at least one plan of a certain type. */ default String getType() { - return GenericWorstPlanForRemovalSelector.UNDEFINED_TYPE; + return UNDEFINED_PLAN_TYPE; } - + } diff --git a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java index 49d4971caa1..61e2df24a2e 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java +++ b/matsim/src/main/java/org/matsim/core/replanning/selectors/GenericWorstPlanForRemovalSelector.java @@ -28,6 +28,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.matsim.api.core.v01.population.BasicPlan.UNDEFINED_PLAN_TYPE; + /** *

Selects the worst plan of a person (most likely for removal), but respects * the set plan types in a way the no plan is selected that is the last one of @@ -41,8 +43,6 @@ */ public class GenericWorstPlanForRemovalSelector implements PlanSelector { - public static final String UNDEFINED_TYPE = "undefined"; - @Override public T selectPlan(HasPlansAndId person) { @@ -53,7 +53,7 @@ public T selectPlan(HasPlansAndId person) { for (T plan : person.getPlans()) { String type = plan.getType(); if ( type==null ) { - type = UNDEFINED_TYPE ; + type = UNDEFINED_PLAN_TYPE; } typeCounts.merge( type, 1, ( a, b ) -> a + b ); } @@ -64,7 +64,7 @@ public T selectPlan(HasPlansAndId person) { String type = plan.getType(); if ( type==null ) { - type = UNDEFINED_TYPE; + type = UNDEFINED_PLAN_TYPE; } if ( typeCounts.get( type ) > 1) { // (if we have more than one plan of the same type:)