Metadata-Version: 2.4
Name: ride-gym
Version: 0.1.0
Summary: A multi-agent ride-pooling & dispatching simulation environment for transportation gig-market research.
Author: Zijian Zhao, Yulong Hu, Sen Li
Maintainer: Zijian Zhao, Yulong Hu, Sen Li
License-Expression: MIT
Project-URL: Homepage, https://github.com/RS2002/RideGym
Project-URL: Repository, https://github.com/RS2002/RideGym
Project-URL: Issues, https://github.com/RS2002/RideGym
Keywords: reinforcement-learning,ride-pooling,ride-hailing,simulation,multi-agent,gym,dispatching,transportation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.21
Provides-Extra: data
Requires-Dist: pandas>=1.3; extra == "data"
Requires-Dist: pyarrow>=6.0; extra == "data"
Requires-Dist: geopandas>=0.10; extra == "data"
Requires-Dist: osmnx>=1.3; extra == "data"
Requires-Dist: networkx>=2.6; extra == "data"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.4; extra == "viz"
Provides-Extra: osmnx
Requires-Dist: osmnx>=1.3; extra == "osmnx"
Requires-Dist: networkx>=2.6; extra == "osmnx"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Provides-Extra: all
Requires-Dist: pandas>=1.3; extra == "all"
Requires-Dist: pyarrow>=6.0; extra == "all"
Requires-Dist: geopandas>=0.10; extra == "all"
Requires-Dist: matplotlib>=3.4; extra == "all"
Requires-Dist: osmnx>=1.3; extra == "all"
Requires-Dist: networkx>=2.6; extra == "all"
Dynamic: license-file

# RideGym

**RideGym** is a Gym-like (but not Gym-dependent) simulation environment for large-scale ride-pooling and order dispatching. A fleet of vehicles serves a stream of ride requests that arrive over time, with realistic pooling, capacity limits, road-network routing, and impatient passengers.

The environment models each vehicle as an agent under a fully-centralized multi-agent setting: at every decision step you assign pending orders to vehicles, and the simulator handles conflict resolution, route re-planning, movement, and reward computation. It is built from swappable components (order source, road network, route planner, reward), so you can plug in your own without touching the core loop.

## Installation

```bash
pip install ride-gym
```

The core only needs `numpy`. Install extras as needed:

```bash
pip install ride-gym[data]     # pandas: build demand from a DataFrame
pip install ride-gym[osmnx]    # real OpenStreetMap road networks
pip install ride-gym[viz]      # matplotlib: rendering & animation
pip install ride-gym[all]      # everything
```

Requires Python >= 3.9.

## Quickstart

```python
from ride_gym import RidePoolEnv
from ride_gym.order_generator import RandomOrderGenerator
from ride_gym.road_network import ManhattanNetwork

# 1. Demand: your own trips, or a procedural generator.
order_gen = RandomOrderGenerator(
    area=(0.0, 0.0, 10.0, 10.0), horizon=60.0, num_orders=10000,
    arrival="poisson", max_party_size=3,
)

# 2. Road network: abstract backend, or a real OSM graph (see below).
network = ManhattanNetwork(speed=1.0)   # coordinate units per minute

# 3. Environment.
env = RidePoolEnv(
    num_drivers=1000,
    driver_capacity=4,
    dt=1.0, horizon=60.0,
    order_timeout=3.0,          # orders waiting longer than this are withdrawn
    order_generator=order_gen,
    road_network=network,
)

# 4. Roll out. obs / rewards are dicts keyed by vehicle id.
obs, info = env.reset(seed=0)
done = False
while not done:
    actions = {}
    for i, s_v in obs.items():
        pool = s_v["pending_orders"]        # orders waiting to be assigned
        order_ids = my_policy(s_v, pool)    # -> list of order ids to bid on
        actions[i] = {"orders": order_ids}  # empty list = take no order
    obs, rewards, dones, info = env.step(actions)
    done = dones["__all__"]
```

Drop your training code straight into the loop between `step` calls.

## Actions

Each vehicle's action is a small dict (the two keys are mutually exclusive):

```python
{"orders": [order_id, ...]}    # bid on pending orders (empty = take no order)
{"relocate": index_or_coord}   # idle vehicles only: reposition to a point
```

The simulator automatically enforces feasibility every step: an order goes to at most one vehicle, and a vehicle never exceeds its remaining capacity.

## Order sources

Bring your own historical trips as a table (one row per order):

```python
from ride_gym.order_generator import DataFrameOrderGenerator

# Columns: origin_x, origin_y, dest_x, dest_y, request_time, num_passengers
order_gen = DataFrameOrderGenerator(dataframe=my_orders_df)
```

or use `RandomOrderGenerator` for synthetic demand with `uniform` / `poisson` / `peak` arrivals.

## Road networks

For abstract experiments, use the fast closed-form `EuclideanNetwork` or `ManhattanNetwork`. For real maps, `OSMnxNetwork` loads an OpenStreetMap graph whose all-pairs shortest paths are precomputed and cached to disk, so every distance query is an `O(1)` lookup:

```python
from ride_gym.osmnx_network import OSMnxNetwork
network = OSMnxNetwork(graph_path="data/manhattan.gpickle")
```

## Custom rewards

A `DefaultRewardFunction` modelling platform revenue and passenger satisfaction is provided. To optimize for your own criteria (waiting time, service rate, detour, ...), subclass `RewardFunction` and pass it to the env:

```python
from ride_gym import RidePoolEnv, DefaultRewardFunction
env = RidePoolEnv(..., reward_function=DefaultRewardFunction(assignment_bonus=1.0))
```

## Centralized view

For single-agent / global-optimization research, wrap the env so one policy emits all actions and gets an aggregated reward (the per-vehicle rewards are kept in `info`):

```python
from ride_gym import CentralizedWrapper
env = CentralizedWrapper(RidePoolEnv(...), aggregate="sum")
obs, reward, done, info = env.step(joint_action)
```

## Visualization

With the `[viz]` extra you can render a single frame or animate a whole episode:

```python
from ride_gym.visualize import TrajectoryRecorder, render_animation

env.render(mode="human", save_path="frame.png")   # one static frame

rec = TrajectoryRecorder()
obs, _ = env.reset(seed=0)
done = False
while not done:
    obs, rewards, dones, info = env.step(my_policy(obs))
    rec.snapshot(env)
    done = dones["__all__"]
render_animation(rec, out_path="episode.gif")     # or .mp4
```

Each vehicle is drawn in its own color, with its current location, planned route along the road network, and the origins/destinations of the orders it is serving. Aggregate plots (demand & service heatmaps, supply-demand gaps, load time series, waiting-time distributions) are also available.


## Authors

- Zijian Zhao
- Yulong Hu
- Sen Li

The Hong Kong University of Science and Technology.

## License

MIT License. See [LICENSE](LICENSE) for details.
