Graph-based warehouse order-picking layouts, heuristics, and self-contained web visualization.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pywarehouse_routing-1.1.5.tar.gz.
File metadata
- Download URL: pywarehouse_routing-1.1.5.tar.gz
- Upload date:
- Size: 52.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bd7d06534cbe18b3288877d436d76aa54a11ce7c326731f9bb080d17f1b2fa3
|
|
| MD5 |
3ca3e7581e1a0d48794e822dfde84118
|
|
| BLAKE2b-256 |
453f82114071d6ce6000627aadde21052f016c3ffea21bf3293753f616272496
|
File details
Details for the file pywarehouse_routing-1.1.5-py3-none-any.whl.
File metadata
- Download URL: pywarehouse_routing-1.1.5-py3-none-any.whl
- Upload date:
- Size: 56.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb7b28419907da27491f7c3c8bde3ca35f38cd57132476dc262b7d6f8ba24330
|
|
| MD5 |
a52232399790e85104b5722d072264a4
|
|
| BLAKE2b-256 |
1f5e326717bd0fb36f443635f05782bf958e6719c6fc3dcd15520309087870d6
|