LocationBasedParticipationModel.java
package org.matsim.episim.model.activity;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.episim.EpisimConfigGroup;
import org.matsim.episim.EpisimPerson;
import org.matsim.episim.policy.Restriction;
import org.matsim.facilities.ActivityFacility;
import java.util.*;
/**
* Location based participation model restricts activity participation by the local remaining fraction corresponding
* to the location of the ActivityFacility, if available. Otherwise, the global remaining fraction is used.
*/
public class LocationBasedParticipationModel implements ActivityParticipationModel {
private final SplittableRandom rnd;
private final EpisimConfigGroup episimConfig;
private ImmutableMap<String, Restriction> im;
/**
* Map of each ActivityFacility with the corresponding subdistrict
*/
private final Map<String, String> subdistrictFacilities;
@Inject
public LocationBasedParticipationModel(SplittableRandom rnd, EpisimConfigGroup episimConfig, Scenario scenario) {
this.rnd = rnd;
this.episimConfig = episimConfig;
if (episimConfig.getActivityHandling() == EpisimConfigGroup.ActivityHandling.duringContact)
throw new IllegalStateException("Participation model can only be used with activityHandling startOfDay");
if (episimConfig.getDistrictLevelRestrictions() != EpisimConfigGroup.DistrictLevelRestrictions.yes) {
throw new IllegalStateException("LocationBasedParticipationModel can only be used if location based restrictions are used");
}
subdistrictFacilities = new HashMap<>();
if (scenario != null && !scenario.getActivityFacilities().getFacilities().isEmpty()) {
for (ActivityFacility facility : scenario.getActivityFacilities().getFacilities().values()) {
String subdistrictAttributeName = episimConfig.getDistrictLevelRestrictionsAttribute();
String subdistrict = (String) facility.getAttributes().getAttribute(subdistrictAttributeName);
if (subdistrict != null) {
this.subdistrictFacilities.put(facility.getId().toString(), subdistrict);
}
}
}
}
@Override
public void setRestrictionsForIteration(int iteration, ImmutableMap<String, Restriction> im) {
this.im = im;
}
@Override
public void updateParticipation(EpisimPerson person, BitSet trajectory, int offset, List<EpisimPerson.PerformedActivity> activities) {
for (int i = 0; i < activities.size(); i++) {
String context = activities.get(i).params.getContainerName();
Id<ActivityFacility> facilityId = activities.get(i).getFacilityId();
Restriction restriction = im.get(context);
double remainingFraction = restriction.getRemainingFraction();
// Replaces global remaining fraction with local one, if applicable
if (facilityId != null) {
if (subdistrictFacilities.containsKey(facilityId.toString())) {
String subdistrict = subdistrictFacilities.get(facilityId.toString());
if (restriction.getLocationBasedRf().containsKey(subdistrict)) {
remainingFraction = restriction.getLocationBasedRf().get(subdistrict);
}
}
}
if (remainingFraction == 1.0)
trajectory.set(offset + i, true);
else if (remainingFraction == 0.0)
trajectory.set(offset + i, false);
else
trajectory.set(offset + i, rnd.nextDouble() < remainingFraction);
}
}
}