Deterministic 3D cartonization and rectangular bin packing. Pure Python, no runtime dependencies, exact integer geometry.
Full documentation, the constraint reference and benchmarks live at packvium.com.
Version 1.3.0 — the public API is frozen. Field names, status codes and the objective vector do not change without a major version, so any
1.xis a safe upgrade from any earlier1.x. Read docs/GUARANTEES.md before relying on a result.
pip install packviumfrom packvium import Container, Dimensions, Item, Packer, PackingConfig
result = Packer(PackingConfig.balanced()).pack(
items=[Item.create("book", Dimensions.mm("210", "140", "30"), quantity=4)],
containers=[Container.create("box", Dimensions.mm("400", "300", "250"))],
)
print(result.status) # feasible
for container in result.containers:
for placement in container.placements:
print(placement.item_id, placement.position, placement.orientation)Fractional inches are exact, not approximated:
Dimensions.inches("12 3/8", "8 1/2", "3/4")There is also a CLI that reads a JSON request on standard input:
echo '{"items":[{"id":"box","quantity":8,"dimensions":{"length":"50","width":"50","height":"50"}}],
"containers":[{"id":"carton","inner_dimensions":{"length":"100","width":"100","height":"100"}}]}' \
| python -m packviumRunnable, in examples/. Each one is a single file you can read top to bottom
and execute without a project around it. Every one of them is executed by the test suite
on each release, so none of them can quietly stop working.
New here? Read basic.py, then objectives.py — between them they cover what most
callers need. units.py and serialization.py explain the two design choices that
surprise people. extensions.py is last on purpose: reach for it only after the fields
in constraints.py have failed you.
| File | What it shows |
|---|---|
basic.py |
The smallest useful call: items in, placements out — and the three details in it that are easy to miss. |
objectives.py |
All six objectives on scenes where they genuinely disagree, including the rate card that makes the heavier shipment the cheaper one. |
constraints.py |
Upright-only, floor-only, non-stackable, top-load limits, and tags that keep two items out of the same box — plus how to read the reason an item was refused. |
units.py |
Why there are no floats anywhere: fractional inches, exact ticks, and the one-tick difference between a fit and a refusal. |
serialization.py |
The same request as JSON, the result in full, and exactly which mistakes are refused and which are silently ignored. |
shapes.py |
Items that are not their box: complementary wedges sharing one crate as convex_hull, and a cushion that compresses under load until the crush limit refuses it. |
nested.py |
Units into cartons, cartons onto a pallet, in one call. |
commerce.py |
Rate a shipment, apply an eligibility rule, and pin a catalog version. |
execution.py |
Turn a result into dock instructions: solver facts kept apart from screen text, a step order that is injected or honestly absent, and an operator lock that yields a second plan rather than editing the approved one. |
artifacts.py |
Hand a result to a system with no engine: one document with the plan, geometry and the request that produced it, exported as CSV and a printable work order, with an honest replay level. |
intelligence.py |
Prove a carton change is worth publishing: two scenarios compared order by order, a proposal that refuses to exist on thin evidence, and a replay against held-out history where a cheaper packing your validator rejects still counts as a regression. |
extensions.py |
A rule the schema has no field for — and an honest account of what you give up by writing one. |
PYTHONPATH=src python3 examples/objectives.py- Exact arithmetic. Length is measured in ticks of 1/16000 mm and weight in 1/8 µg. No coordinate is ever a float, so no placement decision depends on rounding.
- Real constraints. Weight and payload limits, permitted rotations, keep-upright, floor-only, non-stackable, top-load limits, minimum support ratio, tag incompatibility, clearance and rectangular obstacles.
- A solver portfolio, not one algorithm. Regular-grid, layer, extreme-point, maximal-space and bounded exact search, selected by problem shape and profile.
- Answers you can check. Every solution is re-validated by logic independent of the search. Unplaced items come back with a reason code, not silently missing.
- Deterministic. The same input and seed produce the same result, always.
- Multi-container and nested. Split across containers, or pack containers into containers.
- Extensible. Register your own constraints, item orderings, candidate scorers, container selectors or complete solvers.
- Work orders, not just coordinates.
packvium.executionturns a validated result into a plan: solver facts kept apart from the text that cites them, an injected loading order or an honestunavailable, and a canonical form four engines emit byte for byte.packvium.lockslets an operator pin a placement and get a second plan beside the approved one — never an edit of it, and never a placement the engine would refuse. - Artifacts a warehouse system can use without an engine.
packvium.artifactswraps the plan with geometry, display values and provenance, including the request itself and an honest replay level.packvium.artifact_exportswrites it as RFC 8785 JSON, CSV or a self-contained HTML work order, byte for byte what the other engines write. - Decide before you publish.
packvium.simulationandpackvium.recommendationscompare two catalog scenarios order by order and propose a change only when the paired cohort supports it;packvium.holdoutreplays that proposal against history it has not seen. Python-only, and supported but not yet signature-frozen — see PUBLIC-API.md.
| Document | Covers |
|---|---|
| docs/GUARANTEES.md | What is promised and what is not. Start here. |
| docs/PUBLIC-API.md | Inputs, outputs and status semantics. |
| docs/UNITS-AND-NUMERICS.md | Units, accepted input forms, rounding policy. |
Python 3.9 or newer. No dependencies.
One request and result contract, implemented independently in four engines (Rust, Python, PHP, JavaScript) and held to identical placements on a shared fixture set. Pick the package for your stack; mixing them in one system is safe.
Documentation, the constraint reference and the benchmarks are at packvium.com.
| Package | Install | Source |
|---|---|---|
Python — packvium |
pip install packvium |
packvium-python |
PHP — packvium/packvium |
composer require packvium/packvium |
packvium-php |
Rust — packvium |
packvium = "1.0" |
packvium-rust |
Node.js — @packvium/engine |
npm install @packvium/engine |
packvium-node |
Browser / WebAssembly — @packvium/browser |
npm install @packvium/browser |
packvium-wasm |
PHP FFI bridge — packvium/native-bridge |
composer require packvium/native-bridge |
packvium-php-bridge |
Python native selector — packvium-native |
from source until the native wheels ship | packvium-python-adapter |
See CONTRIBUTING.md. Security reports go through the process in SECURITY.md, not public issues.
MIT. See LICENSE.