Quadratic Expressions
Quadratic expressions work as you'd expect. Simply multiply two linear expression together (or square an expression with **2
) and you'll get a quadratic. The quadratic can then be used in constraints or the objective.
Example
Maximize area of box
Here's a short example that shows that a square maximizes the area of any box with a fixed perimeter.
import pyoframe as pf
model = pf.Model(sense="max")
model.w = pf.Variable(lb=0)
model.h = pf.Variable(lb=0)
model.limit_perimter = 2 * (model.w + model.h) <= 20
model.objective = model.w * model.h
model.solve()
print(f"It's a square: {model.w.solution==model.h.solution}")
print(f"With area: {model.objective.evaluate()}")
# Outputs:
# It's a square: True
# With area: 25.0
Facility Location Problem
See examples/facility_location.
Note for Pyoframe developers: Internal Representation of Quadratics
Internally, Pyoframe's Expression
object is used for both linear and quadratic expressions. When the dataframe within an Expression
object (i.e. Expression.data
) contains an additional column (named __quadratic_variable_id
) we know that the expression is a quadratic.
This extra column stores the ID of the second variable in quadratic terms. For terms with only one variable, this column contains ID 0
(a reserved variable ID which can thought of as meaning 'no variable'). The variables in a quadratic are rearranged such that the ID in the __variable_id
column is always greater or equal than the variable ID in the __quadratic_variable_id
(recall: ab=ba). This rearranging not only ensures that ab+ba=2a*b but also generates a useful property: If the variable ID in the first column (__variable_id
) is 0
we know the variable ID in the second must also be 0
and therefore the term must be a constant.
The additional quadratic variable ID column is automatically dropped if through arithmetic the quadratic terms cancel out.