Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/assign/costFunctionChecker.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-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 costFunctionChecker.py
15
# @author Michael Behrisch
16
# @author Daniel Krajzewicz
17
# @author Jakob Erdmann
18
# @author Mirko Barthauer
19
# @date 2009-08-31
20
21
from __future__ import absolute_import
22
from __future__ import print_function
23
import os
24
import sys
25
import subprocess
26
from datetime import datetime
27
from xml.sax import make_parser, handler
28
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
29
import sumolib # noqa
30
31
32
def call(command, log):
33
if not isinstance(command, str):
34
command = [str(c) for c in command]
35
print("-" * 79, file=log)
36
print(command, file=log)
37
log.flush()
38
retCode = subprocess.call(command, stdout=log, stderr=log)
39
if retCode != 0:
40
print("Execution of %s failed. Look into %s for details." % (
41
command, log.name), file=sys.stderr)
42
sys.exit(retCode)
43
44
45
def writeRouteConf(step, options, file, output):
46
fd = open("iteration_" + str(step) + ".duarcfg", "w")
47
print("""<configuration>
48
<input>
49
<net-file value="%s"/>""" % options.net, file=fd)
50
print(' <route-files value="%s"/>' % file, file=fd)
51
if step > 0:
52
print(' <weights value="dump_%s_%s.xml"/>' % (
53
step - 1, options.aggregation), file=fd)
54
print(""" </input>
55
<output>
56
<output-file value="%s"/>
57
<exit-times value="True"/>
58
</output>""" % output, file=fd)
59
print(""" <processing>
60
<continue-on-unbuild value="%s"/>
61
<expand-weights value="True"/>
62
<gBeta value="%s"/>
63
<gA value="%s"/>
64
</processing>""" % (options.continueOnUnbuild, options.gBeta, options.gA), file=fd)
65
print(' <random_number><abs-rand value="%s"/></random_number>' %
66
options.absrand, file=fd)
67
print(' <time><begin value="%s"/>' % options.begin, end=' ', file=fd)
68
if options.end:
69
print('<end value="%s"/>' % options.end, end=' ', file=fd)
70
print("""</time>
71
<report>
72
<verbose value="%s"/>
73
<suppress-warnings value="%s"/>
74
</report>
75
</configuration>""" % (options.verbose, options.noWarnings), file=fd)
76
fd.close()
77
78
79
class RouteReader(handler.ContentHandler):
80
81
def __init__(self):
82
self._edgeWeights = {}
83
self._maxDepart = 0
84
85
def startElement(self, name, attrs):
86
if name == 'route':
87
for edge in attrs['edges'].split():
88
if edge not in self._edgeWeights:
89
self._edgeWeights[edge] = 0
90
self._edgeWeights[edge] += 1
91
elif name == 'vehicle':
92
if float(attrs['depart']) > self._maxDepart:
93
self._maxDepart = float(attrs['depart'])
94
95
def getWeight(self, edge):
96
return self._edgeWeights.get(edge, 0)
97
98
def getMaxDepart(self):
99
return self._maxDepart
100
101
102
class NetReader(handler.ContentHandler):
103
104
def __init__(self):
105
self._edges = []
106
107
def startElement(self, name, attrs):
108
if name == 'edge':
109
if 'function' not in attrs or attrs['function'] == 'normal':
110
self._edges.append(attrs['id'])
111
112
def getEdges(self):
113
return self._edges
114
115
116
def identity(edge, weight):
117
return weight
118
119
120
def generateWeights(step, options, edges, weights, costFunction):
121
fd = open("dump_%s_%s.xml" % (step, options.aggregation), "w")
122
print('<?xml version="1.0"?>\n<netstats>', file=fd)
123
for time in range(0, int(reader.getMaxDepart() + 1), options.aggregation):
124
print(' <interval begin="%s" end="%s" id="dump_%s">' % (
125
time, time + options.aggregation, options.aggregation), file=fd)
126
for edge in edges:
127
cost = costFunction(edge, weights.getWeight(edge))
128
if cost is not None:
129
print(' <edge id="%s" traveltime="%s"/>' % (
130
edge, cost), file=fd)
131
print(' </interval>', file=fd)
132
print('</netstats>', file=fd)
133
fd.close()
134
135
136
parser = sumolib.options.ArgumentParser()
137
parser.add_argument("-v", "--verbose", action="store_true", dest="verbose",
138
default=False, help="tell me what you are doing")
139
parser.add_argument("--continue-on-unbuild", action="store_true", dest="continueOnUnbuild",
140
default=False, help="continues on unbuild routes")
141
parser.add_argument("-w", "--disable-warnings", action="store_true", dest="noWarnings",
142
default=False, help="disables warnings")
143
144
parser.add_argument("-n", "--net-file", dest="net", type=parser.net_file,
145
help="SUMO network (mandatory)", metavar="FILE")
146
parser.add_argument("-t", "--trips", dest="trips", type=parser.route_file,
147
help="trips in step 0 (this or flows is mandatory)", metavar="FILE")
148
parser.add_argument("-F", "--flows", type=parser.route_file,
149
help="flows in step 0 (this or trips is mandatory)", metavar="FILE")
150
parser.add_argument("-+", "--additional", dest="additional", type=parser.additional_file,
151
default="", help="Additional files")
152
153
parser.add_argument("-b", "--begin", dest="begin",
154
type=parser.time, default=0, help="Set simulation/routing begin [default: %(default)s]")
155
parser.add_argument("-e", "--end", dest="end",
156
type=parser.time, help="Set simulation/routing end [default: %(default)s]")
157
parser.add_argument("-R", "--route-steps", dest="routeSteps",
158
type=int, default=200, help="Set simulation route steps [default: %(default)s]")
159
parser.add_argument("-a", "--aggregation", dest="aggregation",
160
type=parser.time, default=900, help="Set main weights aggregation period [default: %(default)s]")
161
parser.add_argument("-A", "--gA", dest="gA",
162
type=float, default=.5, help="Sets Gawron's Alpha [default: %(default)s]")
163
parser.add_argument("-B", "--gBeta", dest="gBeta",
164
type=float, default=.9, help="Sets Gawron's Beta [default: %(default)s]")
165
166
parser.add_argument("-f", "--first-step", dest="firstStep",
167
type=int, default=0, help="First DUA step [default: %(default)s]")
168
parser.add_argument("-l", "--last-step", dest="lastStep",
169
type=int, default=50, help="Last DUA step [default: %(default)s]")
170
parser.add_argument("-p", "--path", dest="path", type=str, help="Path to binaries")
171
172
parser.add_argument("-y", "--absrand", dest="absrand", action="store_true",
173
default=False, help="use current time to generate random number")
174
parser.add_argument("--cost-function", dest="costfunc", type=str,
175
default="identity", help="(python) function to use as cost function")
176
177
options = parser.parse_args()
178
179
if not options.net or not (options.trips or options.flows):
180
parser.error(
181
"At least --net-file and --trips or --flows have to be given!")
182
183
184
duaBinary = sumolib.checkBinary("duarouter", options.path)
185
log = open("dua-log.txt", "w+")
186
187
saxparser = make_parser()
188
reader = NetReader()
189
saxparser.setContentHandler(reader)
190
saxparser.parse(options.net)
191
edges = reader.getEdges()
192
193
if "." in options.costfunc:
194
idx = options.costfunc.rfind(".")
195
module = options.costfunc[:idx]
196
func = options.costfunc[idx + 1:]
197
exec("from %s import %s as costFunction" % (module, func))
198
else:
199
exec("costFunction = %s" % options.costfunc)
200
201
if options.flows:
202
tripFiles = options.flows.split(",")
203
else:
204
tripFiles = options.trips.split(",")
205
starttime = datetime.now()
206
for step in range(options.firstStep, options.lastStep):
207
btimeA = datetime.now()
208
print("> Executing step " + str(step))
209
210
# router
211
files = []
212
for tripFile in tripFiles:
213
file = tripFile
214
tripFile = os.path.basename(tripFile)
215
if step > 0:
216
file = tripFile[
217
:tripFile.find(".")] + "_%s.rou.alt.xml" % (step - 1)
218
output = tripFile[:tripFile.find(".")] + "_%s.rou.xml" % step
219
print(">> Running router with " + file)
220
btime = datetime.now()
221
print(">>> Begin time: %s" % btime)
222
writeRouteConf(step, options, file, output)
223
retCode = call([duaBinary, "-c", "iteration_%s.duarcfg" % step], log)
224
etime = datetime.now()
225
print(">>> End time: %s" % etime)
226
print(">>> Duration: %s" % (etime - btime))
227
print("<<")
228
files.append(output)
229
# generating weights file
230
print(">> Generating weights")
231
reader = RouteReader()
232
saxparser.setContentHandler(reader)
233
for f in files:
234
saxparser.parse(f)
235
# see evaluation of options.costfunc above
236
generateWeights(step, options, edges, reader, costFunction) # noqa
237
print("<<")
238
print("< Step %s ended (duration: %s)" % (step, datetime.now() - btimeA))
239
print("------------------\n")
240
sys.stdout.flush()
241
print("dua-iterate ended (duration: %s)" % (datetime.now() - starttime))
242
243
log.close()
244
245