Solve the bin packing problem in Python

Bin packing — fit a set of items into as few fixed-capacity bins as possible — is everywhere: filling trucks, VMs onto servers, ads into breaks, files onto disks. The usual answer is a greedy first-fit-decreasing pass, which is quick but not optimal. With quicopt you get the provably fewest bins in a few lines of Python.

The naive approach

First-fit-decreasing sorts items large-to-small and drops each into the first bin that fits. It is a good heuristic, but it can waste a bin and never tells you whether fewer was possible. Trying every assignment is exponential. Model it instead.

Model it as a MILP

y[b] marks bin b as used; x[i][b] puts item i in bin b. Every item goes in exactly one bin, each bin respects its capacity, and we minimize bins used:

bin_packing.py
from ortools.math_opt.python import mathopt
from quicopt import Client
size = [4, 8, 5, 7, 3, 6]
C = 10
n = len(size)
B = n  # at most n bins
model = mathopt.Model(name="bin_packing")
y = [model.add_binary_variable(name=f"y{b}") for b in range(B)]
x = [[model.add_binary_variable(name=f"x_{i}_{b}") for b in range(B)] for i in range(n)]
for i in range(n):
    model.add_linear_constraint(sum(x[i][b] for b in range(B)) == 1)
for b in range(B):
    model.add_linear_constraint(sum(size[i] * x[i][b] for i in range(n)) <= C * y[b])
model.minimize(sum(y))
print(Client("https://try.quicoptapi.pgi.fz-juelich.de").solve(model).display)
$ python bin_packing.py
├── status:     optimal
├── feasible:   true
├── objective:  4.0
├── x:          x_0_0=0, x_0_1=0, x_0_2=0, x_0_3=0, x_0_4=0, x_0_5=1, …  (42 variables)
└── solve_time: 0.0185 s

What you get

status: optimal means 4 bins is proven minimal for these six items — no packing uses fewer. The total size is 33 and each bin holds 10, so three bins (capacity 30) can't work; the solver proves four is the floor, which a greedy pass can only guess at.

The same model extends to larger instances and takes side rules as plain linear constraints — you change the data, not the method. (Bin packing is NP-hard, and this compact formulation is bin-symmetric, so it is best on small-to-medium instances; very large packings call for symmetry-breaking or specialized methods.)

Next

Reference: M. R. Garey and D. S. Johnson, Computers and Intractability: A Guide to the Theory of NP-Completeness, W. H. Freeman, 1979.

More items — or a different problem?

Tell us what you're optimizing. We'll help you model it and point you at the right approach.

Talk to us →

Frequently asked questions

Isn't first-fit-decreasing (FFD) good enough?

FFD is fast but only a heuristic — it can use more bins than necessary and never proves optimality. The MILP returns the provably fewest bins.

Can I add per-bin cost or item-compatibility rules?

Yes — bin costs, forbidden pairs, or category limits are extra linear constraints on the same model.

Is quicopt free to use?

Yes — pip install quicopt and your first call sets up a free key, no license.