PhysicsOfMobility/ridepy

SimulationSet: `t_cutoff` bug and documention inconsistencies

s-bien opened this issue · 4 comments

The parameter t_cutoff in SimulationSet does not work. Instead, whenever providing the parameter, it seems that somehow the alternative parameter n_reqs gets set to the value 100.
As a result, the simulation is not cut off, but instead continues until the RequestGenerator has generated 100 request, i.e. until roughly time 100/rate.

This seems to happen always, no matter if providing t_cutoff as a base, zip, or product parameter, and no matter any other parameter values.

Also, the section https://ridepy.org/extras.html#parameter-configuration seems to be wrong or outdated:

  1. SimulationSet.default_base_params does not seem to exist,
  2. the parameter dictionary structure seems to be outdated. The structure at https://ridepy.org/extras.html#ridepy.extras.simulation_set.perform_single_simulation seems to be the correct one.

For reproduction of the t_cutoff bug:

import pandas as pd
from pathlib import Path

from ridepy.data_structures_cython import TransportationRequest
from ridepy.vehicle_state_cython import VehicleState
from ridepy.util.dispatchers_cython import BruteForceTotalTravelTimeMinimizingDispatcher

from ridepy.util.request_generators import RandomRequestGenerator
from ridepy.fleet_state import SlowSimpleFleetState
from ridepy.util.analytics import get_stops_and_requests
from ridepy.extras.simulation_set import SimulationSet, make_file_path
from ridepy.extras.io import read_events_json, read_params_json

output_path = Path("./output/tmp").resolve()

simulation_set = SimulationSet(
    base_params={
        "general": {"t_cutoff": 10, "n_vehicles": 1},
        "request_generator": {"rate": 1},
    },
    data_dir=output_path,
)

simulation_set.run()
simulation_set.run_analytics(only_stops_and_requests=True)

print(read_params_json(simulation_set.param_paths[0]))

stops_fpath = make_file_path(simulation_set.simulation_ids[0], output_path, "_stops.pq")
print(pd.read_parquet(stops_fpath).tail())

The first print shows that n_reqs=100 has been set, while still displaying t_cutoff=10.
The second print shows that the simulation runs until a time of roughly 100.

Thanks for reporting this! I'll have a look.

What you observed turned out to be a mix of intended behavior, and my failure to highlight this intended behavior :)

  • With the SimulationSet parameter dicts, there are two cases in which only a subset of otherwise contradicting parameters must be supplied:
    • Either n_reqs or t_cutoff
    • Either (n_vehicles and initial_location) or initial_locations.
  • The parameter(s) that are not specified in this case need to be set to None, otherwise an exception will be raised (which didn't happen due to a faulty if-condition, that was indeed a bug)

Thus, the solution to t_cutoff not being respected is simply to also specify n_reqs=None. I.e., for your example:

simulation_set = SimulationSet(
    base_params={
        "general": {"t_cutoff": 10, "n_vehicles": 1, "n_reqs": None},
        "request_generator": {"rate": 1},
    },
    data_dir=output_path,
)

which produces the following stops DataFrame:

timestamp delta_occupancy request_id state_duration occupancy location dist_to_next time_to_next
(0.0, 12) 8.30672 -1 5 0.254385 2 [0.34025052 0.1554795 ] 0.254385 0.254385
(0.0, 13) 8.56111 -1 6 0.722341 1 [0.09274584 0.09671638] 0.722341 0.722341
(0.0, 14) 9.28345 -1 4 0.598439 0 [0.80943046 0.00649876] 0.598439 0.598439
(0.0, 15) 9.88189 1 7 0.118111 1 [0.84749437 0.60372603] 0.118111 0.118111
(0.0, 16) 10 0 -200 0 1 [0.81146118 0.71620629] nan nan

Thanks again for pointing this out, also the outdated documentation. I have tried to improve and update it (see here). Maybe you can take a look and tell me if there's still something missing from or confusing about it.

Regarding SimulationSet.default_base_params not existing: As there is some logic to do before the dictionary can be created (switching between Python and Cython data structures), it is only available after instantiation:

>>> SimulationSet(data_dir='.').default_base_params
{'general': {'n_reqs': 100,
  't_cutoff': None,
  'space': Euclidean2D(velocity=1.0),
  'n_vehicles': 10,
  'initial_location': (0, 0),
  'initial_locations': None,
  'seat_capacity': 8,
  'transportation_request_cls': ridepy.data_structures_cython.data_structures.TransportationRequest,
  'vehicle_state_cls': ridepy.vehicle_state_cython.vehicle_state.VehicleState,
  'fleet_state_cls': ridepy.fleet_state.SlowSimpleFleetState},
 'dispatcher': {'dispatcher_cls': ridepy.util.dispatchers_cython.dispatchers.BruteForceTotalTravelTimeMinimizingDispatcher},
 'request_generator': {'request_generator_cls': ridepy.util.request_generators.RandomRequestGenerator,
  'rate': 1}}

I've added the defaults now also to the documentation page to have them more readily available. Hope this helps :)

Edit: The fix is included in the newest release version, 2.4.2.post1.

@s-bien Does it work for you now/can I close this issue?

Sorry for not replying earlier! I just checked it today and everything seems to work like I expect it to :)