FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserNext example

Linearizations and approximations via SOS and piecewise linear (pwl) expressions

Description
Various examples of using SOS (Special Ordered Sets of type 1 or 2) to represent nonlinear functions in MIP models implemented with the Xpress Solver Python API.
  • approximating a continuous nonlinear function in a single variable via SOS-1 (soslin.*);
  • approximating a continuous nonlinear function in two variables via SOS-2 (sosquad.*);
Further explanation of this example: Whitepaper 'MIP formulations and linearizations', Section Non-linear functions

pwlinsospy.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
soslin.py[download]
sosquad.py[download]





soslin.py

"""
   Xpress Python Example Problems
   ======================

   file soslin.py
    ```````````````
   Approximation of a nonlinear function by a SOS-2.
   - Example discussed in mipformref whitepaper -

   (c) 2024 Fair Isaac Corporation
       author: B. Vieira, Sep. 2024
"""

import xpress as xp
from xpress.enums import SolStatus

I = range(4)
R = [1, 2.5, 4.5, 6.5]
FR = [1.5, 6, 3.5, 2.5]

p = xp.problem()

# Create the decision variables
x = p.addVariable(lb=R[0],ub=R[3],name="x") # x-values interval defined by the breakpoints
y = p.addVariable(name="y")
w = [p.addVariable(name="w{0}".format(i)) for i in I]

# Define the SOS-2 with weights R
p.addSOS(w, R, name="Defx", type=2)

# Weights must sum up to 1
p.addConstraint(xp.Sum(w[i] for i in I) == 1.0)

# The variable and the corresponding function value we want to approximate
p.addConstraint(x == xp.Sum(R[i]*w[i] for i in I))
p.addConstraint(y == xp.Sum(FR[i]*w[i] for i in I))

# Set a lower bound on x to make the problem more interesting
x.lb = 2

# Set objective
p.setObjective(y)

# Write out the model in case we want to look at it
p.write("soslin.lp")

# Solve the problem
p.optimize()

match p.attributes.solstatus:
    case SolStatus.FEASIBLE | SolStatus.OPTIMAL:
        print("MIP solution: ", p.attributes.objval)
    case SolStatus.INFEASIBLE:
        print("Problem is infeasible")
    case SolStatus.UNBOUNDED:
        print("LP unbounded")
    case SolStatus.NOTFOUND:
        print("Solution not found")

print(x.name,": ",p.getSolution(x))
Back to examples browserNext example