Search code examples
pythonoptimizationgurobiobjective-function

Calculating the value of the objective function for a manual input in Gurobi


I have a complex model and I want to calculate the objective function value for different options (not just the optimal solution).

I created the toy example below:

import gurobipy as gp
from gurobipy import GRB
import numpy as np

m = gp.Model()
X = {}
for i in range(5):
    X[i] = m.addVar(vtype= GRB.INTEGER, name=f"x[{i}]")
obj_func = 0
for i in range(5):
    np.random.seed(i)
    obj_func += np.random.rand() * X[i]
m.setObjective(obj_func, GRB.MINIMIZE)
m.addConstr(2 * X[1] + 5 * X[3] <= 10, name = 'const1')
m.addConstr(X[0] + 3 * X[4] >= 4, name = 'const2')
m.addConstr(3 * X[1] - X[4] <= 3, name = 'const3')
m.optimize()

for x_index, x in X.items():
    if round(x.X)>0:
        print(x_index, x.X)
# 0 1.0
# 4 1.0

How can I can calculate the objective function for the manual input of X = [0,1,1,0,0] or X=[1,0,0,0,1]. I want the output return the objective function value if this input is a feasible solution, otherwise a warning. I can hard-code the problem, but I would rather to extract the objective coefficients directly form m (model) and multiply them with the new X input.


Solution

  • A pretty simple idea: You could fix all the variables in the model by setting the lower and upper bounds to your given inputs and then solve the model. Then, the model.objVal attribute contains the objective value for your given input solution. A straightforward implementation looks like this:

    import numpy as np
    
    given_sols = np.array([[0, 1, 1, 0, 0], [1, 0, 0, 0, 1]])
    
    # Evaluate the objective for multiple given solutions
    def get_obj_vals(model, given_sols):
        obj_vals = np.nan * np.zeros(given_sols.shape[0])
        # for each given solution..
        for k, x in enumerate(given_sols):
            # reset the model
            model.reset()
            # Fix the lower/upper bounds
            for i, var in enumerate(model.getVars()):
                var.lb = x[i]
                var.ub = x[i]
            # solve the problem
            model.optimize()
            if model.Status == GRB.Status.OPTIMAL:
                obj_vals[k] = model.objVal
        return obj_vals
    

    Here, nan in obj_vals[i] means that given_sols[i] is not feasible.