pythongurobi

How to get the result of the objective function while using a slack variable?


I have a simple Python code using Gurobi. I have added a slack variable to force model feasibility. I need to know how to get the real minimum value in my objective function.

import gurobipy as gp
from gurobipy import GRB

# Create the model
model = gp.Model("quadratic_optimization_with_slack")

# Variables
x = model.addVar(name="x", lb=0)  # x >= 0
y = model.addVar(name="y", lb=0)  # y >= 0
slack = model.addVar(name="slack", lb=0)  # Slack variable for relaxation. If slack = 0 --> Model is infeasible

# Objective: Minimize 2x^2 + y
model.setObjective(2 * x**2 + y, GRB.MINIMIZE)

# Constraints
model.addConstr(x - 5 + slack == 0, name="constraint_1")  # (slack allows relaxation) <-- Condition to be relaxed
model.addConstr(x + y == 4, name="constraint_2")

# Add slack penalty in the objective to ensure the slack value is minimum.
# The problem is that the result is not anymore the model.ObjVal, but the penalty*slack
penalty_weight = 0.00010  # Penalty for slack usage
model.setObjective(model.getObjective() + (penalty_weight * slack))

# Optimize the model
model.optimize()

According to the values:

x = 4
y = 0
slack = 1
model.ObjVal = 0.0001  # (penalty_weight * slack)

Obviously, 0.0001 is not the minimum value that my objective function 2x^2 + y can get. With this slack, it should be 2 * 4^2 + 0 = 32.

How can I get the real minimum value of my objective function?


Solution

  • First let's fix an error in the code. This:

    model.getObjective() only works properly after model.update() or model.write() or model.optimize(). In this code it will just return 0.

    Using the getObjective() method is not recommended. Rather do something like this:

    orig_obj = 2 * x**2 + y
    penalty_weight = 100  # rather than 0.0001, to truly minimize value of slack
    model.setObjective(orig_obj + (penalty_weight * slack), GRB.MINIMIZE)
    

    After optimization you can use QuadExpr.getValue(), i.e. print(orig_obj.getValue())

    Source: https://support.gurobi.com/hc/en-us/community/posts/30217975677713-How-to-get-the-result-of-the-objective-function-while-using-a-slack-variable