Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/assign/duaIterate.py
193876 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
4
# Copyright (C) 2008-2026 German Aerospace Center (DLR) and others.
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file duaIterate.py
16
# @author Daniel Krajzewicz
17
# @author Michael Behrisch
18
# @author Jakob Erdmann
19
# @author Yun-Pang Floetteroed
20
# @author Behzad Bamdad Mehrabani
21
# @date 2008-02-13
22
23
"""
24
Run duarouter and sumo alternating to perform a dynamic user assignment or a dynamic system optimal assignment
25
"""
26
from __future__ import print_function
27
from __future__ import absolute_import
28
import os
29
import sys
30
import subprocess
31
import argparse
32
import xml.etree.ElementTree as ET
33
from datetime import datetime
34
from collections import defaultdict
35
36
from costMemory import CostMemory
37
38
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
39
import sumolib # noqa
40
from sumolib.options import get_long_option_names, ArgumentParser # noqa
41
42
DEBUGLOG = None
43
EDGEDATA_ADD = "edgedata.add.xml"
44
45
46
def addGenericOptions(argParser):
47
# add options which are used by duaIterate and cadytsIterate
48
argParser.add_argument("-w", "--disable-warnings", action="store_true", dest="noWarnings",
49
default=False, help="disables warnings")
50
argParser.add_argument("-n", "--net-file", dest="net", category="input", type=argParser.net_file,
51
help="SUMO network (mandatory)", metavar="FILE")
52
argParser.add_argument("-+", "--additional", category="input", default="",
53
type=argParser.additional_file, help="Additional files")
54
argParser.add_argument("-b", "--begin",
55
type=argParser.time, default=0, help="Set simulation/routing begin")
56
argParser.add_argument("-e", "--end",
57
type=argParser.time, help="Set simulation/routing end")
58
argParser.add_argument("-R", "--route-steps", type=int, default=200, help="Set simulation route steps")
59
argParser.add_argument("-a", "--aggregation",
60
type=argParser.time, default=900, help="Set main weights aggregation period")
61
argParser.add_argument("-m", "--mesosim", action="store_true",
62
default=False, help="Whether mesosim shall be used")
63
argParser.add_argument("-p", "--path", type=str, help="Path to binaries")
64
argParser.add_argument("-y", "--absrand", action="store_true",
65
default=False, help="use current time to generate random number")
66
argParser.add_argument("-I", "--nointernal-link", action="store_true", dest="internallink",
67
default=False, help="not to simulate internal link: true or false")
68
argParser.add_argument("-j", "--meso-junctioncontrol", action="store_true", default=False,
69
help="Enable mesoscopic traffic light and priority junction handling")
70
argParser.add_argument("-L", "--meso-junctioncontrollimited", action="store_true", default=False,
71
help="Enable mesoscopic traffic light and priority junction handling for saturated links")
72
argParser.add_argument("-q", "--meso-multiqueue", action="store_true", default=False,
73
help="Enable multiple queues at edge ends")
74
argParser.add_argument("--meso-recheck", type=int, default=0,
75
help="Delay before checking whether a jam is gone. " +
76
"(higher values can lead to a big speed increase)")
77
argParser.add_argument("--meso-tls-penalty", type=float,
78
help="Apply scaled time penalties when driving across tls controlled junctions")
79
argParser.add_argument("--meso-minor-penalty", type=int,
80
help="Apply fixed time penalty when driving across a minor link; " +
81
"do not use together with --meso-junctioncontrollimited")
82
argParser.add_argument("-Q", "--eco-measure", choices=['CO', 'CO2', 'PMx', 'HC', 'NOx', 'fuel', 'noise'],
83
help="define the applied eco measure, e.g. fuel, CO2, noise")
84
argParser.add_argument("--eager-insert", action="store_true",
85
default=False, help="eager insertion tests (may slow down the sim considerably)")
86
argParser.add_argument("--time-to-teleport", dest="timetoteleport", type=argParser.time, default=300,
87
help="Delay before blocked vehicles are teleported (negative value disables teleporting)")
88
argParser.add_argument("--time-to-teleport.highways", dest="timetoteleport_highways", type=argParser.time,
89
default=0, help="Delay before blocked vehicles are teleported on wrong highway lanes")
90
argParser.add_argument("--measure-vtypes", dest="measureVTypes", type=str,
91
help="Restrict edgeData measurements to the given vehicle types")
92
argParser.add_argument("-7", "--zip", action="store_true",
93
default=False, help="zip old iterations (non-functional, kept for backwards compatibility)")
94
argParser.add_argument("-s", "--method-of-successive-average", action="store_true", dest="MSA",
95
default=False, help="apply the method of successive average as the swapping algorithm")
96
97
98
def initOptions():
99
argParser = ArgumentParser(
100
description=""" Any options of the form sumo--long-option-name will be passed to sumo.
101
These must be given after all the other options
102
example: sumo--step-length 0.5 will add the option --step-length 0.5 to sumo.""",
103
allowed_programs=['duarouter', 'sumo'],
104
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
105
addGenericOptions(argParser)
106
107
argParser.add_argument("--continue-on-unbuild", action="store_true", dest="continueOnUnbuild",
108
default=False, help="continues on unbuild routes")
109
argParser.add_argument("-t", "--trips",
110
help="trips in step 0 (either trips, flows, or routes have to be supplied)", metavar="FILE")
111
argParser.add_argument("-r", "--routes",
112
help="routes in step 0 (either trips, flows, or routes have to be supplied)", metavar="FILE")
113
argParser.add_argument("-F", "--flows",
114
help="flows in step 0 (either trips, flows, or routes have to be supplied)", metavar="FILE")
115
argParser.add_argument("-A", "--gA",
116
type=float, default=.5, help="Sets Gawron's Alpha")
117
argParser.add_argument("-B", "--gBeta",
118
type=float, default=.9, help="Sets Gawron's Beta")
119
argParser.add_argument("-E", "--disable-summary", "--disable-emissions", category="output", action="store_true",
120
dest="noSummary", default=False, help="No summaries are written by the simulation")
121
argParser.add_argument("-T", "--disable-tripinfos", action="store_true", dest="noTripinfo",
122
default=False, help="No tripinfos are written by the simulation")
123
argParser.add_argument("--tripinfo-filter", dest="tripinfoFilter",
124
help="filter tripinfo attributes")
125
argParser.add_argument("--inc-start", dest="incStart",
126
type=float, default=0, help="Start for incrementing scale")
127
argParser.add_argument("--inc-max", dest="incMax",
128
type=float, default=1, help="Maximum for incrementing scale")
129
argParser.add_argument("--inc-base", dest="incBase", type=int, default=-1,
130
help="Give the incrementation base. Negative values disable incremental scaling")
131
argParser.add_argument("--incrementation", dest="incValue",
132
type=int, default=1, help="Give the incrementation")
133
argParser.add_argument("--time-inc", dest="timeInc",
134
type=int, default=0, help="Give the time incrementation")
135
argParser.add_argument("-f", "--first-step", dest="firstStep",
136
type=int, default=0, help="First DUA step")
137
argParser.add_argument("-l", "--last-step", dest="lastStep",
138
type=int, default=50, help="Last DUA step")
139
argParser.add_argument("--convergence-iterations", dest="convIt",
140
type=int, default=10, help="Number of iterations to use for convergence calculation")
141
argParser.add_argument("--max-convergence-deviation", dest="convDev",
142
type=float, help="Maximum relative standard deviation in travel times")
143
argParser.add_argument("-D", "--districts", help="use districts as sources and targets", metavar="FILE")
144
argParser.add_argument("-x", "--vehroute-file", dest="routefile",
145
choices=['None', 'routesonly', 'detailed'],
146
default='None', help="choose the format of the route file")
147
argParser.add_argument("-z", "--output-lastRoute", action="store_true", category="output", dest="lastroute",
148
default=False, help="output the last routes")
149
argParser.add_argument("-K", "--keep-allroutes", action="store_true", dest="allroutes",
150
default=False, help="save routes with near zero probability")
151
argParser.add_argument("--routing-algorithm", default="dijkstra", help="select the routing algorithm")
152
argParser.add_argument("--max-alternatives", default=5, help="prune the number of alternatives to INT")
153
argParser.add_argument("--skip-first-routing", action="store_true", dest="skipFirstRouting",
154
default=False, help="run simulation with demands before first routing")
155
argParser.add_argument("--logit", action="store_true", default=False, help="use the logit model for route choice")
156
argParser.add_argument("-g", "--logitbeta", type=float,
157
default=0.15, help="use the c-logit model for route choice; logit model when beta = 0")
158
argParser.add_argument("-i", "--logitgamma", type=float, default=1., help="use the c-logit model for route choice")
159
argParser.add_argument("-G", "--logittheta", type=float, help="parameter to adapt the cost unit")
160
argParser.add_argument("-J", "--addweights", help="Additional weights for duarouter")
161
argParser.add_argument("--convergence-steps", dest="convergenceSteps", type=int,
162
help="Given x, if x > 0 reduce probability to change route by 1/x per step "
163
"(Probabilistic Swapping (PSwap)). "
164
"If x < 0 set probability of rerouting to 1/step after step |x|")
165
argParser.add_argument("--addweights.once", dest="addweightsOnce", action="store_true",
166
default=False, help="use added weights only on the first iteration")
167
argParser.add_argument("--router-verbose", action="store_true",
168
default=False, help="let duarouter print some statistics")
169
argParser.add_argument("--weight-memory", action="store_true", default=False, dest="weightmemory",
170
help="smooth edge weights across iterations")
171
argParser.add_argument("--pessimism", default=1, type=float,
172
help="give traffic jams a higher weight when using option --weight-memory")
173
argParser.add_argument("--clean-alt", action="store_true", dest="clean_alt",
174
default=False, help="Whether old rou.alt.xml files shall be removed")
175
argParser.add_argument("--gzip", "--binary", action="store_true", default=True,
176
help="writing intermediate and resulting route files in gzipped format (the default)")
177
argParser.add_argument("--no-gzip", dest="gzip", action="store_false")
178
argParser.set_defaults(gzip=True)
179
argParser.add_argument("--dualog", default="dua.log", category="output", help="log file path (default 'dua.log')")
180
argParser.add_argument("--log", default="stdout.log", category="output",
181
help="stdout log file path (default 'stdout.log')")
182
argParser.add_argument("--marginal-cost", action="store_true", default=False,
183
help="use marginal cost to perform system optimal traffic assignment")
184
argParser.add_argument("--marginal-cost.exp", type=float, default=0, dest="mcExp",
185
help="apply the given exponent on the current traffic count when computing marginal cost")
186
argParser.add_argument("remaining_args", nargs='*')
187
return argParser
188
189
190
def call(command, log):
191
command = [str(c) for c in command]
192
print("-" * 79, file=log)
193
print(command, file=log)
194
log.flush()
195
retCode = subprocess.call(command, stdout=log, stderr=log)
196
if retCode != 0:
197
print(("Execution of %s failed. Look into %s for details.") %
198
(command, log.name), file=sys.stderr)
199
return retCode
200
201
202
def writeRouteConf(duarouterBinary, step, options, dua_args, file,
203
output, routesInfo):
204
filename = os.path.basename(file)
205
filename = filename.split('.')[0]
206
cfgname = "%03i/iteration_%03i_%s.duarcfg" % (step, step, filename)
207
args = [
208
'--net-file', options.net,
209
'--route-files', file,
210
'--output-file', output,
211
'--exit-times', str(routesInfo == "detailed"),
212
'--ignore-errors', str(options.continueOnUnbuild),
213
'--with-taz', str(options.districts is not None),
214
'--gawron.beta', str(options.gBeta),
215
'--gawron.a', str(options.gA),
216
'--keep-all-routes', str(options.allroutes),
217
'--routing-algorithm', options.routing_algorithm,
218
'--max-alternatives', str(options.max_alternatives),
219
'--weights.expand',
220
'--logit.beta', str(options.logitbeta),
221
'--logit.gamma', str(options.logitgamma),
222
'--random', str(options.absrand),
223
'--begin', str(options.begin),
224
'--verbose', str(options.router_verbose),
225
'--no-step-log',
226
'--no-warnings', str(options.noWarnings),
227
]
228
if options.districts:
229
args += ['--additional-files', options.districts]
230
if options.logit:
231
args += ['--route-choice-method', 'logit']
232
if options.MSA:
233
probKeepRoute = step/(step+1)
234
args += ['--keep-route-probability', str(probKeepRoute)]
235
if options.convergenceSteps:
236
if options.convergenceSteps > 0:
237
probKeepRoute = max(0, min(step / float(options.convergenceSteps), 1))
238
else:
239
startStep = -options.convergenceSteps
240
probKeepRoute = 0 if step > startStep else 1 - 1.0 / (step - startStep)
241
args += ['--keep-route-probability', str(probKeepRoute)]
242
243
if step > 0 or options.addweights:
244
weightpath = ""
245
if step > 0:
246
weightpath = get_weightfilename(options, step - 1, "dump")
247
if options.addweights and (step == 0 or not options.addweightsOnce):
248
if step > 0:
249
weightpath += ","
250
weightpath += options.addweights
251
args += ['--weight-files', weightpath]
252
if options.eco_measure:
253
args += ['--weight-attribute', options.eco_measure]
254
if 'CH' in options.routing_algorithm:
255
args += ['--weight-period', str(options.aggregation)]
256
if options.logittheta:
257
args += ['--logit.theta', str(options.logittheta)]
258
if options.end:
259
args += ['--end', str(options.end)]
260
261
args += ["--save-configuration", cfgname]
262
263
subprocess.call([duarouterBinary] + args + dua_args)
264
return cfgname
265
266
267
def get_scale(options, step):
268
# compute scaling factor for simulation
269
# using incValue = 1 (default) and incBase = 10 would produce
270
# iterations with increasing scale 0.1, 0.2, ... 0.9, 1, 1, 1, ...
271
if options.incBase > 0:
272
return min(options.incStart + options.incValue * float(step + 1) / options.incBase, options.incMax)
273
else:
274
return options.incMax
275
276
277
def get_dumpfilename(options, step, prefix, full_path=True):
278
# the file to which edge costs (traveltimes) are written
279
suffix = ".xml.gz" if getattr(options, "gzip", False) else ".xml"
280
if full_path:
281
return "%03i/%s_%s%s" % (step, prefix, options.aggregation, suffix)
282
return "%s_%s%s" % (prefix, options.aggregation, suffix)
283
284
285
def get_weightfilename(options, step, prefix):
286
# the file from which edge costs are loaded
287
# this defaults to the dumpfile written by the simulation but may be
288
# different if one of the options --addweights, --memory-weights or
289
# --cost-modifier is used
290
if options.weightmemory:
291
prefix = "memory_" + prefix
292
return get_dumpfilename(options, step, prefix)
293
294
295
def writeSUMOConf(sumoBinary, step, options, additional_args, route_files):
296
cfgfile = "%03i/iteration_%03i.sumocfg" % (step, step)
297
add = [EDGEDATA_ADD]
298
if options.additional != '':
299
add += options.additional.split(',')
300
301
sumoCmd = [sumoBinary,
302
'--output-prefix', '%03i/' % step,
303
'--save-configuration', cfgfile,
304
'--log', "iteration_%03i.sumo.log" % step,
305
'--net-file', options.net,
306
'--route-files', route_files,
307
'--additional-files', ",".join(add),
308
'--no-step-log',
309
'--random', options.absrand,
310
'--begin', options.begin,
311
'--route-steps', options.route_steps,
312
'--no-internal-links', options.internallink,
313
'--eager-insert', options.eager_insert,
314
'--time-to-teleport', options.timetoteleport,
315
'--time-to-teleport.highways', options.timetoteleport_highways,
316
'--verbose',
317
'--no-warnings', options.noWarnings,
318
] + additional_args
319
320
if hasattr(options, "noSummary") and not options.noSummary:
321
sumoCmd += ['--summary-output', "summary_%03i.xml" % step]
322
if hasattr(options, "noTripinfo") and not options.noTripinfo:
323
sumoCmd += ['--tripinfo-output', "tripinfo_%03i.xml" % step]
324
if options.eco_measure:
325
sumoCmd += ['--device.emissions.probability', '1']
326
if hasattr(options, "routefile"):
327
if options.routefile == "routesonly":
328
sumoCmd += ['--vehroute-output', "vehroute_%03i.xml" % step,
329
'--vehroute-output.route-length']
330
elif options.routefile == "detailed":
331
sumoCmd += ['--vehroute-output', "vehroute_%03i.xml" % step,
332
'--vehroute-output.route-length',
333
'--vehroute-output.exit-times']
334
if hasattr(options, "lastroute") and options.lastroute:
335
sumoCmd += ['--vehroute-output.last-route', options.lastroute]
336
if hasattr(options, "timeInc") and options.timeInc:
337
sumoCmd += ['--end', int(options.timeInc * (step + 1))]
338
elif options.end:
339
sumoCmd += ['--end', options.end]
340
341
if hasattr(options, "incBase") and options.incBase > 0:
342
sumoCmd += ['--scale', get_scale(options, step)]
343
if options.mesosim:
344
sumoCmd += ['--mesosim',
345
'--meso-recheck', options.meso_recheck]
346
if options.meso_multiqueue:
347
sumoCmd += ['--meso-multi-queue']
348
if options.meso_junctioncontrol:
349
sumoCmd += ['--meso-junction-control']
350
if options.meso_junctioncontrollimited:
351
sumoCmd += ['--meso-junction-control.limited']
352
if options.meso_tls_penalty:
353
sumoCmd += ['--meso-tls-penalty', options.meso_tls_penalty]
354
if options.meso_minor_penalty:
355
sumoCmd += ['--meso-minor-penalty', options.meso_minor_penalty]
356
357
# make sure all arguments are strings
358
sumoCmd = list(map(str, sumoCmd))
359
# use sumoBinary to write a config file
360
subprocess.call(sumoCmd, stdout=subprocess.PIPE)
361
362
return cfgfile
363
364
365
def filterTripinfo(step, attrs):
366
if "id" not in attrs:
367
attrs = ["id"] + attrs
368
inFile = "%03i%stripinfo_%03i.xml" % (step, os.sep, step)
369
if os.path.exists(inFile):
370
with open(inFile) as inf, open(inFile + ".filtered", 'w') as out:
371
print("<tripinfos>", file=out)
372
hadOutput = False
373
for line in inf:
374
if "<tripinfo " in line:
375
if hadOutput:
376
print("/>", file=out)
377
print(" <tripinfo", end=' ', file=out)
378
for a in attrs:
379
pos = line.find(a)
380
if pos >= 0:
381
pos += len(a) + 2
382
print('%s="%s"' % (a, line[pos:line.find('"', pos)]), end=' ', file=out)
383
hadOutput = True
384
if "<emission" in line:
385
for a in attrs:
386
pos = line.find(a)
387
if pos >= 0:
388
pos += len(a) + 2
389
print('%s="%s"' % (a, line[pos:line.find('"', pos)]), end=' ', file=out)
390
if hadOutput:
391
print("/>", file=out)
392
print("</tripinfos>", file=out)
393
os.remove(inFile)
394
os.rename(out.name, inFile)
395
396
397
def assign_remaining_args(application, prefix, args):
398
# assign remaining args [ prefix--o1 a1 prefix--o2 prefix--o3 a3 ...]
399
# only handles long options!
400
assigned = []
401
# split into options and arguments
402
items = []
403
item = None
404
for arg in args:
405
if "--" in arg:
406
if item is not None:
407
items.append(item)
408
if "=" in arg:
409
item = arg.split("=")
410
else:
411
item = [arg]
412
else:
413
if item is None:
414
sys.exit(
415
'Encountered argument "%s" without a preceding option' % arg)
416
item.append(arg)
417
if item is not None:
418
items.append(item)
419
420
# assign to programs
421
valid_options = set(get_long_option_names(application))
422
for item in items:
423
prefixed = item[0]
424
if prefixed[0:len(prefix)] == prefix:
425
option = prefixed[len(prefix):]
426
if option in valid_options:
427
assigned.append(option)
428
assigned += item[1:]
429
else:
430
sys.exit('"%s" is not a valid option for "%s"' %
431
(option, application))
432
433
return assigned
434
435
436
def get_basename(demand_file):
437
basename = os.path.basename(demand_file)
438
# note this will still cause problems if multiple input file have the same
439
# prefix and only differ in suffix
440
for suffix in ['.rou.xml', '.rou.alt.xml', '.trips.xml', '.xml']:
441
if basename.endswith(suffix):
442
basename = basename[:-len(suffix)]
443
break
444
return basename
445
446
447
def calcMarginalCost(step, options):
448
if step > 1:
449
if DEBUGLOG:
450
log = open("marginal_cost2.log", "w" if step == 2 else "a")
451
with sumolib.openz(get_weightfilename(options, step - 1, "dump")) as f:
452
tree_sumo_cur = ET.parse(f)
453
with sumolib.openz(get_weightfilename(options, step - 2, "dump")) as f:
454
tree_sumo_prv = ET.parse(f)
455
oldValues = defaultdict(dict)
456
for interval_prv in tree_sumo_prv.getroot():
457
begin_prv = interval_prv.attrib.get("begin")
458
for edge_prv in interval_prv.iter('edge'):
459
if edge_prv.get("traveltime") is not None:
460
veh_prv = float(edge_prv.get("left")) + float(edge_prv.get("arrived"))
461
tt_prv = float(edge_prv.get("overlapTraveltime"))
462
mc_prv = float(edge_prv.get("traveltime"))
463
oldValues[begin_prv][edge_prv.get("id")] = (veh_prv, tt_prv, mc_prv)
464
465
for interval_cur in tree_sumo_cur.getroot():
466
begin_cur = interval_cur.attrib.get("begin")
467
if begin_cur in oldValues:
468
oldIntervalValues = oldValues[begin_cur]
469
for edge_cur in interval_cur.iter('edge'):
470
if edge_cur.get("traveltime") is not None:
471
id_cur = edge_cur.get("id")
472
if id_cur in oldIntervalValues:
473
veh_prv, tt_prv, mc_prv = oldIntervalValues[id_cur]
474
veh_cur = float(edge_cur.get("left")) + float(edge_cur.get("arrived"))
475
tt_cur = float(edge_cur.get("traveltime"))
476
dif_tt = abs(tt_cur - tt_prv)
477
dif_veh = abs(veh_cur - veh_prv)
478
if dif_veh != 0:
479
mc_cur = (dif_tt / dif_veh) * (veh_cur ** options.mcExp) + tt_cur
480
else:
481
# previous marginal cost
482
mc_cur = tt_cur
483
484
edge_cur.set("traveltime", str(mc_cur))
485
edge_cur.set("overlapTraveltime", str(tt_cur))
486
edgeID = edge_cur.get("id")
487
if DEBUGLOG:
488
if begin_cur == "1800.00":
489
print("step=%s beg=%s e=%s tt=%s ttprev=%s n=%s nPrev=%s mC=%s mCPrev=%s" %
490
(step, begin_cur, edgeID, tt_cur, tt_prv, veh_cur, veh_prv,
491
mc_cur, mc_prv), file=log)
492
tree_sumo_cur.write(get_weightfilename(options, step - 1, "dump"))
493
494
if DEBUGLOG:
495
log.close()
496
497
498
def generateEdgedataAddFile(EDGEDATA_ADD, options):
499
"""write detectorfile"""
500
with open(EDGEDATA_ADD, 'w') as fd:
501
vTypes = ' vTypes="%s"' % ' '.join(options.measureVTypes.split(',')) if options.measureVTypes else ""
502
print("<a>", file=fd)
503
print(' <edgeData id="dump_%s" freq="%s" file="%s" excludeEmpty="true" minSamples="1"%s/>' % (
504
options.aggregation,
505
options.aggregation,
506
get_dumpfilename(options, -1, "dump", False),
507
vTypes), file=fd)
508
if options.eco_measure:
509
print((' <edgeData id="eco_%s" type="emissions" freq="%s" file="%s" ' +
510
'excludeEmpty="true" minSamples="1"%s/>') % (
511
options.aggregation,
512
options.aggregation,
513
get_dumpfilename(options, -1, "dump", False),
514
vTypes), file=fd)
515
print("</a>", file=fd)
516
fd.close()
517
518
519
def main(args=None):
520
argParser = initOptions()
521
522
try:
523
options = argParser.parse_args(args=args)
524
except (NotImplementedError, ValueError) as e:
525
print(e, file=sys.stderr)
526
sys.exit(1)
527
528
if not options.net:
529
argParser.error("Option --net-file is mandatory")
530
if (not options.trips and not options.routes and not options.flows) or (options.trips and options.routes):
531
argParser.error(
532
"Either --trips, --flows, or --routes have to be given!")
533
duaBinary = sumolib.checkBinary("duarouter", options.path)
534
sumoBinary = sumolib.checkBinary("sumo", options.path)
535
if options.marginal_cost and not options.logit:
536
print("Warning! --marginal-cost works best with --logit.", file=sys.stderr)
537
538
# make sure BOTH binaries are callable before we start
539
try:
540
subprocess.call(duaBinary, stdout=subprocess.PIPE)
541
except OSError:
542
sys.exit(
543
("Error: Could not locate duarouter (%s).\nMake sure its on the search path or set environment " +
544
"variable DUAROUTER_BINARY\n") % duaBinary)
545
try:
546
subprocess.call(sumoBinary, stdout=subprocess.PIPE)
547
except OSError:
548
sys.exit(
549
("Error: Could not locate sumo (%s).\nMake sure its on the search path or set environment " +
550
"variable SUMO_BINARY\n") % sumoBinary)
551
552
sumo_args = assign_remaining_args(sumoBinary, 'sumo', options.remaining_args)
553
dua_args = assign_remaining_args(duaBinary, 'duarouter', options.remaining_args)
554
sys.stdout = sumolib.TeeFile(sys.stdout, open(options.log, "w+"))
555
log = open(options.dualog, "w+")
556
if options.zip:
557
print("Warning: Option -7/--zip is deprecated and has no effect.", file=sys.stderr)
558
starttime = datetime.now()
559
if options.trips:
560
input_demands = options.trips.split(",")
561
elif options.flows:
562
input_demands = options.flows.split(",")
563
else:
564
input_demands = options.routes.split(",")
565
if options.weightmemory:
566
costmemory = CostMemory('traveltime', pessimism=options.pessimism, network_file=options.net
567
)
568
routesSuffix = ".xml"
569
if options.gzip:
570
routesSuffix += ".gz"
571
572
if options.weightmemory and options.firstStep != 0:
573
# load previous dump files when continuing a run
574
print(">> Reassembling cost-memory from previous iteration steps")
575
for step in range(0, options.firstStep):
576
dumpfile = get_dumpfilename(options, step, "dump")
577
print(">>> Loading %s" % dumpfile)
578
costmemory.load_costs(dumpfile, step, get_scale(options, step))
579
580
# generate edgedata.add.xml
581
generateEdgedataAddFile(EDGEDATA_ADD, options)
582
583
avgTT = sumolib.miscutils.Statistics()
584
ret = 0
585
for step in range(options.firstStep, options.lastStep):
586
current_directory = os.getcwd()
587
final_directory = os.path.join(current_directory, "%03i" % step)
588
if not os.path.exists(final_directory):
589
os.makedirs(final_directory)
590
btimeA = datetime.now()
591
print("> Executing step %s" % step)
592
593
router_demands = input_demands
594
simulation_demands = input_demands
595
# demand files have regular names based on the basename and the step
596
if not (options.skipFirstRouting and step == 0):
597
simulation_demands = ["%03i/%s_%03i.rou%s" % (step, get_basename(f), step, routesSuffix)
598
for f in input_demands]
599
if not ((options.skipFirstRouting and step == 1) or step == 0):
600
router_demands = ["%03i/%s_%03i.rou.alt%s" % (step-1, get_basename(f), step-1, routesSuffix)
601
for f in input_demands]
602
603
if not (options.skipFirstRouting and step == options.firstStep):
604
# call duarouter
605
for router_input, output in zip(router_demands, simulation_demands):
606
print(">> Running router on %s" % router_input)
607
btime = datetime.now()
608
print(">>> Begin time: %s" % btime)
609
cfgname = writeRouteConf(duaBinary, step, options, dua_args, router_input,
610
output, options.routefile)
611
log.flush()
612
sys.stdout.flush()
613
if options.marginal_cost:
614
calcMarginalCost(step, options)
615
616
ret = call([duaBinary, "-c", cfgname], log)
617
if ret != 0:
618
break
619
if options.clean_alt and router_input not in input_demands:
620
os.remove(router_input)
621
etime = datetime.now()
622
print(">>> End time: %s" % etime)
623
print(">>> Duration: %s" % (etime - btime))
624
print("<<")
625
if ret != 0:
626
break
627
628
# simulation
629
print(">> Running simulation")
630
btime = datetime.now()
631
print(">>> Begin time: %s" % btime)
632
sumocfg = writeSUMOConf(sumoBinary, step, options, sumo_args,
633
",".join(simulation_demands)) # todo: change 'grou.xml'
634
log.flush()
635
sys.stdout.flush()
636
ret = call([sumoBinary, "-c", sumocfg], log)
637
if ret != 0:
638
break
639
if options.tripinfoFilter:
640
filterTripinfo(step, options.tripinfoFilter.split(","))
641
etime = datetime.now()
642
print(">>> End time: %s" % etime)
643
print(">>> Duration: %s" % (etime - btime))
644
print("<<")
645
646
if options.weightmemory:
647
print(">> Smoothing edge weights")
648
costmemory.load_costs(get_dumpfilename(options, step, "dump"), step, get_scale(options, step))
649
costmemory.write_costs(get_weightfilename(options, step, "dump"))
650
print(">>> Updated %s edges" % costmemory.loaded())
651
print(">>> Decayed %s unseen edges" % costmemory.decayed())
652
print(">>> Error avg:%.12g mean:%.12g" % (costmemory.avg_error(), costmemory.mean_error()))
653
print(">>> Absolute Error avg:%.12g mean:%.12g" %
654
(costmemory.avg_abs_error(), costmemory.mean_abs_error()))
655
656
converged = False
657
if options.convDev:
658
sum = 0.
659
count = 0
660
for t in sumolib.output.parse_fast("%03i/tripinfo_%03i.xml" % (step, step),
661
'tripinfo', ['duration']):
662
sum += float(t.duration)
663
count += 1
664
if count == 0:
665
sys.exit("Error: No vehicle has reached its destination within the simulation duration.")
666
avgTT.add(sum / count)
667
relStdDev = avgTT.relStdDev(options.convIt)
668
print("< relative travel time deviation in the last %s steps: %.05f" % (
669
min(avgTT.count(), options.convIt), relStdDev))
670
if avgTT.count() >= options.convIt and relStdDev < options.convDev:
671
converged = True
672
673
print("< Step %s ended (duration: %s)" %
674
(step, datetime.now() - btimeA))
675
print("------------------\n")
676
677
log.flush()
678
sys.stdout.flush()
679
if converged:
680
break
681
print("dua-iterate ended (duration: %s)" % (datetime.now() - starttime))
682
683
log.close()
684
sys.stdout.close()
685
sys.stdout = sys.__stdout__
686
return ret
687
688
689
if __name__ == "__main__":
690
sys.exit(main())
691
692