pyWarehouse
pyWarehouse models a warehouse as a Walkable Graph and computes picker routes using classical warehouse heuristics, custom product orders, and tabular RL policies. It also exports a polished, dependency-light HTML viewer with route animation, live telemetry, pick sequence, and a scrubbable timeline.
The package is designed for three uses:
- Warehouse Routing Experiments: Compare
s_shape,return,midpoint,largest_gap,combined,q_learning, andsarsaon the same layout. - Algorithm Teaching: Make routing policies visible, not only numerical.
- RL Research Prototyping: Expose terminal sequences, waypoint sequences, graph paths, and transition tables.
Core Idea
A warehouse is represented as a Walkable Graph:
| Component | Meaning |
|---|---|
| Steiner Nodes | Aisle/cross-aisle intersections, corridor corners, auxiliary points |
| Terminal Nodes | Product locations, start nodes, finish nodes |
| Edges | Walkable corridor segments |
| Distance | Manhattan distance along the warehouse graph, not Euclidean shortcuts |
The router builds a full terminal distance structure over the graph, so route distance, animation distance, telemetry, and RL rewards are all computed from the same physical model.
Installation
pip install pywarehouse-routing
Colab Demos
Quick Start
from pywarehouse import WarehouseLayout, Router, Plotter
# 1) Build a rectangular warehouse layout
layout = WarehouseLayout.rectangular(
num_aisles = 6,
slots_per_block = 11,
num_blocks = 1,
aisle_spacing = 5.0,
slot_pitch = 1.0,
front_corridor = 1.0,
cross_corridor = 3.0,
back_corridor = 0.0,
)
# 2) Add products as: (product_id, aisle, slot, block)
layout.add_products([
("A", 0, 5, 0),
("B", 0, 9, 0),
("D", 1, 9, 0),
("C", 1, 10, 0),
("H", 2, 1, 0),
("G", 2, 4, 0),
("E", 2, 5, 0),
("F", 2, 10, 0),
])
# 3) Start and finish can be the same depot
layout.set_start("START", x = 0.0, y = -1.0)
layout.set_finish("FINISH", x = 0.0, y = -1.0)
# 4) Build graph and solve
G, node_attrs, edges_df = layout.build_graph()
router = Router(layout, G, node_attrs)
route = router.solve(strategy = "s_shape")
print("Distance:", route.total_distance)
print("Terminals:", route.terminal_sequence)
print("Waypoints:", route.waypoint_sequence)
# 5) Export a route viewer
plotter = Plotter(G, node_attrs)
viewer = plotter.draw_route(route, label_mode = "id", title = "Route")
viewer.write_html("route.html")
Strategies
pyWarehouse supports classical warehouse heuristics, custom orders, and tabular RL strategies.
| Strategy | Type | Behavior |
|---|---|---|
s_shape |
Classical | Traverses active aisles and alternates side when useful. |
return |
Classical | Enters each active aisle, reaches the deepest required pick, and returns to the same side. |
midpoint |
Classical | Splits aisle work around the midpoint; lower picks are served from the lower corridor and upper picks from the upper corridor. |
largest_gap |
Classical | Avoids the largest unused vertical gap in each aisle. |
combined |
Hybrid classical | Chooses aisle-by-aisle whether to return or traverse, producing a mixed policy. |
q_learning |
RL | Learns a terminal-level picking sequence using tabular Q-learning. |
sarsa |
RL | Learns a terminal-level sequence using on-policy SARSA. |
custom |
User-defined | Follows a user-provided terminal order. |
Route Representation
A solved Route separates policy, physical path, and visualization data:
route.strategy
route.terminal_sequence
route.waypoint_sequence
route.waypoint_details
route.node_path
route.segments
route.movements
route.total_distance
The distinction matters:
| Attribute | Purpose |
|---|---|
terminal_sequence |
The sequence of START, products, and FINISH. |
waypoint_sequence |
Policy-level milestones, including corridor waypoints such as B0:A2:LOWER. |
waypoint_details |
JSON-friendly metadata for each waypoint. |
node_path |
Full graph path used for distance, telemetry, and animation. |
segments |
Edge-level route geometry. |
movements |
Compressed movement commands such as UP, DOWN, LEFT, RIGHT, and CHECKPOINT. |
Classical heuristics such as return, midpoint, largest_gap, and combined are not only product permutations. They are aisle policies. The waypoint layer prevents these strategies from collapsing into generic shortest-path chaining.
Tabular RL
pyWarehouse includes a compact tabular RL interface. The default RL environment is a terminal metric-closure MDP:
state = (current terminal id, picked-product bit mask)
action = next unpicked product, or FINISH after all products are picked
reward = - graph shortest-path distance
Q-learning / SARSA
from pywarehouse import QLearningConfig, TabularQLearningRouter
cfg_q = QLearningConfig(
algorithm = "q_learning",
episodes = 30000,
alpha = 0.25,
gamma = 1.0,
epsilon = 1.0,
epsilon_min = 0.02,
epsilon_decay = 0.9995,
seed = 11,
route_selection = "best", # "best" or "greedy"
)
result_q = TabularQLearningRouter(router, cfg_q).train()
route_q = result_q.route
print(route_q.terminal_sequence)
print(route_q.total_distance)
print(result_q.metadata)
cfg_s = QLearningConfig(
algorithm = "sarsa",
episodes = 30000,
alpha = 0.25,
gamma = 1.0,
epsilon = 1.0,
epsilon_min = 0.02,
epsilon_decay = 0.9995,
seed = 11,
route_selection = "best", # "best" or "greedy"
)
result_s = TabularQLearningRouter(router, cfg_s).train()
route_s = result_s.route
print(route_s.terminal_sequence)
print(route_s.total_distance)
print(result_s.metadata)
Direct Router API
route_q = router.solve(strategy = "q_learning", rl_config = cfg_q)
route_s = router.solve(strategy = "sarsa", rl_config = cfg_s)
Waypoint Transition Table
For RL diagnostics, imitation learning, or route-guidance experiments:
route = router.solve(strategy = "combined")
transitions = router.waypoint_transition_table(route)
for row in transitions:
print(row["state"], row["action"], row["next_state"], row["reward"])
Each row has the form:
{
"state": "0:START",
"action": "GO_TO:B0:A0:LOWER",
"next_state": "1:B0:A0:LOWER",
"distance": 1.0,
"reward": -1.0,
"done": False,
}
Repeated waypoints are occurrence-indexed, so a waypoint such as B0:A2:LOWER can appear multiple times without losing its visit identity.
Metadata
Release files for pyWarehouse-routing 1.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pywarehouse_routing-1.1.5.tar.gz | 52.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pywarehouse_routing-1.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 108.9 kB
Release files / pywarehouse_routing-1.1.5.tar.gz
| Download URL | pywarehouse_routing-1.1.5.tar.gz |
|---|---|
| Size | 52.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1bd7d06534cbe18b3288877d436d76aa54a11ce7c326731f9bb080d17f1b2fa3
|
|
BLAKE2b-256 checksum How to use checksums |
453f82114071d6ce6000627aadde21052f016c3ffea21bf3293753f616272496
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / pywarehouse_routing-1.1.5-py3-none-any.whl
| Download URL | pywarehouse_routing-1.1.5-py3-none-any.whl |
|---|---|
| Size | 56.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb7b28419907da27491f7c3c8bde3ca35f38cd57132476dc262b7d6f8ba24330
|
|
BLAKE2b-256 checksum How to use checksums |
1f5e326717bd0fb36f443635f05782bf958e6719c6fc3dcd15520309087870d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|