20 package org.matsim.core.replanning.annealing;
22 import java.io.BufferedWriter;
23 import java.io.IOException;
25 import java.util.stream.Collectors;
26 import jakarta.inject.Inject;
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
55 private static final String
COL_IT =
"it";
59 private final String
sep;
79 return !(selectors.contains(strategyName) ||
80 ((strategyName.toLowerCase().contains(
"selector") || strategyName.toLowerCase().contains(
"expbeta")) && !strategyName.contains(
"_")));
85 header =
new ArrayList<>();
91 var mapPerSubpopulation = this.currentValuesPerSubpopulation.computeIfAbsent(av.getAnnealParameter(),a->
new HashMap<>());
92 mapPerSubpopulation.put(av.getSubpopulation(),av.getStartValue());
93 String subpopulationString = av.getSubpopulation()!=null?
"_"+av.getSubpopulation() :
"";
94 header.add(av.getAnnealParameter().name()+subpopulationString);
97 .filter(s -> Objects.equals(av.getSubpopulation(), s.getSubpopulation()))
98 .map(strategySettings -> strategySettings.getStrategyName()+subpopulationString)
99 .collect(Collectors.toList()));
107 bw.write(COL_IT + sep + header.stream().collect(Collectors.joining(sep)));
109 }
catch (IOException e) {
118 Map<String, String> annealStats =
new HashMap<>();
121 if (this.currentIter > 0) {
122 switch (av.getAnnealType()) {
124 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
125 v * av.getShapeFactor());
128 int halfLifeIter = av.getHalfLife() <= 1.0 ?
129 (int) (av.getHalfLife() * this.
innovationStop) : (
int) av.getHalfLife();
130 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
131 av.getStartValue() / Math.exp((
double) this.currentIter / halfLifeIter));
134 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
135 av.getStartValue() / Math.pow(this.currentIter, av.getShapeFactor()));
138 halfLifeIter = av.getHalfLife() <= 1.0 ?
139 (int) (av.getHalfLife() * this.
innovationStop) : (
int) av.getHalfLife();
140 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
141 av.getEndValue() + (av.getStartValue() - av.getEndValue()) /
142 (1 + Math.exp(av.getShapeFactor() * (this.currentIter - halfLifeIter))));
145 double slope = (av.getStartValue() - av.getEndValue())
147 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
148 this.currentIter * slope + av.getStartValue());
153 throw new IllegalArgumentException();
156 log.info(
"Annealling will be performed on parameter " + av.getAnnealParameter() +
". Subpopulation: "+av.getSubpopulation()+
157 ". Value: " +this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).
get(av.getSubpopulation()));
159 this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).compute(av.getSubpopulation(), (k, v) ->
160 Math.max(v, av.getEndValue()));
162 double annealValue = this.currentValuesPerSubpopulation.get(av.getAnnealParameter()).
get(av.getSubpopulation());
163 String subpopulationString = av.getSubpopulation()!=null?
"_"+av.getSubpopulation() :
"";
165 annealStats.put(av.getAnnealParameter().name()+subpopulationString, String.format(Locale.US,
"%.4f", annealValue));
166 anneal(event, av, annealValue, annealStats);
174 bw.write(Integer.toString(currentIter));
175 for (String v : header) {
176 String s = sep + annealStats.get(v);
180 }
catch (IOException e) {
192 case PathSizeLogitBeta:
198 case globalInnovationRate:
199 if (this.currentIter > this.innovationStop) {
207 annealStats.put(ss.getStrategyName()+subpopulationString, String.format(Locale.US,
"%.4f", annealValues.get(i)));
212 annealStats.put(av.
getAnnealParameter().name()+subpopulationString, String.format(Locale.US,
"%.4f",
216 throw new IllegalArgumentException();
221 List<Double> annealValues =
new ArrayList<>();
224 List<GenericPlanStrategy<Plan, Person>> strategies = stratMan.
getStrategies(subpopulation);
226 double weight = stratMan.
getWeights(subpopulation).get(strategies.indexOf(strategy));
228 weight = totalInnovationWeights > 0 ?
229 globalInnovationValue * weight / totalInnovationWeights : 0.0;
231 weight = totalSelectorWeights > 0 ?
232 (1 - globalInnovationValue) * weight / totalSelectorWeights : 0.0000001;
235 annealValues.add(weight);
244 List<GenericPlanStrategy<Plan, Person>> strategies = stratMan.
getStrategies(subpopulation);
245 double totalWeights = 0.0;
247 double weight = stratMan.
getWeights(subpopulation).get(strategies.indexOf(strategy));
251 totalWeights += weight;
256 totalWeights += weight;
260 totalWeights += weight;
274 double totalWeights = 0.0;
276 if (Objects.equals(strategy.getSubpopulation(), subpopulation)) {
285 totalWeights += strategy.getWeight();
289 totalWeights += strategy.getWeight();
307 int maxIter = strategy.getDisableAfter();
308 if ((maxIter > globalInnovationDisableAfter || maxIter == -1) &&
isInnovationStrategy(strategy.getStrategyName())) {
309 maxIter = globalInnovationDisableAfter;
312 if (innoStop == -1) {
316 if (innoStop != maxIter) {
317 log.warn(
"Different 'Disable After Interation' values are set for different replaning modules." +
318 " Annealing doesn't support this function and will be performed according to the 'Disable After Interation' setting of the first replanning module " +
319 "or 'globalInnovationDisableAfter', which ever value is lower.");
328 switch (av.getAnnealParameter()) {
332 case PathSizeLogitBeta:
338 case globalInnovationRate:
341 if (innovationWeights + selectorWeights != 1.0) {
342 log.warn(
"Initial sum of strategy weights different from 1.0. Rescaling.");
343 double innovationStartValue = av.getStartValue() == null ? innovationWeights : av.getStartValue();
349 throw new IllegalArgumentException();
351 if (av.getStartValue() == null) {
352 log.warn(
"Anneal start value not set. Config value will be used.");
353 av.setStartValue(configValue);
358 double selectorStartValue = 1 - innovationStartValue;
360 List<GenericPlanStrategy<Plan, Person>> strategies = stratMan.
getStrategies(subpopulation);
362 double weight = stratMan.
getWeights(subpopulation).get(strategies.indexOf(strategy));
364 weight = innovationStartValue > 0 ?
365 weight / innovationStartValue : 0.0;
367 weight = selectorStartValue > 0 ?
368 weight / selectorStartValue : 0.0;
375 if (Objects.equals(strategy.getSubpopulation(), subpopulation)) {
378 weight = innovationStartValue > 0 ?
379 weight / innovationStartValue : 0.0;
381 weight = selectorStartValue > 0 ?
382 weight / selectorStartValue : 0.0;
384 strategy.setWeight(weight);
389 private enum StratType {allInnovation, allSelectors, allStrategies}
void setLearningRate(double learningRate)
void notifyStartup(StartupEvent event)
ReplanningAnnealer(Config config)
void anneal(IterationStartsEvent event, AnnealingVariable av, double annealValue, Map< String, String > annealStats)
static< T extends ConfigGroup > T addOrGetModule(Config config, Class< T > moduleClass)
static boolean isInnovationStrategy(String strategyName)
List< Double > annealReplanning(double globalInnovationValue, StrategyManager stratMan, String subpopulation)
void notifyIterationStarts(IterationStartsEvent event)
final List< GenericPlanStrategy< Plan, Person > > getStrategies(final String subpopulation)
double getFractionOfIterationsToDisableInnovation()
double getPathSizeLogitBeta()
List< AnnealingVariable > getAllAnnealingVariables()
OutputDirectoryHierarchy outputDirectoryHierarchy
final ScoringConfigGroup scoring()
String SelectPathSizeLogit
static BufferedWriter getBufferedWriter(URL url, Charset charset, boolean append)
static final String ANNEAL_FILENAME
final List< Double > getWeights(final String subpopulation)
double getStrategyWeights(Config config, String subpopulation, StratType stratType)
void checkAndFixStartValue(ReplanningAnnealerConfigGroup.AnnealingVariable av, StartupEvent event)
void setBrainExpBeta(double brainExpBeta)
String getSubpopulation()
final ReplanningAnnealerConfigGroup saConfig
static final String COL_IT
MatsimServices getServices()
void writeIterationstats(int currentIter, Map< String, String > annealStats)
static BufferedWriter getAppendingBufferedWriter(String filename)
int getInnovationStop(Config config)
void setPathSizeLogitBeta(double beta)
StrategyManager getStrategyManager()
boolean removeParameterSet(final ConfigGroup set)
final EnumMap< AnnealParameterOption, Map< String, Double > > currentValuesPerSubpopulation
final boolean changeWeightOfStrategy(final GenericPlanStrategy< Plan, Person > strategy, final String subpopulation, final double newWeight)
final ReplanningConfigGroup replanning()
void rescaleStartupWeights(double innovationStartValue, Config config, StrategyManager stratMan, String subpopulation)
final String getOutputFilename(final String filename)
final ControllerConfigGroup controller()
final GlobalConfigGroup global()
StrategySettings getStrategySettings(final Id< StrategySettings > index, final boolean createIfMissing)
double getStrategyWeights(StrategyManager stratMan, String subpopulation, StratType stratType)
AnnealParameterOption getAnnealParameter()
String getDefaultDelimiter()