Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/output/tripStatistics.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2007-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file tripStatistics.py
15
# @author Yun-Pang Floetteroed
16
# @author Michael Behrisch
17
# @date 2007-02-27
18
19
"""
20
This script is to calculate the global performance indices according to the SUMO-based simulation results.
21
Besides, this script is also to execute the significance test for evaluating the results from different assignment
22
methods.
23
The t test and the Kruskal-Wallis test are available in this script.
24
If not specified, the Kruskal-Wallis test will be applied with the assumption that data are not normally distributed.
25
26
The analyzed parameters include:
27
- travel length
28
- travel time
29
- travel speed
30
- stop time
31
"""
32
from __future__ import absolute_import
33
from __future__ import print_function
34
35
import sys
36
import operator
37
38
from xml.sax import make_parser
39
from optparse import OptionParser
40
from statisticsElements import Assign, T_Value, H_Value, VehInformationReader
41
from statisticsElements import getStatisticsOutput, getSignificanceTestOutput
42
from tables import chiSquareTable, tTable
43
44
45
def getBasicStats(verbose, method, vehicles, assignments):
46
totalVeh = 0.
47
totalTravelTime = 0.
48
totalTravelLength = 0.
49
totalTravelSpeed = 0.
50
totalWaitTime = 0.
51
totalDiffSpeed = 0.
52
totalDiffLength = 0.
53
totalDiffWaitTime = 0.
54
totalDiffTravelTime = 0.
55
totalDepartDelay = 0.
56
57
for veh in vehicles:
58
totalVeh += 1
59
veh.method = method
60
# unit: speed - m/s; traveltime - s; travel length - m
61
veh.speed = veh.travellength / veh.traveltime
62
totalTravelTime += veh.traveltime
63
totalTravelLength += veh.travellength
64
totalWaitTime += veh.waittime
65
totalTravelSpeed += veh.speed
66
totalDepartDelay += veh.departdelay
67
if verbose:
68
print('totalVeh:', totalVeh)
69
70
totalVehDivisor = max(1, totalVeh) # avoid division by 0
71
avgTravelTime = totalTravelTime / totalVehDivisor
72
avgTravelLength = totalTravelLength / totalVehDivisor
73
avgTravelSpeed = totalTravelSpeed / totalVehDivisor
74
avgWaitTime = totalWaitTime / totalVehDivisor
75
avgDepartDelay = totalDepartDelay / totalVehDivisor
76
for veh in vehicles:
77
totalDiffTravelTime += (veh.traveltime - avgTravelTime)**2
78
totalDiffSpeed += (veh.speed - avgTravelSpeed)**2
79
totalDiffLength += (veh.travellength - avgTravelLength)**2
80
totalDiffWaitTime += (veh.waittime - avgWaitTime)**2
81
82
# SD: standard deviation
83
SDTravelTime = (totalDiffTravelTime / totalVehDivisor)**(0.5)
84
SDLength = (totalDiffLength / totalVehDivisor)**(0.5)
85
SDSpeed = (totalDiffSpeed / totalVehDivisor)**(0.5)
86
SDWaitTime = (totalDiffWaitTime / totalVehDivisor)**(0.5)
87
88
assignments[method] = Assign(method, totalVeh, totalTravelTime, totalTravelLength,
89
totalDepartDelay, totalWaitTime, avgTravelTime,
90
avgTravelLength, avgTravelSpeed, avgDepartDelay,
91
avgWaitTime, SDTravelTime, SDLength, SDSpeed, SDWaitTime)
92
93
94
# The observations should be drawn from a normally distributed population.
95
# For two independent samples, the t test has the additional requirement
96
# that the population standard deviations should be equal.
97
def doTTestForAvg(verbose, tValueAvg, assignments):
98
if verbose:
99
print('begin the t test!')
100
for num, A in enumerate(assignments):
101
for B in assignments[num + 1:]:
102
sdABTravelTime = 0.
103
sdABSpeed = 0.
104
sdABLength = 0.
105
sdABWaitTime = 0.
106
if str(A.label) != str(B.label):
107
sdABTravelTime = (float(A.totalVeh - 1) * ((A.SDTravelTime)**2) + float(
108
B.totalVeh - 1) * ((B.SDTravelTime)**2)) / float(A.totalVeh + B.totalVeh - 2)
109
sdABTravelTime = sdABTravelTime**(0.5)
110
111
sdABSpeed = (float(A.totalVeh - 1) * ((A.SDSpeed)**2) + float(
112
B.totalVeh - 1) * ((B.SDSpeed)**2)) / float(A.totalVeh + B.totalVeh - 2)
113
sdABSpeed = sdABSpeed**(0.5)
114
115
sdABLength = (float(A.totalVeh - 1) * ((A.SDLength)**2) + float(
116
B.totalVeh - 1) * ((B.SDLength)**2)) / float(A.totalVeh + B.totalVeh - 2)
117
sdABLength = sdABLength**(0.5)
118
119
sdABWaitTime = (float(A.totalVeh - 1) * ((A.SDWaitTime)**2) + float(
120
B.totalVeh - 1) * ((B.SDWaitTime)**2)) / float(A.totalVeh + B.totalVeh - 2)
121
sdABWaitTime = sdABWaitTime**(0.5)
122
123
tempvalue = (
124
float(A.totalVeh * B.totalVeh) / float(A.totalVeh + B.totalVeh))**0.5
125
126
avgtraveltime = abs(
127
A.avgTravelTime - B.avgTravelTime) / sdABTravelTime * tempvalue
128
129
avgtravelspeed = abs(
130
A.avgTravelSpeed - B.avgTravelSpeed) / sdABSpeed * tempvalue
131
132
avgtravellength = abs(
133
A.avgTravelLength - B.avgTravelLength) / sdABLength * tempvalue
134
135
if sdABWaitTime != 0.:
136
avgwaittime = abs(
137
A.avgWaitTime - B.avgWaitTime) / sdABWaitTime * tempvalue
138
else:
139
avgwaittime = 0.
140
print(
141
'check if the information about veh.waittime exists!')
142
freedomdegree = A.totalVeh + B.totalVeh - 2
143
if freedomdegree > 30 and freedomdegree <= 40:
144
freedomdegree = 31
145
if freedomdegree > 40 and freedomdegree <= 50:
146
freedomdegree = 32
147
if freedomdegree > 50 and freedomdegree <= 60:
148
freedomdegree = 33
149
if freedomdegree > 60 and freedomdegree <= 80:
150
freedomdegree = 34
151
if freedomdegree > 80 and freedomdegree <= 100:
152
freedomdegree = 35
153
if freedomdegree > 100:
154
freedomdegree = 36
155
lowvalue = tTable[freedomdegree][6]
156
highvalue = tTable[freedomdegree][9]
157
158
tValueAvg[A][B] = T_Value(
159
avgtraveltime, avgtravelspeed, avgtravellength, avgwaittime, lowvalue, highvalue)
160
161
162
def doKruskalWallisTest(verbose, groups, combivehlist, assignments, label, hValues):
163
if verbose:
164
print('\nbegin the Kruskal-Wallis test!')
165
print('methods:', label)
166
print('number of samples:', len(combivehlist))
167
adjlabel = label + '_' + "adjusted"
168
if groups >= 100.:
169
groups = 100.
170
lowvalue = chiSquareTable[int(groups) - 1][2]
171
highvalue = chiSquareTable[int(groups) - 1][4]
172
173
H = H_Value(label, lowvalue, highvalue)
174
adjH = H_Value(adjlabel, lowvalue, highvalue)
175
hValues.append(H)
176
hValues.append(adjH)
177
178
for index in [("traveltime"), ("speed"), ("travellength"), ("waittime")]:
179
for veh in combivehlist:
180
veh.rank = 0.
181
for method in assignments.values():
182
method.sumrank = 0.
183
184
samecountlist = []
185
current = 0
186
lastrank = 0
187
subtotal = 0.
188
adjusted = 0.
189
190
combivehlist.sort(key=operator.attrgetter(index))
191
totalsamples = len(combivehlist)
192
193
for i in range(0, len(combivehlist)):
194
samecount = 0
195
if i <= current:
196
if index == "traveltime":
197
value = combivehlist[current].traveltime
198
elif index == "speed":
199
value = combivehlist[current].speed
200
elif index == "travellength":
201
value = combivehlist[current].travellength
202
elif index == "waittime":
203
value = combivehlist[current].waittime
204
else:
205
print('error!')
206
207
for j in range(current, len(combivehlist)):
208
if index == "traveltime":
209
if combivehlist[j].traveltime == value:
210
samecount += 1
211
else:
212
break
213
elif index == "speed":
214
if combivehlist[j].speed == value:
215
samecount += 1
216
else:
217
break
218
elif index == "travellength":
219
if combivehlist[j].travellength == value:
220
samecount += 1
221
else:
222
break
223
elif index == "waittime":
224
if combivehlist[j].waittime == value:
225
samecount += 1
226
else:
227
break
228
229
if samecount == 1.:
230
lastrank += 1.
231
combivehlist[current].rank = lastrank
232
else:
233
sumrank = 0.
234
for j in range(0, samecount):
235
lastrank += 1.
236
sumrank += lastrank
237
rank = sumrank / samecount
238
for j in range(0, samecount):
239
combivehlist[current + j].rank = rank
240
241
elem = (value, samecount)
242
samecountlist.append(elem)
243
244
current = current + samecount
245
246
if current > (len(combivehlist) - 1):
247
break
248
249
for veh in combivehlist:
250
for method in assignments.values():
251
if veh.method == method.label:
252
method.sumrank += veh.rank
253
254
for method in assignments.values():
255
subtotal += (method.sumrank**2.) / method.totalVeh
256
257
for elem in samecountlist:
258
adjusted += (float(elem[1]**3) - float(elem[1]))
259
260
c = 1. - (adjusted / float(totalsamples**3 - totalsamples))
261
262
if index == "traveltime":
263
H.traveltime = 12. / \
264
(totalsamples * (totalsamples + 1)) * \
265
subtotal - 3. * (totalsamples + 1)
266
if c > 0.:
267
adjH.traveltime = H.traveltime / c
268
elif index == "speed":
269
H.travelspeed = 12. / \
270
(totalsamples * (totalsamples + 1)) * \
271
subtotal - 3. * (totalsamples + 1)
272
if c > 0.:
273
adjH.travelspeed = H.travelspeed / c
274
elif index == "travellength":
275
H.travellength = 12. / \
276
(totalsamples * (totalsamples + 1)) * \
277
subtotal - 3. * (totalsamples + 1)
278
if c > 0.:
279
adjH.travellength = H.travellength / c
280
elif index == "waittime":
281
H.waittime = 12. / \
282
(totalsamples * (totalsamples + 1)) * \
283
subtotal - 3. * (totalsamples + 1)
284
if c > 0.:
285
adjH.waittime = H.waittime / c
286
287
288
optParser = OptionParser()
289
optParser.add_option("-t", "--tripinform-file", dest="vehfile",
290
help="read vehicle information generated by the DUA assignment from FILE (mandatory)",
291
metavar="FILE")
292
optParser.add_option("-o", "--output-file", dest="outputfile", default="Global_MOE.txt",
293
help="write output to FILE", metavar="FILE")
294
optParser.add_option("-g", "--SGToutput-file", dest="sgtoutputfile", default="significanceTest.txt",
295
help="write output to FILE", metavar="FILE")
296
optParser.add_option("-v", "--verbose", action="store_true", dest="verbose",
297
default=False, help="tell me what you are doing")
298
optParser.add_option("-e", "--tTest", action="store_true", dest="ttest",
299
default=False, help="perform the t-Test")
300
optParser.add_option("-k", "--kruskalWallisTest", action="store_true", dest="kwtest",
301
default=False, help="perform the Kruskal-Wallis-Test")
302
303
304
(options, args) = optParser.parse_args()
305
306
if not options.vehfile:
307
optParser.print_help()
308
sys.exit()
309
parser = make_parser()
310
311
allvehicles = {}
312
for filename in options.vehfile.split(","):
313
allvehicles[filename] = []
314
parser.setContentHandler(VehInformationReader(allvehicles[filename]))
315
parser.parse(filename)
316
317
# Vehicles from dua, incremental, clogit and oneshot are in included in
318
# the allvehlist.
319
320
# The results of the t test are stored in the tValueAvg.
321
tValueAvg = {}
322
# The resultes of the Kruskal-Wallis test are stored in the hValues.
323
hValues = []
324
325
# intitalization
326
combilabel = ''
327
328
assignments = {}
329
# calculate/read the basic statistics
330
for method, vehicles in allvehicles.items():
331
getBasicStats(options.verbose, method, vehicles, assignments)
332
333
getStatisticsOutput(assignments, options.outputfile)
334
print('The calculation of network statistics is done!')
335
336
# begin the significance test for the observations with a normal distribution
337
if options.ttest:
338
print('begin the t test!')
339
for A in assignments.values():
340
tValueAvg[A] = {}
341
doTTestForAvg(options.verbose, tValueAvg, list(assignments.values()))
342
print('The t test is done!')
343
if options.kwtest:
344
# The Kruskal-Wallis test is applied for the data, not drawn from a
345
# normally distributed population.
346
groups = 2
347
values = list(allvehicles.items())
348
for num, A in enumerate(values):
349
for B in values[num + 1:]:
350
combilabel = ''
351
combivehlist = []
352
combilabel = A[0] + '_' + B[0]
353
print('Test for:', combilabel)
354
for veh in A[1]:
355
combivehlist.append(veh)
356
for veh in B[1]:
357
combivehlist.append(veh)
358
doKruskalWallisTest(
359
options.verbose, groups, combivehlist, assignments, combilabel, hValues)
360
361
getSignificanceTestOutput(
362
assignments, options.ttest, tValueAvg, hValues, options.sgtoutputfile)
363
print('The Significance test is done!')
364
365