Skip to content

Reference

Solver

A multi-start first-fit-decreasing search over extreme points, scored by the objective you pick.

Objectives

ObjectiveThen ranks byTies fall through to
MIN_CARTONSFewest physical cartons.Utilization, then cost.
MIN_COSTCarton cost plus a freight proxy on billable weight.Carton count, then utilization.
MIN_DIM_WEIGHTTotal billable weight — the greater of gross and dimensional.Carton count, then utilization, then cost.
BEST_FITHighest aggregate volume utilization.Carton count, then cost.

Units placed outranks all four: a cheaper plan that leaves goods on the bench is not a plan. BEST_FIT uses aggregate utilization — goods volume over total cavity — because a mean can be raised by adding another small, full box.

Orderingsvolume, longest edge,footprint, height,weight, groupCartonsactive sizes thatcould hold the order,stock respectedPlaceevery allowed poseat every extreme point;reject on bounds, overlap,weight cap, supportscore, then re-generateScorerank whole packingsby the objective,keep the bestMulti-start first-fit-decreasing. Ties keep the incumbent, so the earlier ordering wins.Every step is a pure function of the request — no clock, no randomness, no unordered iteration.
Orderings × cartons × poses × positions, pruned hard at every step.
placednext candidate positionsDominated points are pruned before the next placement.
Each placement creates new extreme points; dominated ones are pruned.
StepRule
Order6 orderings by default, 12 at most. Fragile items always sort last.
PositionEvery live extreme point, in every permitted pose.
ScoreLowest y, then lowest z, then lowest x, then greatest contact area.
RepeatRegenerate extreme points, prune dominated ones, place the next unit.
KeepThe best whole packing under the objective. Ties keep the incumbent.
The 12 orderings, in the sequence they are tried
  1. 1volume-descLargest volume first
  2. 2longest-edge-descLongest edge first
  3. 3footprint-descLargest footprint first
  4. 4height-descTallest first
  5. 5weight-descHeaviest first
  6. 6group-clusteredGrouped sets first
  7. 7surface-area-descLargest surface area first
  8. 8density-descDensest first
  9. 9shortest-edge-descThickest first
  10. 10footprint-then-heightLayer building
  11. 11weight-then-volumeHeaviest, then largest
  12. 12volume-ascSmallest volume first

The first 6 run by default. The rest earn their keep on awkward mixes and are reached only when a deeper search is asked for.

Constraints

supported — acceptedcontact 100%contact 20% — rejectedsupportThreshold 0.7
Default support threshold 0.7.
A placement is rejected whenBecause
It leaves the cavityPadding is already subtracted from every face.
It overlaps a placed boxAxis-aligned intersection test.
Support is too lowFloor contact, or enough top-face area under it.
A box below cannot bear itNon-stackable, fragile, or over maxStackWeight anywhere down the stack.
The carton is over its capContents mass past maxWeight.
No pose is allowedOrientation lock rules out every fitting rotation.

Anything that cannot be placed anywhere comes back in result.unpacked with a reason, and result.success turns false. The HTTP status stays 200 — the run happened.

Options and plan ceilings

options, on POST /api/v1/pack
NameTypeReqDescription
allowMultipleCartonsbooleannoSplit the order across cartons. Default true.
maxCartonsinteger 1–200noCartons for one shipment. Engine default 20; your plan caps it.
respectStockOnHandbooleannoHonor quantity on hand. Default true.
supportThresholdnumber 0–1noBase area that must be supported. Default 0.7; 0 disables.
keepGroupsTogetherbooleannoKeep same-groupKey lines in one carton. Default true.
strategiesinteger 1–12noOrderings to try. More orderings, better packs, more compute.
dimWeightDivisornumber 1–100000noOverrides your carrier divisor for this run.
CeilingFree / Pro
Cartons per shipment3 / 50
Search strategies3 / 10

A value above your ceiling is clamped, not rejected — the run succeeds with the plan’s limit applied.

Determinism

GuaranteeHow
Same request, same planByte-identical, forever, on any machine.
No randomnessNo Math.random anywhere in the engine.
No clock in scoringThe time budget bounds the search, not the ranking.
Stable iterationCartons sorted by SKU; no unordered map traversal.
Stable tiesAn equal score keeps the incumbent, so the earlier ordering wins.
Stored verbatimA job keeps its request and result, so /jobs/:id replays exactly what shipped.

One field varies between runs: summary.computeMs. Exclude it when you diff two results.

Performance

DriverEffect
Units in the orderRoughly quadratic — every unit is tried at every live point.
Candidate cartonsLinear. Restrict with cartonIds when a bench stocks a subset.
StrategiesLinear. Each is a full re-pack under a different ordering.
Orientation locksFewer poses is faster; identical poses are deduplicated.
Flexible cartonsNear free — volume and footprint, not 3D placement.
Time budget5 seconds server-side. On expiry the best plan found so far is returned, with a warning.
Reported on every run
"summary": { "strategy": "volume-desc", "candidatesEvaluated": 84, "computeMs": 37 }
Solver · Carton Pack Pro