Skip to content

Commit 00bb005

Browse files
Merge pull request #131 from moia-oss/master
Update MATSim CW 7
2 parents 543c9b9 + 2ead4d2 commit 00bb005

File tree

4 files changed

+195
-44
lines changed

4 files changed

+195
-44
lines changed

contribs/application/src/main/java/org/matsim/application/analysis/CheckPopulation.java

+106-19
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
import org.matsim.core.population.PopulationUtils;
2020
import org.matsim.core.router.TripStructureUtils;
2121
import org.matsim.core.utils.geometry.CoordUtils;
22+
import org.matsim.core.utils.misc.OptionalTime;
2223
import picocli.CommandLine;
2324

2425
import java.nio.file.Files;
2526
import java.nio.file.Path;
2627
import java.util.*;
27-
import java.util.stream.Collectors;
2828

2929
@CommandLine.Command(
3030
name = "check-population",
@@ -121,16 +121,16 @@ public Integer call() throws Exception {
121121

122122
List<? extends Person> agents = population.getPersons().values().stream()
123123
.filter(filter)
124-
.collect(Collectors.toList());
124+
.toList();
125125

126126
// agents with trips
127127
List<? extends Person> mobileAgents = agents.stream()
128-
.filter(a -> TripStructureUtils.getTrips(a.getSelectedPlan()).size() > 0)
129-
.collect(Collectors.toList());
128+
.filter(a -> !TripStructureUtils.getTrips(a.getSelectedPlan()).isEmpty())
129+
.toList();
130130

131131
List<TripStructureUtils.Trip> trips = agents.stream().flatMap(
132132
agent -> TripStructureUtils.getTrips(agent.getSelectedPlan().getPlanElements()).stream()
133-
).collect(Collectors.toList());
133+
).toList();
134134

135135
log.info("Number of trips: \t\t{}", trips.size());
136136
log.info("Avg. trips per agent: \t{}", (double) trips.size() / agents.size());
@@ -154,6 +154,8 @@ public Integer call() throws Exception {
154154
counts.forEach((k, v) -> log.info("\t{}-m: {} ({}%)", k.intValue(), v, Math.round((v * 1000d) / trips.size()) / 10d));
155155

156156
sep();
157+
log.info("Activities:");
158+
log.info("");
157159

158160
Object2IntMap<String> acts = new Object2IntAVLTreeMap<>();
159161
Object2IntMap<String> firstAct = new Object2IntAVLTreeMap<>();
@@ -164,35 +166,98 @@ public Integer call() throws Exception {
164166

165167
List<TripStructureUtils.Subtour> subtours = new ArrayList<>();
166168

169+
NavigableSet<Double> timeGroups = new TreeSet<>(List.of(0d, 1d, 2d, 3d, 4d, 5d, 6d, 7d, 8d, 9d, 10d, 11d,
170+
12d, 13d, 14d, 15d, 16d, 17d, 18d, 19d, 20d, 21d, 22d, 23d));
171+
Map<String, Double2IntMap> actStartTimes = new HashMap<>();
172+
Map<String, Double2IntMap> actEndTimes = new HashMap<>();
173+
int noStartTime = 0;
174+
int noEndTime = 0;
175+
int noStartAndEndTime = 0;
176+
int zeroDurationActs = 0;
177+
int numberOfActs = 0;
178+
167179
for (Person agent : agents) {
168180

169181
// if there are no facility or link ids. the coordinate is used as proxy id.
170182
for (PlanElement el : agent.getSelectedPlan().getPlanElements()) {
171-
if (el instanceof Activity) {
172-
Activity act = (Activity) el;
173-
if (act.getFacilityId() == null && act.getLinkId() == null) {
174-
act.setLinkId(Id.createLinkId(act.getCoord().toString()));
175-
}
183+
if (el instanceof Activity act && act.getFacilityId() == null && act.getLinkId() == null) {
184+
act.setLinkId(Id.createLinkId(act.getCoord().toString()));
176185
}
177186
}
178187

179188
subtours.addAll(TripStructureUtils.getSubtours(agent.getSelectedPlan()));
180189

181-
List<String> activities = TripStructureUtils.getActivities(agent.getSelectedPlan(), TripStructureUtils.StageActivityHandling.ExcludeStageActivities)
182-
.stream().map(CheckPopulation::actName).collect(Collectors.toList());
190+
List<Activity> activities = new ArrayList<>(TripStructureUtils.getActivities(agent.getSelectedPlan(), TripStructureUtils.StageActivityHandling.ExcludeStageActivities));
183191

184-
if (activities.size() == 0)
192+
if (activities.isEmpty())
185193
continue;
186194

187-
firstAct.mergeInt(activities.get(0), 1, Integer::sum);
188-
lastAct.mergeInt(activities.get(activities.size() - 1), 1, Integer::sum);
189-
activities.forEach(act -> acts.mergeInt(act, 1, Integer::sum));
195+
firstAct.mergeInt(actName(activities.getFirst()), 1, Integer::sum);
196+
lastAct.mergeInt(actName(activities.getLast()), 1, Integer::sum);
197+
activities.forEach(act -> acts.mergeInt(actName(act), 1, Integer::sum));
198+
199+
for (Activity act : Sets.newHashSet(activities)) {
200+
String name = actName(act);
201+
haveActivity.mergeInt(name, 1, Integer::sum);
202+
203+
boolean hasNoStartTime = false;
204+
boolean hasNoEndTime = false;
205+
206+
// find time bin for start and end of act or increase counter if no start or end time is defined
207+
hasNoStartTime = categorizeTime(act.getStartTime(), timeGroups, actStartTimes, name, hasNoStartTime);
208+
hasNoEndTime = categorizeTime(act.getEndTime(), timeGroups, actEndTimes, name, hasNoEndTime);
209+
210+
// increase counters
211+
if (hasNoStartTime || hasNoEndTime) {
212+
noStartTime += hasNoStartTime ? 1 : 0;
213+
noEndTime += hasNoEndTime ? 1 : 0;
214+
noStartAndEndTime += (hasNoStartTime && hasNoEndTime) ? 1 : 0;
215+
}
190216

191-
for (String act : Sets.newHashSet(activities)) {
192-
haveActivity.mergeInt(act, 1, Integer::sum);
217+
double duration = 0.;
218+
if (act.getStartTime().isDefined() && act.getEndTime().isDefined()) {
219+
duration = act.getEndTime().seconds() - act.getStartTime().seconds();
220+
} else if (act.getStartTime().isDefined() && !act.getEndTime().isDefined()) {
221+
// initiate as 24h in case act is the last act of a plan
222+
double previousActStart = 24 * 3600.;
223+
224+
if (activities.indexOf(act) != activities.indexOf(activities.getLast())) {
225+
previousActStart = activities.get(activities.indexOf(act) + 1).getStartTime().seconds();
226+
}
227+
duration = previousActStart - act.getStartTime().seconds();
228+
} else if (act.getEndTime().isDefined() && !act.getStartTime().isDefined()) {
229+
// initiate as 0 in case act is first act of a plan
230+
double previousActEnd = 0.;
231+
if (activities.indexOf(act) != activities.indexOf(activities.getFirst())) {
232+
previousActEnd = activities.get(activities.indexOf(act) - 1).getEndTime().seconds();
233+
}
234+
duration = act.getEndTime().seconds() - previousActEnd;
235+
}
236+
237+
if (duration <= 0.) {
238+
zeroDurationActs++;
239+
}
240+
numberOfActs++;
193241
}
194242
}
195243

244+
log.info("Activity type start time distributions:");
245+
log.info("");
246+
247+
logActTimes(actStartTimes);
248+
249+
log.info("Activity type end time distributions:");
250+
log.info("");
251+
252+
logActTimes(actEndTimes);
253+
254+
log.info("Activities without start time: {}", noStartTime);
255+
log.info("Activities without end time: {}", noEndTime);
256+
log.info("Activities without start AND end time: {}", noStartAndEndTime);
257+
log.info("Activities with duration of <=0s: {} ({}%)", zeroDurationActs, String.format("%.2f", ((double) zeroDurationActs / numberOfActs) * 100));
258+
log.info("");
259+
260+
196261
log.info("Number of persons having at least one activity:");
197262
haveActivity.forEach((k, v) -> log.info("\t{}: {} ({}%)", k, v, Math.round((v * 1000d) / agents.size()) / 10d));
198263

@@ -210,14 +275,36 @@ public Integer call() throws Exception {
210275

211276
long closed = subtours.stream().filter(TripStructureUtils.Subtour::isClosed).count();
212277

213-
if (subtours.size() > 0)
278+
if (!subtours.isEmpty())
214279
log.info("Closed subtours estimate: \t{}%", Math.round((closed * 1000d) / subtours.size()) / 10d);
215280
else
216281
log.info("No info about subtours (link or facilities ids missing)");
217282

218283
return 0;
219284
}
220285

286+
private static void logActTimes(Map<String, Double2IntMap> actTimesMap) {
287+
actTimesMap.forEach((k, v) -> {
288+
double total = v.values().intStream().sum();
289+
290+
// Iterate again to log each entry
291+
v.forEach((subKey, subValue) -> log.info("{} - {}h: {} ({}%)", k, subKey, subValue, String.format("%.2f", (subValue / total) * 100)));
292+
log.info("");
293+
});
294+
}
295+
296+
private boolean categorizeTime(OptionalTime time, NavigableSet<Double> timeGroups, Map<String, Double2IntMap> timesMap, String name, boolean timeNotDefined) {
297+
if (time.isDefined()) {
298+
double group = timeGroups.floor(Math.floor(time.seconds()/3600));
299+
300+
timesMap.putIfAbsent(name, new Double2IntAVLTreeMap());
301+
timesMap.get(name).mergeInt(group, 1, Integer::sum);
302+
} else {
303+
timeNotDefined = true;
304+
}
305+
return timeNotDefined;
306+
}
307+
221308
private static String actName(Activity act) {
222309

223310
int idx = act.getType().lastIndexOf("_");

contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java

+29-24
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.matsim.core.config.ConfigGroup;
4444
import org.matsim.core.router.util.TravelTime;
4545

46+
import com.google.common.base.Preconditions;
4647
import com.google.common.base.Verify;
4748
import com.google.common.collect.Sets;
4849
import org.matsim.core.utils.io.IOUtils;
@@ -93,32 +94,38 @@ public int getZonalTravelTime(Node fromNode, Node toNode, double departureTime)
9394
}
9495

9596
public static FreeSpeedTravelTimeMatrix createFreeSpeedMatrixFromCache(Network dvrpNetwork, ZoneSystem zoneSystem, DvrpTravelTimeMatrixParams params, int numberOfThreads, double qSimTimeStepSize, URL cachePath) {
97+
Preconditions.checkState(cachePath != null);
9698

97-
FreeSpeedTravelTimeMatrix matrix;
98-
if (cachePath != null) {
99-
try {
100-
return new FreeSpeedTravelTimeMatrix(dvrpNetwork, zoneSystem, cachePath);
101-
} catch (FileNotFoundException e) {
102-
log.warn("Freespeed matrix cache file not found, will use as output path for on-the-fly creation.");
103-
}
104-
}
105-
matrix = createFreeSpeedMatrix(dvrpNetwork, zoneSystem, params, numberOfThreads, qSimTimeStepSize);
106-
matrix.write(cachePath, dvrpNetwork);
107-
return matrix;
99+
// we need to do this weird test, because the IOUtils.getInputStream
100+
// only raises UncheckedIOException that we cannot catch here
101+
try {
102+
cachePath.openStream().close();
103+
} catch (FileNotFoundException e) {
104+
log.warn("Freespeed matrix cache file not found, will use as output path for on-the-fly creation.");
105+
106+
var matrix = createFreeSpeedMatrix(dvrpNetwork, zoneSystem, params, numberOfThreads, qSimTimeStepSize);
107+
matrix.write(cachePath, dvrpNetwork);
108+
return matrix;
109+
} catch (IOException e) {
110+
throw new UncheckedIOException(e);
111+
}
112+
113+
InputStream inputStream = IOUtils.getInputStream(cachePath);
114+
return new FreeSpeedTravelTimeMatrix(dvrpNetwork, zoneSystem, inputStream);
108115
}
109116

110-
public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, URL cachePath) throws FileNotFoundException {
117+
public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, InputStream inputStream) {
111118
this.zoneSystem = zoneSystem;
112119

113-
try (DataInputStream inputStream = new DataInputStream(IOUtils.getInputStream(cachePath))) {
120+
try (DataInputStream dataStream = new DataInputStream(inputStream)) {
114121
// number of zones
115-
int numberOfZones = inputStream.readInt();
122+
int numberOfZones = dataStream.readInt();
116123
Verify.verify(numberOfZones == zoneSystem.getZones().size());
117124

118125
// read zone list
119126
List<Id<Zone>> zoneIds = new ArrayList<>(numberOfZones);
120127
for (int i = 0; i < numberOfZones; i++) {
121-
zoneIds.add(Id.create(inputStream.readUTF(), Zone.class));
128+
zoneIds.add(Id.create(dataStream.readUTF(), Zone.class));
122129
}
123130

124131
IdSet<Zone> systemZones = new IdSet<>(Zone.class);
@@ -144,39 +151,39 @@ public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, URL
144151
Zone fromZone = zoneArray[i];
145152
for (int j = 0; j < numberOfZones; j++) {
146153
Zone toZone = zoneArray[j];
147-
freeSpeedTravelTimeMatrix.set(fromZone, toZone, inputStream.readInt());
154+
freeSpeedTravelTimeMatrix.set(fromZone, toZone, dataStream.readInt());
148155
}
149156
}
150157

151158
// sparse matrix available?
152-
boolean hasSparseMatrix = inputStream.readBoolean();
159+
boolean hasSparseMatrix = dataStream.readBoolean();
153160

154161
if (!hasSparseMatrix) {
155162
freeSpeedTravelTimeSparseMatrix = null;
156163
} else {
157164
freeSpeedTravelTimeSparseMatrix = new SparseMatrix();
158165

159166
// read nodes
160-
int numberOfNodes = inputStream.readInt();
167+
int numberOfNodes = dataStream.readInt();
161168
Verify.verify(numberOfNodes == dvrpNetwork.getNodes().size());
162169

163170
List<Node> nodes = new ArrayList<>(numberOfNodes);
164171
for (int i = 0; i < numberOfNodes; i++) {
165-
Id<Node> nodeId = Id.createNodeId(inputStream.readUTF());
172+
Id<Node> nodeId = Id.createNodeId(dataStream.readUTF());
166173
nodes.add(Objects.requireNonNull(dvrpNetwork.getNodes().get(nodeId)));
167174
}
168175

169176
// read rows
170177
for (int i = 0; i < numberOfNodes; i++) {
171178
Node from = nodes.get(i);
172-
int numberOfElements = inputStream.readInt();
179+
int numberOfElements = dataStream.readInt();
173180

174181
if (numberOfElements > 0) {
175182
List<NodeAndTime> nodeTimeList = new ArrayList<>(numberOfElements);
176183

177184
for (int j = 0; j < numberOfElements; j++) {
178-
Node to = nodes.get(inputStream.readInt());
179-
int value = inputStream.readInt();
185+
Node to = nodes.get(dataStream.readInt());
186+
int value = dataStream.readInt();
180187

181188
nodeTimeList.add(new NodeAndTime(to.getId().index(), value));
182189
}
@@ -186,8 +193,6 @@ public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, URL
186193
}
187194
}
188195
}
189-
} catch (FileNotFoundException e) {
190-
throw e;
191196
} catch (IOException e) {
192197
throw new UncheckedIOException(e);
193198
}

contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java

+54
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package org.matsim.contrib.zone.skims;
2222

2323
import static org.assertj.core.api.Assertions.assertThat;
24+
import static org.junit.jupiter.api.Assertions.assertTrue;
2425

2526
import java.io.File;
2627
import java.net.MalformedURLException;
@@ -30,13 +31,24 @@
3031
import org.junit.jupiter.api.extension.RegisterExtension;
3132
import org.matsim.api.core.v01.Coord;
3233
import org.matsim.api.core.v01.Id;
34+
import org.matsim.api.core.v01.Scenario;
3335
import org.matsim.api.core.v01.network.Network;
3436
import org.matsim.api.core.v01.network.Node;
3537
import org.matsim.contrib.common.zones.ZoneSystem;
3638
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystem;
39+
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
40+
import org.matsim.contrib.dvrp.run.DvrpModule;
41+
import org.matsim.core.config.Config;
42+
import org.matsim.core.config.ConfigUtils;
43+
import org.matsim.core.controler.Controler;
3744
import org.matsim.core.network.NetworkUtils;
45+
import org.matsim.core.scenario.ScenarioUtils;
46+
import org.matsim.core.utils.io.IOUtils;
47+
import org.matsim.examples.ExamplesUtils;
3848
import org.matsim.testcases.MatsimTestUtils;
3949

50+
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams;
51+
4052
/**
4153
* @author Michal Maciejewski (michalm)
4254
*/
@@ -131,4 +143,46 @@ void sparseMatrix() throws MalformedURLException {
131143
assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 11 + 2); // 2 s for moving over nodes
132144
assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 9 + 2); // 2 s for moving over nodes
133145
}
146+
147+
@Test
148+
void cacheViaConfig() throws MalformedURLException {
149+
// need to get an absolute path, otherwise will try to generate the cache relative to the config
150+
String cachePath = new File(utils.getOutputDirectory() + "/cache.bin").getAbsolutePath();
151+
152+
URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("dvrp-grid"),
153+
"generic_dvrp_one_taxi_config.xml");
154+
155+
Config config = ConfigUtils.loadConfig(configUrl, new DvrpConfigGroup());
156+
157+
DvrpConfigGroup dvrpConfig = DvrpConfigGroup.get(config);
158+
159+
DvrpTravelTimeMatrixParams params = dvrpConfig.getTravelTimeMatrixParams();
160+
params.maxNeighborDistance = 9999;
161+
params.cachePath = cachePath;
162+
163+
SquareGridZoneSystemParams zoneParams = new SquareGridZoneSystemParams();
164+
zoneParams.cellSize = 1000;
165+
params.addParameterSet(zoneParams);
166+
167+
Scenario scenario = ScenarioUtils.createScenario(config);
168+
ScenarioUtils.loadScenario(scenario);
169+
170+
{
171+
// generate from scratch
172+
assertTrue(!new File(cachePath).exists());
173+
174+
Controler controller = new Controler(scenario);
175+
controller.addOverridingModule(new DvrpModule());
176+
controller.getInjector().getInstance(TravelTimeMatrix.class);
177+
}
178+
179+
{
180+
// read from cache
181+
assertTrue(new File(cachePath).exists());
182+
183+
Controler controller = new Controler(scenario);
184+
controller.addOverridingModule(new DvrpModule());
185+
controller.getInjector().getInstance(TravelTimeMatrix.class);
186+
}
187+
}
134188
}

0 commit comments

Comments
 (0)