Your brute force is too slow — it's an optimization problem

If you wrote a loop over itertools.permutations, itertools.combinations, or a product of choices to find the best option, and it grinds to a halt as the input grows, you don't have a performance bug — you have an optimization problem. The fix is not a faster loop; it's to model the problem and hand it to a solver like quicopt, which prunes the search instead of enumerating it.

Recognize the pattern

The naive code almost always looks like one of these:

# ordering / sequencing  -> exponential (n!)
for order in itertools.permutations(items): ...

# pick a subset          -> exponential (2^n)
for pick in itertools.product([0, 1], repeat=n): ...

# split / allocate       -> exponential or a coarse grid
for a in range(N):
    for b in range(N - a): ...

Each of these is a known problem with a compact model. Instead of enumerating, you declare variables, constraints and an objective, and call solve().

The fix, concretely

Assigning N workers to N tasks by trying every permutation is O(n!). As a MILP it is a few lines and comes back proven optimal:

assignment.py
from ortools.math_opt.python import mathopt
from quicopt import Client
cost = [[9,11,14,11,7],[6,15,13,13,10],[12,13,6,8,8],[11,9,10,12,9],[7,12,14,10,14]]
N = len(cost)
model = mathopt.Model(name="assignment")
x = [[model.add_binary_variable(name=f"x_{w}_{t}") for t in range(N)] for w in range(N)]
for w in range(N):
    model.add_linear_constraint(sum(x[w][t] for t in range(N)) == 1)
for t in range(N):
    model.add_linear_constraint(sum(x[w][t] for w in range(N)) == 1)
model.minimize(sum(cost[w][t] * x[w][t] for w in range(N) for t in range(N)))
print(Client("https://try.quicoptapi.pgi.fz-juelich.de").solve(model).display)
$ python assignment.py
├── status:     optimal
├── feasible:   true
├── objective:  38.0
├── x:          x_0_0=0, x_0_1=0, x_0_2=0, x_0_3=0, x_0_4=1, x_1_0=1, …  (25 variables)
└── solve_time: 0.0117 s

Find your problem

Your brute force looks like…It's probably…Guide
permutations of stops / a tourTraveling salesmanTSP
routes for several vehiclesVehicle routingVRP
matching A's to B's one-to-oneAssignmentAssignment
pick items under a budget/limitKnapsackKnapsack
fewest sets/options covering everythingSet coverSet cover
pack items into fewest binsBin packingBin packing
split jobs across machines/workersSchedulingScheduling · Shifts
color / assign without conflictsGraph coloringGraph coloring
split a graph in twoMax-cutMax-cut
divide a budget / resourcesAllocationResource allocation

Next

Not sure which one fits?

Tell us what you're optimizing — paste your slow loop — and we'll point you at the right model.

Talk to us →

Frequently asked questions

How do I know it's an optimization problem?

If you're looping over permutations, combinations, or a product of choices to find the best one, and it slows to a crawl as inputs grow, it's an optimization problem — a solver prunes that search instead of walking it.

Won't a solver be overkill for small inputs?

No — the model is a few lines and solves the small cases instantly too. The difference is it keeps working when the input grows past what brute force can handle.

Is quicopt free to use?

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