MATSIM
ExpBetaPlanChanger.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * ExpBetaPlanChanger.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.replanning.selectors;
22 
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
28 
34 public final class ExpBetaPlanChanger<T extends BasicPlan, I> implements PlanSelector<T, I> {
35  private static final Logger log = LogManager.getLogger(ExpBetaPlanChanger.class);
36 
37  public static final class Factory<T extends BasicPlan,I> {
38  private double beta = 1.;
40  return new ExpBetaPlanChanger<>( beta );
41  }
42  public Factory<T,I> setBetaValue( double beta ){
43  this.beta = beta;
44  return this;
45  }
46  }
47 
48  private final double beta;
49  static boolean betaWrnFlag = true ;
50  static boolean scoreWrnFlag = true ;
51 
52 
56  public ExpBetaPlanChanger(double beta) {
57  this.beta = beta;
58  }
59 
64  @Override
65  public T selectPlan(final HasPlansAndId<T, I> person) {
66  // current plan and random plan:
67  T currentPlan = person.getSelectedPlan();
68  T otherPlan = new RandomPlanSelector<T, I>().selectPlan(person);
69 
70  if (currentPlan == null) {
71  // this case should only happen when the agent has no plans at all
72  return null;
73  }
74 
75  if ((currentPlan.getScore() == null) || (otherPlan.getScore() == null)) {
76  /* With the previous behavior, Double.NaN was returned if no score was available.
77  * This resulted in weight=NaN below as well, and then ultimately in returning
78  * the currentPlan---what we're doing right now as well.
79  */
80  if ( currentPlan.getScore()!=null && otherPlan.getScore()==null ) {
81  if ( scoreWrnFlag ) {
82  log.error( "yyyyyy not switching to other plan although it needs to be explored. "
83  + "Possibly a serious bug; ask kai if you encounter this. kai, sep'10" ) ;
84  scoreWrnFlag = false ;
85  }
86  }
87  return currentPlan;
88  }
89 
90  // defending against NaN (which should not happen, but happens):
91  if ( currentPlan.getScore().isNaN() ) {
92  return otherPlan ;
93  }
94  if ( otherPlan.getScore().isNaN() ) {
95  return currentPlan ;
96  }
97 
98  double currentScore = currentPlan.getScore();
99  double otherScore = otherPlan.getScore();
100 
101  if ( betaWrnFlag ) {
102  log.warn("Would make sense to revise this once more. See comments in code. kai, nov08") ;
103  /* Gunnar says, rightly I think, that what is below hits the "0.01*weight > 1" threshold fairly quickly.
104  * An alternative might be to divide by exp(0.5*beta*oS)+exp(0.5*beta*cS), or the max of these two numbers. But:
105  * (1) someone would need to go through the theory to make sure that we remain within what we have said before
106  * (convergence to logit and proba of jump between equal options = 0.01
107  * (2) someone would need to test if the "traffic" results are similar
108  */
109  betaWrnFlag = false ;
110  }
111  double weight = Math.exp( 0.5 * this.beta * (otherScore - currentScore) );
112  // (so far, this is >1 if otherScore>currentScore, and <=1 otherwise)
113  // (beta is the slope (strength) of the operation: large beta means strong reaction)
114 
115  if (MatsimRandom.getRandom().nextDouble() < 0.01*weight ) { // as of now, 0.01 is hardcoded (proba to change when both
116  // scores are the same)
117  return otherPlan;
118  }
119  return currentPlan;
120  }
121 
122 }