Releases: HansBug/packingsolver3d
Release list
v0.0.5
Upstream moved to PackingSolver 9ae71316
Five upstream commits since d10db9d7, two of them fixes for crashes reported from this package:
- Bin weight checks use one absolute tolerance. fontanf/packingsolver#586 (fixes #582) replaces the multiplicative
PSTOLslack the branching schemes relaxed against with a tolerance precomputed from the highest bin weight of the instance, applied identically in the search and inSolution::build. The ROADEF 2022 instanceX/MA4/MA4_2520aborted in all four optimisation modes with solution doesn't satisfy bin weight capacity ond10db9d7; it now places its 122 items in 0.8–1.6 s in every mode. Applied toonedimensional,box,rectangleandboxstacks. - Sequential value correction no longer aborts on a multi-bin knapsack. #588 (fixes #587) stops dividing by the packed copies of an item type the previous pass left out entirely; such a type keeps its profit instead of poisoning the next pass with Items must have strictly positive profits. Of 36 synthetic multi-bin
boxstacksknapsack loads (2–3 containers, 3–12 item types, 1.2–2.0 times the volume), 19 aborted ond10db9d7and none do now; one improves (118 → 127 items), none worsens. Upstream's regression instance is replayed by this package's upstream-case tests. boxstacksexposes its remainingOptimizeParameterson the command line and drops the unuseduse_tree_searchfield (the bridge never set it); theshapeandmathoptsolverscmakedependencies are bumped (the stricterconvex_hullonly affectsirregular, which this package does not build).
Algorithm paths and their pacing are unchanged: the three multi-bin bin-packing loads of the SSK path end with the same items, bins and times to the millisecond, so the recommend_time_budget constants measured on d10db9d7 are kept. Data and scripts of the comparison: gist.
Compatibility
- No API change; calls behave as in 0.0.4, apart from the upstream fixes above.
__UPSTREAM_COMMIT__is9ae71316e8856c0a312f06b61b536e44f37d0d5d.
Wheels: CPython 3.7 to 3.14 on Linux x86_64 / aarch64, Windows AMD64 / ARM64, macOS arm64 / x86_64, built with PACKINGSOLVER_USE_HIGHS=ON, as before.
v0.0.4
Upstream moved to PackingSolver d10db9d7
- Multi-bin
boxstacksbin packing fills bins one at a time. Upstream9bfb9431adds a sequential single knapsack path (SSK) next to sequential value correction (SVC), chosen by the same mean-items-per-bin thresholds asbox;63ed7915(fontanf/packingsolver#584) forwards the timer to the DP pricing subproblem andd10db9d7enables its pairing heuristic. On 43 container loads with a 60 s limit: loads without a solution 31 → 15 of 43, first solution median 30 s → 0.5 s, no time-limit overrun. Knapsack and variable-sized bin packing with several bins still runSVC. - Not included: fontanf/packingsolver#586 (the weight-tolerance abort of #582) is not merged upstream yet.
New API
stop_when_unimproved_ratioonbox.solve/boxstacks.solve: a relative patience. The solve stops once no improvement has arrived for the larger ofstop_when_unimproved_forandratiotimes the time of the last improvement, and never before a first solution exists. Upstream's anytime searches double their queues between passes, so a fixed patience either cuts late passes short or wastes most of the budget; the relative one waits for the next pass wherever the search is.recommend_time_budgetnow returns that ratio (alpha / 2clamped to 1 … 4: 2 forbox, 4 forboxstacksat their defaultalpha), setsstop_when_unimproved_afterto the predicted first-solution latency andstop_when_unimproved_forto a 5 s floor;TimeBudget.as_options()carries all four values. 0.0.3's rule (after = T/2,patience = (T − L)/2) ended solves at 0.5–0.85 of the limit; on the recorded curves the relative rule ends them at 0.7–1.0 of a tighter limit for the balancedalphaand gives back a third of the time atalpha = 8.algorithm_pathmirrors the new multi-binboxstacksselection; the multi-binboxstackspaths were re-measured ond10db9d7(122 runs plus 24 multi-bin knapsack loads) and the constants regenerated. Docs: Explanations / Upstream behaviours gains "Multi-bin boxstacks fills bins one at a time"; the time-budget page documents the stall rule with a replay against the previous one.
Compatibility
- No breaking change; calls without the new keyword argument behave as in 0.0.3, apart from the upstream improvements above.
Wheels: CPython 3.7 to 3.14 on Linux x86_64 / aarch64, Windows AMD64 / ARM64, macOS arm64 / x86_64, built with PACKINGSOLVER_USE_HIGHS=ON, as before.
v0.0.3
Upstream moved to PackingSolver 2a598481
- Anytime single-bin
boxstacks. Upstream fontanf/packingsolver#578 turns the sequential onedimensional rectangle algorithm into an anytime variant: under a time limit the solve no longer returns the truncated result of one fixed-size pass but grows its queues level by level and always holds the best complete solution found so far. On the 40' container of the examples the 10 s result went from about half the cargo to 1022 of 1036 items.
New API
progress_callback(#2) onbox.solve/boxstacks.solve: called on every improvement with an immutableProgressEvent(time, items, bins, profit, cost, upstream's label); returningFalsestops the solve (result.run.stop_reason == 'callback'). Exceptions raised in the callback propagate unchanged.stop_when_unimproved_for/stop_when_unimproved_after(#3): end an anytime solve once no improvement has arrived for the given number of seconds, optionally not before a given time;result.run.stop_reason == 'unimproved'.recommend_time_budget(instance, solver, alpha=None, speed=1.0)(#4) returns aTimeBudget— atime_limitthat is a loose upper bound plus matching stall-stop knobs — from a model fitted on 3158 recorded anytime curves, one interpretable formula per upstream algorithm path (algorithm_pathreplicates upstream's automatic selection).alphaweighs quality against waiting (4 balanced, 8 thorough; default 4 forbox, 8 forboxstacks),speedrescales for the machine. Also exported:DEFAULT_ALPHA,instance_features,count_stacks. The campaign, its figures and a replay of stopping policies live inexperiments/time_budget/; the docs gain Explanations / How the time budget is estimated and a how-to section.
Compatibility
- No breaking change: calls without the new keyword arguments behave as in 0.0.2, apart from the upstream anytime improvement above.
Wheels: CPython 3.7 to 3.14 on Linux x86_64 / aarch64, Windows AMD64 / ARM64, macOS arm64 / x86_64, built with PACKINGSOLVER_USE_HIGHS=ON, as before.
v0.0.2
Upstream moved to PackingSolver 3f4faae1
This release only moves the vendored PackingSolver from a7e53303 to 3f4faae1; the Python API is unchanged.
boxstacksno longer returns an empty solution under a time limit. Upstream fontanf/packingsolver#571 (fixes #570) replaced theboxtree search that computed the bound before the primal algorithms with closed-form volume bounds, a one-dimensional relaxation and dual feasible functions. Before, on knapsack, bin packing and variable-sized bin packing instances with several item types and more items than fit, that search consumed the wholetime_limitandboxstacks.solvecame back with no placements.- Instance reduction in
boxandboxstacks(upstream24decc4c): negative-profit item types are trimmed under knapsack and identical item types are merged; both happen insideoptimize()and results are mapped back to the original item types. - Multi-bin solutions no longer read past unsized weight vectors. Upstream fontanf/packingsolver#576 (fixes #575): with instance reduction on, every bin packing / variable-sized bin packing solve using two or more bins rebuilt its solution through a path that indexed the still-empty per-group weight vectors of later bins, an access violation with MSVC. This is why 0.0.2 was not published from
24decc4c: its Windows test suite crashed on exactly that case. test/test_upstream_cases.pyreplays the three upstream reproducer instances of #570 with the same 3 s limit, and the postal-carton instance of #575 without one.
Wheels: CPython 3.7 to 3.14 on Linux x86_64 / aarch64, Windows AMD64 / ARM64, macOS arm64 / x86_64, built with PACKINGSOLVER_USE_HIGHS=ON, as before.
v0.0.1
First release of packingsolver3d: Pythonic, in-process bindings for the two three-dimensional solvers of PackingSolver, box and boxstacks. The upstream C++ (commit a7e53303) is compiled together with a pybind11 bridge into one extension module; nothing runs in a subprocess and no C++ object ever reaches Python.
What it does
packingsolver3d.box-- 3D bin packing, knapsack, variable-sized bin packing and open-dimension objectives over rectangular boxes: several bin types with copies and costs, item types with copies, profits, weights and any subset of the six rotations, bin weight capacity, and every upstream algorithm switch (tree search, sequential single knapsack, sequential value correction, column generation, dichotomic search, dual feasible functions).packingsolver3d.boxstacks-- the truck-loading engine on top of the same model: stacks with stackability ids, nesting height, maximum stackability, maximum weight above, stack density, semi-trailer truck axle limits, floor defects and unloading constraints.- Value in, value out -- frozen dataclasses (
Instance,BinType,ItemType, ...) go in, aResultwithstatus,value,bound, bins, stacks and placements comes out;Result.runrecords the exact upstream options, upstream's log and the wall time. - Honest statuses --
OPTIMALonly when the achieved value meets a bound upstream reported for that objective; a good-looking heuristic packing staysFEASIBLE. - Guarded inputs -- instances that the chosen solver would silently misread are refused with typed errors (
UnsupportedFeatureError,StackSemanticsError,InvalidInstanceError) instead of being solved as a different problem. - Budgets --
time_limitandmemory_limitgo to upstream's own timer and memory check; anytime and deterministic optimisation modes are exposed. - Visualisation --
packingsolver3d.visual.plot_resultdraws any result as an interactive plotly figure (optionalplotextra). - Concurrency -- the GIL is released while upstream runs and its log is collected through a per-call stream, so several threads may solve at once.
Benchmarks
The documentation carries a reproducible capability study on three public instance families (Egeblad-Pisinger 3D knapsack, Martello-Pisinger-Vigo class 9, Ivancic-Mathur-Mohanty THPACK9; 97 cases) next to py3dbp, jerry800416/3D-bin-packing, gedex/bp3d, the five U-Nesting strategies and two exact reference codes, with every solution re-validated by an independent geometry checker: https://packingsolver3d.readthedocs.io/en/latest/benchmarks/index.html
Wheels
CPython 3.7--3.14 on Linux x86_64 and Windows AMD64, 3.8--3.14 on Linux aarch64 and macOS (x86_64 and arm64, 11.0+), 3.11--3.14 on Windows ARM64; an sdist for everything else (needs a C++17 compiler, git, network access and CMake 3.28+, which pip installs where a cmake wheel exists). The sdist is installed from source in clean Debian, Alpine and Ubuntu containers on every CI run.
Known upstream behaviours
Documented, not papered over -- see https://packingsolver3d.readthedocs.io/en/latest/explanations/upstream_behaviours/index.html: the LP backend is always HiGHS; copies_min defaults to "all copies"; boxstacks groups stacks by (group_id, stackability_id) without checking footprints and keeps items upright; boxstacks accepts floor defects but places stacks over them at the pinned commit; limits are upstream's own checks and the solver runs in-process; unset profit and cost default to geometry; the default objective produces no solution and is refused; anytime runs are not reproducible run to run.
Install
pip install packingsolver3d # solver only
pip install "packingsolver3d[plot]" # with plotly for the figuresDocumentation: https://packingsolver3d.readthedocs.io/en/latest/ -- Unofficial distribution, not endorsed by the PackingSolver author; upstream is MIT licensed, see NOTICE.md.