from __future__ import absolute_import
from __future__ import print_function
import os
import sys
import subprocess
from datetime import datetime
from xml.sax import make_parser, handler
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import sumolib
def call(command, log):
if not isinstance(command, str):
command = [str(c) for c in command]
print("-" * 79, file=log)
print(command, file=log)
log.flush()
retCode = subprocess.call(command, stdout=log, stderr=log)
if retCode != 0:
print("Execution of %s failed. Look into %s for details." % (
command, log.name), file=sys.stderr)
sys.exit(retCode)
def writeRouteConf(step, options, file, output):
fd = open("iteration_" + str(step) + ".duarcfg", "w")
print("""<configuration>
<input>
<net-file value="%s"/>""" % options.net, file=fd)
print(' <route-files value="%s"/>' % file, file=fd)
if step > 0:
print(' <weights value="dump_%s_%s.xml"/>' % (
step - 1, options.aggregation), file=fd)
print(""" </input>
<output>
<output-file value="%s"/>
<exit-times value="True"/>
</output>""" % output, file=fd)
print(""" <processing>
<continue-on-unbuild value="%s"/>
<expand-weights value="True"/>
<gBeta value="%s"/>
<gA value="%s"/>
</processing>""" % (options.continueOnUnbuild, options.gBeta, options.gA), file=fd)
print(' <random_number><abs-rand value="%s"/></random_number>' %
options.absrand, file=fd)
print(' <time><begin value="%s"/>' % options.begin, end=' ', file=fd)
if options.end:
print('<end value="%s"/>' % options.end, end=' ', file=fd)
print("""</time>
<report>
<verbose value="%s"/>
<suppress-warnings value="%s"/>
</report>
</configuration>""" % (options.verbose, options.noWarnings), file=fd)
fd.close()
class RouteReader(handler.ContentHandler):
def __init__(self):
self._edgeWeights = {}
self._maxDepart = 0
def startElement(self, name, attrs):
if name == 'route':
for edge in attrs['edges'].split():
if edge not in self._edgeWeights:
self._edgeWeights[edge] = 0
self._edgeWeights[edge] += 1
elif name == 'vehicle':
if float(attrs['depart']) > self._maxDepart:
self._maxDepart = float(attrs['depart'])
def getWeight(self, edge):
return self._edgeWeights.get(edge, 0)
def getMaxDepart(self):
return self._maxDepart
class NetReader(handler.ContentHandler):
def __init__(self):
self._edges = []
def startElement(self, name, attrs):
if name == 'edge':
if 'function' not in attrs or attrs['function'] == 'normal':
self._edges.append(attrs['id'])
def getEdges(self):
return self._edges
def identity(edge, weight):
return weight
def generateWeights(step, options, edges, weights, costFunction):
fd = open("dump_%s_%s.xml" % (step, options.aggregation), "w")
print('<?xml version="1.0"?>\n<netstats>', file=fd)
for time in range(0, int(reader.getMaxDepart() + 1), options.aggregation):
print(' <interval begin="%s" end="%s" id="dump_%s">' % (
time, time + options.aggregation, options.aggregation), file=fd)
for edge in edges:
cost = costFunction(edge, weights.getWeight(edge))
if cost is not None:
print(' <edge id="%s" traveltime="%s"/>' % (
edge, cost), file=fd)
print(' </interval>', file=fd)
print('</netstats>', file=fd)
fd.close()
parser = sumolib.options.ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true", dest="verbose",
default=False, help="tell me what you are doing")
parser.add_argument("--continue-on-unbuild", action="store_true", dest="continueOnUnbuild",
default=False, help="continues on unbuild routes")
parser.add_argument("-w", "--disable-warnings", action="store_true", dest="noWarnings",
default=False, help="disables warnings")
parser.add_argument("-n", "--net-file", dest="net", type=parser.net_file,
help="SUMO network (mandatory)", metavar="FILE")
parser.add_argument("-t", "--trips", dest="trips", type=parser.route_file,
help="trips in step 0 (this or flows is mandatory)", metavar="FILE")
parser.add_argument("-F", "--flows", type=parser.route_file,
help="flows in step 0 (this or trips is mandatory)", metavar="FILE")
parser.add_argument("-+", "--additional", dest="additional", type=parser.additional_file,
default="", help="Additional files")
parser.add_argument("-b", "--begin", dest="begin",
type=parser.time, default=0, help="Set simulation/routing begin [default: %(default)s]")
parser.add_argument("-e", "--end", dest="end",
type=parser.time, help="Set simulation/routing end [default: %(default)s]")
parser.add_argument("-R", "--route-steps", dest="routeSteps",
type=int, default=200, help="Set simulation route steps [default: %(default)s]")
parser.add_argument("-a", "--aggregation", dest="aggregation",
type=parser.time, default=900, help="Set main weights aggregation period [default: %(default)s]")
parser.add_argument("-A", "--gA", dest="gA",
type=float, default=.5, help="Sets Gawron's Alpha [default: %(default)s]")
parser.add_argument("-B", "--gBeta", dest="gBeta",
type=float, default=.9, help="Sets Gawron's Beta [default: %(default)s]")
parser.add_argument("-f", "--first-step", dest="firstStep",
type=int, default=0, help="First DUA step [default: %(default)s]")
parser.add_argument("-l", "--last-step", dest="lastStep",
type=int, default=50, help="Last DUA step [default: %(default)s]")
parser.add_argument("-p", "--path", dest="path", type=str, help="Path to binaries")
parser.add_argument("-y", "--absrand", dest="absrand", action="store_true",
default=False, help="use current time to generate random number")
parser.add_argument("--cost-function", dest="costfunc", type=str,
default="identity", help="(python) function to use as cost function")
options = parser.parse_args()
if not options.net or not (options.trips or options.flows):
parser.error(
"At least --net-file and --trips or --flows have to be given!")
duaBinary = sumolib.checkBinary("duarouter", options.path)
log = open("dua-log.txt", "w+")
saxparser = make_parser()
reader = NetReader()
saxparser.setContentHandler(reader)
saxparser.parse(options.net)
edges = reader.getEdges()
if "." in options.costfunc:
idx = options.costfunc.rfind(".")
module = options.costfunc[:idx]
func = options.costfunc[idx + 1:]
exec("from %s import %s as costFunction" % (module, func))
else:
exec("costFunction = %s" % options.costfunc)
if options.flows:
tripFiles = options.flows.split(",")
else:
tripFiles = options.trips.split(",")
starttime = datetime.now()
for step in range(options.firstStep, options.lastStep):
btimeA = datetime.now()
print("> Executing step " + str(step))
files = []
for tripFile in tripFiles:
file = tripFile
tripFile = os.path.basename(tripFile)
if step > 0:
file = tripFile[
:tripFile.find(".")] + "_%s.rou.alt.xml" % (step - 1)
output = tripFile[:tripFile.find(".")] + "_%s.rou.xml" % step
print(">> Running router with " + file)
btime = datetime.now()
print(">>> Begin time: %s" % btime)
writeRouteConf(step, options, file, output)
retCode = call([duaBinary, "-c", "iteration_%s.duarcfg" % step], log)
etime = datetime.now()
print(">>> End time: %s" % etime)
print(">>> Duration: %s" % (etime - btime))
print("<<")
files.append(output)
print(">> Generating weights")
reader = RouteReader()
saxparser.setContentHandler(reader)
for f in files:
saxparser.parse(f)
generateWeights(step, options, edges, reader, costFunction)
print("<<")
print("< Step %s ended (duration: %s)" % (step, datetime.now() - btimeA))
print("------------------\n")
sys.stdout.flush()
print("dua-iterate ended (duration: %s)" % (datetime.now() - starttime))
log.close()