21 package org.matsim.core.scoring;
23 import com.google.inject.Inject;
24 import gnu.trove.TDoubleCollection;
25 import gnu.trove.iterator.TDoubleIterator;
26 import gnu.trove.list.array.TDoubleArrayList;
64 import java.io.BufferedWriter;
65 import java.io.IOException;
66 import java.util.List;
67 import java.util.Map.Entry;
68 import java.util.concurrent.atomic.AtomicReference;
80 final class ScoringFunctionsForPopulation
implements BasicEventHandler {
82 private final Population population;
83 private final ScoringFunctionFactory scoringFunctionFactory;
85 private final EventsToLegs legsDelegate;
86 private final EventsToActivities actsDelegate;
88 private final IdMap<Person, ScoringFunction> agentScorers =
new IdMap<>(Person.class);
89 private final IdMap<Person, TDoubleCollection> partialScores =
new IdMap<>(Person.class);
90 private final AtomicReference<Throwable> exception =
new AtomicReference<>();
91 private final IdMap<Person, Plan> tripRecords =
new IdMap<>(Person.class);
93 private final Vehicle2DriverEventHandler vehicles2Drivers =
new Vehicle2DriverEventHandler();
96 ScoringFunctionsForPopulation(ControlerListenerManager controlerListenerManager, EventsManager eventsManager, EventsToActivities eventsToActivities, EventsToLegs eventsToLegs,
97 Population population, ScoringFunctionFactory scoringFunctionFactory, Config config) {
98 ControllerConfigGroup controllerConfigGroup = config.controller();
100 if (controllerConfigGroup.getEventTypeToCreateScoringFunctions() == ControllerConfigGroup.EventTypeToCreateScoringFunctions.IterationStarts) {
101 controlerListenerManager.addControlerListener((IterationStartsListener) event -> init());
102 }
else if (controllerConfigGroup.getEventTypeToCreateScoringFunctions() == ControllerConfigGroup.EventTypeToCreateScoringFunctions.BeforeMobsim) {
103 controlerListenerManager.addControlerListener((BeforeMobsimListener) event -> init());
105 throw new RuntimeException(
"Unknown approach when to create the scoring functions for population. Aborting...");
108 this.population = population;
109 this.legsDelegate = eventsToLegs;
110 this.actsDelegate = eventsToActivities;
111 this.scoringFunctionFactory = scoringFunctionFactory;
113 eventsManager.addHandler(
this);
114 eventsToActivities.addActivityHandler(this::handleActivity);
115 eventsToLegs.addLegHandler(this::handleLeg);
118 private void init() {
119 for (Person person : this.population.getPersons().values()) {
120 this.agentScorers.put(person.getId(), this.scoringFunctionFactory.createNewScoringFunction(person ) );
121 this.partialScores.put(person.getId(),
new TDoubleArrayList());
122 this.tripRecords.put(person.getId(), PopulationUtils.createPlan());
127 public void handleEvent(Event o) {
131 if (o instanceof HasPersonId) {
132 ScoringFunction scoringFunction = getScoringFunctionForAgent(((HasPersonId) o).getPersonId());
133 if (scoringFunction != null) {
134 if (o instanceof PersonStuckEvent) {
135 scoringFunction.agentStuck(o.getTime());
136 }
else if (o instanceof PersonMoneyEvent) {
137 scoringFunction.addMoney(((PersonMoneyEvent) o).getAmount());
140 }
else if (o instanceof PersonScoreEvent) {
141 scoringFunction.addScore(((PersonScoreEvent) o).getAmount());
143 scoringFunction.handleEvent(o);
149 if (o instanceof VehicleEntersTrafficEvent) {
150 this.vehicles2Drivers.handleEvent((VehicleEntersTrafficEvent) o);
152 if (o instanceof VehicleLeavesTrafficEvent) {
153 this.vehicles2Drivers.handleEvent((VehicleLeavesTrafficEvent) o);
164 if (o instanceof LinkEnterEvent) {
165 Id<Vehicle> vehicleId = ((LinkEnterEvent)o).getVehicleId();
166 Id<Person> driverId = this.vehicles2Drivers.getDriverOfVehicle(vehicleId);
167 ScoringFunction scoringFunction = getScoringFunctionForAgent( driverId );
169 if (scoringFunction != null) {
170 scoringFunction.handleEvent(o);
181 if (o instanceof ActivityStartEvent) this.handleActivityStart((ActivityStartEvent) o);
182 if (o instanceof ActivityEndEvent) this.actsDelegate.handleEvent((ActivityEndEvent) o);
184 if (o instanceof PersonDepartureEvent) this.legsDelegate.handleEvent((PersonDepartureEvent) o);
185 if (o instanceof PersonArrivalEvent) this.legsDelegate.handleEvent((PersonArrivalEvent) o);
186 if (o instanceof LinkEnterEvent) this.legsDelegate.handleEvent((LinkEnterEvent) o);
187 if (o instanceof TeleportationArrivalEvent) this.legsDelegate.handleEvent((TeleportationArrivalEvent) o);
188 if (o instanceof TransitDriverStartsEvent) this.legsDelegate.handleEvent((TransitDriverStartsEvent) o);
189 if (o instanceof PersonEntersVehicleEvent) this.legsDelegate.handleEvent((PersonEntersVehicleEvent) o);
190 if (o instanceof VehicleArrivesAtFacilityEvent) this.legsDelegate.handleEvent((VehicleArrivesAtFacilityEvent) o);
191 if (o instanceof VehicleEntersTrafficEvent) this.legsDelegate.handleEvent((VehicleEntersTrafficEvent) o);
192 if (o instanceof VehicleLeavesTrafficEvent) this.legsDelegate.handleEvent((VehicleLeavesTrafficEvent) o);
195 private void handleActivityStart(ActivityStartEvent event) {
196 this.actsDelegate.handleEvent(event);
197 if (!StageActivityTypeIdentifier.isStageActivity( event.getActType() ) ) {
198 this.callTripScoring(event);
202 private void callTripScoring(ActivityStartEvent event) {
203 Plan plan = this.tripRecords.get(event.getPersonId());
206 Activity activity = PopulationUtils.createActivityFromLinkId(event.getActType(),
event.getLinkId());
207 activity.setStartTime(event.getTime());
208 plan.addActivity(activity);
209 final List<Trip> trips = TripStructureUtils.getTrips(plan);
215 ScoringFunction scoringFunction = ScoringFunctionsForPopulation.this.getScoringFunctionForAgent(event.getPersonId());
216 for (Trip trip : trips) {
218 scoringFunction.handleTrip(trip);
223 plan.getPlanElements().clear();
227 void handleLeg(PersonExperiencedLeg o) {
228 Id<Person> agentId = o.getAgentId();
229 Leg leg = o.getLeg();
230 ScoringFunction scoringFunction = ScoringFunctionsForPopulation.this.getScoringFunctionForAgent(agentId);
231 if (scoringFunction != null) {
232 scoringFunction.handleLeg(leg);
233 TDoubleCollection partialScoresForAgent = this.partialScores.get(agentId);
234 partialScoresForAgent.add(scoringFunction.getScore());
236 Plan plan = this.tripRecords.get( agentId ) ;
242 void handleActivity(PersonExperiencedActivity o) {
243 Id<Person> agentId = o.getAgentId();
244 Activity activity = o.getActivity();
245 ScoringFunction scoringFunction = ScoringFunctionsForPopulation.this.getScoringFunctionForAgent(agentId);
246 if (scoringFunction != null) {
247 scoringFunction.handleActivity(activity);
248 TDoubleCollection partialScoresForAgent = this.partialScores.get(agentId);
249 partialScoresForAgent.add(scoringFunction.getScore());
252 Plan plan = this.tripRecords.get( agentId );
254 plan.addActivity( activity );
268 ScoringFunction getScoringFunctionForAgent(
final Id<Person> agentId) {
269 return this.agentScorers.get(agentId);
272 void finishScoringFunctions() {
274 Throwable throwable = this.exception.get();
275 if (throwable != null) {
277 throw ((RuntimeException) throwable);
279 throw new RuntimeException(throwable);
282 for (ScoringFunction sf : this.agentScorers.values()) {
285 for (Entry<Id<Person>, TDoubleCollection> entry : this.partialScores.entrySet()) {
286 entry.getValue().add(this.getScoringFunctionForAgent(entry.getKey()).getScore());
290 void writePartialScores(String iterationFilename) {
291 try ( BufferedWriter out = IOUtils.getBufferedWriter(iterationFilename) ) {
292 for (Entry<Id<Person>, TDoubleCollection> entry : this.partialScores.entrySet()) {
293 out.write(entry.getKey().toString());
294 TDoubleIterator iterator = entry.getValue().iterator();
295 while (iterator.hasNext()) {
297 out.write(String.valueOf(iterator.next()));
299 out.write(IOUtils.NATIVE_NEWLINE);
301 }
catch (IOException e) {
302 throw new RuntimeException(e);
307 public void reset(
int iteration) {
308 this.legsDelegate.reset(iteration);
309 this.actsDelegate.reset(iteration);