• Gurobi Staff

Hi Hans,

There is no way to use piecewise linear objectives with setObjectiveN(). However, you can add piecewise linear constraints (see here), and then set the multiple objectives to be the variables representing the "y" values of those piecewise linear functions.

To clear a piecewise linear objective, you can set the variable's Obj attribute to 0 (x.Obj = 0). Don't forget to update the model afterwards if you want to immediately verify that the piecewise linear objective was removed (e.g., with model.getPWLObj(x)).

I hope this helps. Thanks!

Ok, I've tried to replace setPWLObj with a custom implementation based on the article you suggested. So I'm mapping all the "x"-values to "y"-values with lambda-variables and SOS2-constraints. Then, I'm summing up the "y"-values for the linear objective. This should be mathematically the same thing. Unfortunately, there seems to be a significant performance difference between the two in practice.

I ran the same model twice for 30 minutes, once with the built-in PWL and once with my custom PWL implementation:

- setPWLObj: Objective went down from 3627 to 2921 (difference = 706)

- custom PWL: Objective went down from 3627 to 3623 (difference = 4)

So, I guess Gurobi does something special with PWL internally?!

For my second question: To reset the Objective and remove PWL objectives on all variables I can do the following?

m.setObjective(0, GRB.MINIMIZE)

• Gurobi Staff

Hi Hans,

Are any of the piecewise linear functions convex (assuming you're minimizing)? If so, you can instead use a more efficient linear formulation to model the piecewise linear function. This is done by adding constraints that y lies in each of the n-1 halfspaces that together define the epigraph of the piecewise linear function. In other words, if you have n points defining the convex piecewise linear function, the reformulation includes n-1 inequalities of the form y >= ax + b, where y = ax + b coincides with one of the line segments of the piecewise linear function. Then, you minimize y in the objective function.

For your second question - to reset the model objective and remove all piecewise linear functions from the variables, you can do the following:

# Remove PWL objectives from variablesfor v in m.getVars():    if len(m.getPWLObj(v)) > 0:        v.Obj = 0# Reset model objectivem.setObjective(0, GRB.MINIMIZE)

Thanks!

Eli

Yes, I'm minimizing and they are always convex! I implemented this and it performs great, even a bit better than setPWLObj. I ran model again for 30 minutes and the objective went down from 3897 to 3125 (difference: 772). It's a bit strange that there seems to be an offset now but that's probably a bug in my implementation. Nevertheless, a big thanks for that! When thinking about the Simplex, it's also clear to me why this is the better implementation.

Resetting the PWLs with your code works great as well.

I found my mistake: My piecewise-linear function was actually not convex (although just very slightly). Because of that the objective values were a bit off.

That means that setPWLObj() can work with non-convex functions but is still as fast as the implementation based on the epigraph (which only works for convex functions).