MATSIM
PathSizeLogitSelector.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * PathSizeLogitSelector.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 java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 
28 import org.matsim.api.core.v01.Id;
37 
45 public final class PathSizeLogitSelector extends AbstractPlanSelector {
46 
47  private final double pathSizeLogitExponent;
48  private final double logitScaleFactor;
49  private Network network;
50 
51  public PathSizeLogitSelector( final double pathSizeLogitExponent, final double logitScaleFactor, final Network network ) {
52  this.pathSizeLogitExponent = pathSizeLogitExponent ;
53  this.logitScaleFactor = logitScaleFactor ;
54  this.network = network ;
55  }
56 
57  public PathSizeLogitSelector(final ScoringConfigGroup config, final Network network) {
58  this( config.getPathSizeLogitBeta(), config.getBrainExpBeta(), network ) ;
59  }
60 
61  //updates the path size logit weights
62  @Override
63  protected Map<Plan,Double> calcWeights(final List<? extends Plan> plans ) {
64  // ("plans" is the list of plans of a single person)
65 
66  Map<Plan,Double> weights = new HashMap<Plan,Double>() ;
67 
68  double maxScore = Double.NEGATIVE_INFINITY;
69 
70  HashMap<Id<Link>, ArrayList<Double>> linksInTime = new HashMap<>();
71  // (a data structure that memorizes possible leg start times for link utilization (??))
72 
73  HashMap<Integer,Double> planLength = new HashMap<Integer, Double>();
74  // (a data structure that memorizes the total travel distance of each plan)
75  // (yyyy is it obvious that no two plans can have the same hash code? what happens if they do? kai, oct'12)
76  // (why not just <Plan,Double>?????)
77 
78  //this gets the choice sets C_n
79  //TODO [GL] since the lack of information in Route(),
80  //the very first and the very last link of a path will be ignored - gl
81  //dg, 09-2013: as first and last link are equal for all routes between to activities this is no major issue
82 
83  for (Plan plan : plans) {
84 
85  if (plan.getScore() > maxScore) maxScore = plan.getScore();
86 
87  double pathSize = 0;
88  double currentEndTime = 0.0;
89  for (PlanElement pe : plan.getPlanElements()) {
90  if (pe instanceof Leg) {
91  Leg leg = (Leg) pe;
92  currentEndTime = leg.getDepartureTime().seconds();
93 
95  // (yyyy this will fail when the route is not a network route. kai, oct'12)
96 
97  pathSize += RouteUtils.calcDistanceExcludingStartEndLink(r, network);
98  // (i.e. pathSize will be the sum over all routes of the plan)
99 
100  for (Id<Link> linkId : r.getLinkIds()){
101  ArrayList<Double> lit = linksInTime.get(linkId);
102  if (lit == null){
103  lit = new ArrayList<Double>();
104  linksInTime.put(linkId, lit);
105  }
106  lit.add(currentEndTime);
107  }
108  }
109  }
110  planLength.put(plan.hashCode(), pathSize);
111  }
112 
113  for (Plan plan : plans) {
114 
115  double tmp = 0;
116  for (PlanElement pe : plan.getPlanElements()) {
117  if (pe instanceof Leg) {
118  Leg leg = (Leg) pe;
119  double currentTime = leg.getDepartureTime().seconds();
120  NetworkRoute route = (NetworkRoute) leg.getRoute();
121  for (Id<Link> linkId : route.getLinkIds()){
122  double denominator = 0;
123  for (double dbl : linksInTime.get(linkId)){
124  //TODO this is just for testing (those legs where the departure time differs more then 3600 seconds will not compared to each other) - need a
125  //little bit to brood on it - gl
126  // An alternative might be to use a kernal, e.g. a Gaussian. Something like
127  // denominator += exp( (dbl-currentTime)^2 / sigma^2 ) . kai, oct'12
128  if (Math.abs(dbl - currentTime) <= 3600)
129  denominator++;
130  }
131  // (the meaning seems to be: for each link that the plan uses, it checks how many other times the
132  // same link is used by a leg that has roughly the same departure time (*))
133 
134  Link link = network.getLinks().get(linkId);
135  tmp += link.getLength() / denominator;
136  // (for a plan, the weight of a link is divided by the number of times it is used)
137  }
138  }
139  }
140  // tmp is now a number that contains the ``reduced'' travel distance of the plan. Divide it by the full travel distance
141  // of the plan, and take to the power of this.beta:
142  double PSi = Math.pow(tmp/planLength.get(plan.hashCode()), this.pathSizeLogitExponent);
143 
144  double weight;
145  if (Double.isInfinite(maxScore)) {
146  // (isInfinite(x) also returns true when x==-Infinity)
147 
148  // likely that wc.maxScore == -Infinity, and thus plan.getScoreAsPrimitiveType() also == -Infinity, handle it like any other case where getScore() == maxScore
149  // I do not understand the line above. kai, oct'12
150 
151  weight = PSi;
152  // (yy I do not understand. Presumably, wc.maxScore may be -Infinity, in which case ALL plan scores are -Infinity
153  // (or NaN or null or something similar). In this case, plans are simply weighted by their PSi, so that
154  // overlapping plans get less weight than very different plans. kai, oct'12)
155  } else {
156  weight = Math.exp(this.logitScaleFactor * (plan.getScore() - maxScore))*PSi;
157  // (this is essentially $PSi * exp( tau * score )$, the "-wc.maxScore" is (presumably) the computational trick
158  // to avoid overflow)
159  }
160 
161  if (weight <= 0.0) weight = 0;
162  // (yy how can weight become negative?? kai, oct'12)
163 
164  // the weight is memorized; the sum of all weights in computed. Choice will be based on those weights
165  weights.put( plan, weight) ;
166  }
167 
168  return weights ;
169  }
170 
171 }
PathSizeLogitSelector(final double pathSizeLogitExponent, final double logitScaleFactor, final Network network)
Map< Id< Link >, ? extends Link > getLinks()
static double calcDistanceExcludingStartEndLink(final NetworkRoute route, final Network network)
Map< Plan, Double > calcWeights(final List<? extends Plan > plans)
PathSizeLogitSelector(final ScoringConfigGroup config, final Network network)