Skip to content

Commit 833ec9c

Browse files
Replace mip package with pulp
Signed-off-by: Keval Morabia <28916987+kevalmorabia97@users.noreply.github.com>
1 parent e4b054b commit 833ec9c

2 files changed

Lines changed: 19 additions & 22 deletions

File tree

modelopt/torch/puzzletron/mip/mip_with_multi_layer_replacements.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from random import random
2525
from typing import Any, TypeAlias
2626

27-
from mip import BINARY, Model, maximize, minimize, xsum
27+
import pulp
2828

2929
from .utils import consecutive_ngrams, get_nested_key, sort_replacements
3030

@@ -55,16 +55,15 @@ def run_mip(
5555
)
5656
print("\n\n\n")
5757

58-
if not replacements:
59-
return [], 0.0, {}
60-
61-
mip_model = Model()
58+
# Create pulp problem with appropriate sense (minimize or maximize)
59+
sense = pulp.LpMaximize if bigger_is_better else pulp.LpMinimize
60+
problem = pulp.LpProblem(name="multi_layer_replacement", sense=sense)
6261

6362
objective_vars = []
6463
constraint_vars = {constraint_key: [] for constraint_key in constraints}
6564
choice_indicators_by_layer = defaultdict(list)
66-
for replacement_id, replacement in replacements.items():
67-
is_chosen = mip_model.add_var(var_type=BINARY)
65+
for i, (replacement_id, replacement) in enumerate(replacements.items()):
66+
is_chosen = pulp.LpVariable(f"choice_{i}", cat=pulp.LpBinary)
6867
replacement["is_chosen"] = is_chosen
6968

7069
for parent_layer_idx in replacement["parent_layer_indices"]:
@@ -79,30 +78,29 @@ def run_mip(
7978

8079
# MIP constraints: each parent layer must come from exactly one chosen replacement
8180
for parent_layer_idx, curr_choice_indicators in choice_indicators_by_layer.items():
82-
mip_model += xsum(curr_choice_indicators) == 1
81+
problem += pulp.lpSum(curr_choice_indicators) == 1
8382

8483
# MIP constraints: the sum of chosen replacement costs must be lower than the max cost
8584
for constraint_key, max_cost in constraints.items():
8685
min_cost = None
8786
if isinstance(max_cost, Iterable):
8887
min_cost, max_cost = max_cost
8988

90-
if max_cost is not None:
91-
mip_model += xsum(constraint_vars[constraint_key]) <= max_cost
92-
if min_cost is not None:
93-
mip_model += xsum(constraint_vars[constraint_key]) >= min_cost
89+
# PuLP is stricter than mip - it doesn't allow NaN/inf in constraints
90+
if max_cost is not None and math.isfinite(max_cost):
91+
problem += pulp.lpSum(constraint_vars[constraint_key]) <= max_cost
92+
if min_cost is not None and math.isfinite(min_cost):
93+
problem += pulp.lpSum(constraint_vars[constraint_key]) >= min_cost
9494

9595
# MIP objective
96-
mip_model.objective = (
97-
maximize(xsum(objective_vars)) if bigger_is_better else minimize(xsum(objective_vars))
98-
)
99-
100-
if max_seconds_per_solution is not None:
101-
mip_model.max_seconds = max_seconds_per_solution
96+
problem += (pulp.lpSum(objective_vars), "objective")
10297

103-
mip_model.optimize()
98+
# Configure and run solver
99+
solver = pulp.PULP_CBC_CMD(msg=True, timeLimit=max_seconds_per_solution)
100+
problem.solve(solver)
104101

105-
if is_chosen.x is None:
102+
# Check if solution is feasible
103+
if problem.status != pulp.LpStatusOptimal:
106104
return []
107105
# raise InfeasibleError()
108106

@@ -112,7 +110,7 @@ def run_mip(
112110
chosen_replacements: ChosenReplacements = []
113111
chosen_layers = []
114112
for replacement_id, replacement in replacements.items():
115-
is_chosen = replacement["is_chosen"].x >= 0.99
113+
is_chosen = replacement["is_chosen"].varValue >= 0.99
116114
if is_chosen:
117115
assert replacement not in chosen_replacements
118116
chosen_replacements.append(replacement)

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ puzzletron = [ # Dependedencies for modelopt.torch.puzzletron subpackage
9191
"hydra-core==1.3.2",
9292
"immutabledict",
9393
"lru-dict",
94-
"mip",
9594
"pandas",
9695
"typeguard",
9796
]

0 commit comments

Comments
 (0)