A very simple MIP optimization script using Gurobi. This uses the gurobipy library instead of calling the gurobi solver from ortools/pulp. In this way, you can tweak the Gurobi parameters, e.g. method, presolve, etc.
import gurobipy as gp
from gurobipy import GRB
# Parameters for the solver
threads = 2 # Number of threads to use
timeout_secs = 60 # Time limit in seconds
mip_gap = 0.01 # Relative MIP optimality gap (1%)
method = 1 # Optimization method: 0=primal simplex, 1=dual simplex, 2=barrier, etc.
presolve = 2 # Level of presolve: -1=auto, 0=off, 1=conservative, 2=aggressive
# Problem data for a simple knapsack problem
profits = [10, 20, 30] # Profit of items
weights = [1, 2, 3] # Weight of items
capacity = 4 # Maximum weight capacity
n = len(profits) # Number of items
# Create a new model
model = gp.Model("knapsack_mip")
# Create binary decision variables
x = model.addVars(n, vtype=GRB.BINARY, name="x")
# Set objective: maximize total profit
model.setObjective(gp.quicksum(profits[i] * x[i] for i in range(n)), GRB.MAXIMIZE)
# Add constraint: total weight ≤ capacity
model.addConstr(gp.quicksum(weights[i] * x[i] for i in range(n)) <= capacity, name="capacity")
# Set Gurobi parameters
model.setParam('Threads', threads)
model.setParam('TimeLimit', timeout_secs)
model.setParam('MIPGap', mip_gap)
model.setParam('Method', method)
model.setParam('Presolve', presolve)
# Optimize the model
model.optimize()
# Enhanced output: check model status
if model.status == GRB.OPTIMAL:
status_str = "OPTIMAL"
print("===== Optimal solution found =====")
elif model.SolCount > 0:
status_str = "FEASIBLE"
print("===== Feasible solution found =====")
else:
status_str = "NO SOLUTION"
print("===== No feasible solution found =====")
# Display solution if feasible or optimal
if status_str in ["OPTIMAL", "FEASIBLE"]:
print(f"\nStatus: {status_str}")
print(f"Objective value: {model.ObjVal}")
for i in range(n):
print(f"Item {i}: {'Selected' if x[i].X > 0.5 else 'Not selected'}")
else:
print("No solution available to display.")