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