mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
Port the Go experiment to Python
This commit is contained in:
parent
de86258402
commit
566f6a9e13
@ -10,9 +10,11 @@ This
|
||||
[Python example](https://github.com/dabreegster/abstreet/blob/master/headless/examples/python_client.py)
|
||||
has everything you need to get started.
|
||||
|
||||
Also check out the
|
||||
[Go example](https://github.com/dabreegster/abstreet/blob/master/headless/examples/go_client.go),
|
||||
which demonstrates just a few of the API calls.
|
||||
There's an experiment to cancel different percentages of trips and quantify the
|
||||
trip time savings on the remaining trips. The experiment is written in both
|
||||
[Go](https://github.com/dabreegster/abstreet/blob/master/headless/examples/go_client.go)
|
||||
and
|
||||
[Python](https://github.com/dabreegster/abstreet/blob/master/headless/examples/cancel_experiment.py).
|
||||
|
||||
## API details
|
||||
|
||||
|
111
headless/examples/cancel_experiment.py
Executable file
111
headless/examples/cancel_experiment.py
Executable file
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/python3
|
||||
# This example runs the same scenario repeatedly, each time cancelling a
|
||||
# different number of trips uniformly at random. The eventual goal is to
|
||||
# quantify how many trips need to be cancelled to substantially speed up
|
||||
# remaining ones.
|
||||
#
|
||||
# Before running this script, start the API server:
|
||||
#
|
||||
# > cargo run --release --bin headless -- --port=1234 data/system/scenarios/montlake/weekday.bin
|
||||
#
|
||||
# You may need to install https://requests.readthedocs.io
|
||||
# Keep this script formatted with autopep8 -i
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import requests
|
||||
import statistics
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--api', default='http://localhost:1234')
|
||||
parser.add_argument('--map_name', default='montlake')
|
||||
parser.add_argument('--hours', type=int, default=24)
|
||||
parser.add_argument('--cmp1', type=int, default=None)
|
||||
parser.add_argument('--cmp2', type=int, default=None)
|
||||
args = parser.parse_args()
|
||||
if args.cmp1 and args.cmp2 and args.cmp1 > args.cmp2:
|
||||
sys.exit(
|
||||
'--cmp1={} --cmp2={} invalid, --cmp1 is the baseline'.format(args.cmp1, args.cmp2))
|
||||
print('Simulating {} hours of data/system/scenarios/{}/weekday.bin'.format(args.hours, args.map_name))
|
||||
print('')
|
||||
|
||||
num_succeeded_last = 0
|
||||
results2 = None
|
||||
for pct in range(100, 0, -10):
|
||||
start = time.time()
|
||||
results = run_sim(args, modifiers=[{'CancelPeople': pct}])
|
||||
print('{}% of people cancelled: {:,} trips aborted, {:,} trips succeeded. Simulation took {:.1f}s'.format(
|
||||
pct, results.num_aborted, len(results.trip_times), time.time() - start))
|
||||
if len(results.trip_times) < num_succeeded_last:
|
||||
print('--> less trips succeeded this round, so likely hit gridlock')
|
||||
break
|
||||
num_succeeded_last = len(results.trip_times)
|
||||
|
||||
if args.cmp2 == pct:
|
||||
results2 = results
|
||||
if args.cmp1 == pct:
|
||||
print('')
|
||||
print('Baseline cancelled {}%, experimental cancelled {}%'.format(
|
||||
args.cmp1, args.cmp2))
|
||||
compare_results(results, results2)
|
||||
print('')
|
||||
|
||||
|
||||
# Returns Results
|
||||
def run_sim(args, modifiers=[]):
|
||||
requests.post(args.api + '/sim/load', json={
|
||||
'load': 'data/system/scenarios/{}/weekday.bin'.format(args.map_name),
|
||||
'modifiers': modifiers,
|
||||
})
|
||||
requests.get(args.api + '/sim/goto-time',
|
||||
params={'t': '{}:00:00'.format(args.hours)})
|
||||
raw_trips = requests.get(
|
||||
args.api + '/data/get-finished-trips').json()['trips']
|
||||
|
||||
# Map trip ID to the duration (in seconds) of the trip. Filter out aborted
|
||||
# (failed) trips.
|
||||
num_aborted = 0
|
||||
trip_times = {}
|
||||
for (_, trip, mode, duration) in raw_trips:
|
||||
if mode is None:
|
||||
num_aborted += 1
|
||||
else:
|
||||
trip_times[trip] = duration
|
||||
|
||||
return Results(num_aborted, trip_times)
|
||||
|
||||
|
||||
class Results:
|
||||
def __init__(self, num_aborted, trip_times):
|
||||
self.num_aborted = num_aborted
|
||||
# Maps trip ID to seconds
|
||||
self.trip_times = trip_times
|
||||
|
||||
|
||||
def compare_results(results1, results2):
|
||||
faster = []
|
||||
slower = []
|
||||
|
||||
for trip, after_dt in results2.trip_times.items():
|
||||
before_dt = results1.trip_times.get(trip)
|
||||
if not before_dt:
|
||||
# The trip didn't finish in time in the baseline run
|
||||
continue
|
||||
if before_dt:
|
||||
if before_dt > after_dt:
|
||||
faster.append(before_dt - after_dt)
|
||||
elif after_dt > before_dt:
|
||||
slower.append(after_dt - before_dt)
|
||||
|
||||
print('{:,} trips faster, average {:.1f}s savings'.format(
|
||||
len(faster), statistics.mean(faster)))
|
||||
print('{:,} trips slower, average {:.1f}s loss'.format(
|
||||
len(slower), statistics.mean(slower)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user