Expressions
JuMP has three types of expressions: affine, quadratic, and nonlinear. These expressions can be inserted into constraints or into the objective. This is particularly useful if an expression is used in multiple places in the model.
Affine expressions
There are four ways of constructing an affine expression in JuMP: with the @expression
macro, with operator overloading, with the AffExpr
constructor, and with add_to_expression!
.
Macros
The recommended way to create an affine expression is via the @expression
macro.
model = Model()
@variable(model, x)
@variable(model, y)
ex = @expression(model, 2x + y - 1)
# output
2 x + y - 1
This expression can be used in the objective or added to a constraint. For example:
@objective(model, Min, 2 * ex - 1)
objective_function(model)
# output
4 x + 2 y - 3
Just like variables and constraints, named expressions can also be created. For example
model = Model()
@variable(model, x[i = 1:3])
@expression(model, expr[i = 1:3], i * sum(x[j] for j in i:3))
expr
# output
3-element Array{GenericAffExpr{Float64,VariableRef},1}:
x[1] + x[2] + x[3]
2 x[2] + 2 x[3]
3 x[3]
Operator overloading
Expressions can also be created without macros. However, note that in some cases, this can be much slower that constructing an expression using macros.
model = Model()
@variable(model, x)
@variable(model, y)
ex = 2x + y - 1
# output
2 x + y - 1
Constructors
A third way to create an affine expression is by the AffExpr
constructor. The first argument is the constant term, and the remaining arguments are variable-coefficient pairs.
model = Model()
@variable(model, x)
@variable(model, y)
ex = AffExpr(-1.0, x => 2.0, y => 1.0)
# output
2 x + y - 1
add_to_expression!
The fourth way to create an affine expression is by using add_to_expression!
. Compared to the operator overloading method, this approach is faster because it avoids constructing temporary objects. The @expression
macro uses add_to_expression!
behind-the-scenes.
model = Model()
@variable(model, x)
@variable(model, y)
ex = AffExpr(-1.0)
add_to_expression!(ex, 2.0, x)
add_to_expression!(ex, 1.0, y)
# output
2 x + y - 1
Removing zero terms
Use drop_zeros!
to remove terms from an affine expression with a 0
coefficient.
julia> model = Model();
julia> @variable(model, x)
x
julia> @expression(model, ex, x + 1 - x)
0 x + 1
julia> drop_zeros!(ex)
julia> ex
1
Quadratic expressions
Like affine expressions, there are four ways of constructing a quadratic expression in JuMP: macros, operator overloading, constructors, and add_to_expression!
.
Macros
The @expression
macro can be used to create quadratic expressions by including quadratic terms.
model = Model()
@variable(model, x)
@variable(model, y)
ex = @expression(model, x^2 + 2 * x * y + y^2 + x + y - 1)
# output
x² + 2 y*x + y² + x + y - 1
Operator overloading
Operator overloading can also be used to create quadratic expressions. The same performance warning (discussed in the affine expression section) applies.
model = Model()
@variable(model, x)
@variable(model, y)
ex = x^2 + 2 * x * y + y^2 + x + y - 1
# output
x² + 2 x*y + y² + x + y - 1
Constructors
Quadratic expressions can also be created using the QuadExpr
constructor. The first argument is an affine expression, and the remaining arguments are pairs, where the first term is a JuMP.UnorderedPair
and the second term is the coefficient.
model = Model()
@variable(model, x)
@variable(model, y)
aff_expr = AffExpr(-1.0, x => 1.0, y => 1.0)
quad_expr = QuadExpr(aff_expr, UnorderedPair(x, x) => 1.0,
UnorderedPair(x, y) => 2.0, UnorderedPair(y, y) => 1.0)
# output
x² + 2 x*y + y² + x + y - 1
add_to_expression!
Finally, add_to_expression!
can also be used to add quadratic terms.
model = Model()
@variable(model, x)
@variable(model, y)
ex = QuadExpr(x + y - 1.0)
add_to_expression!(ex, 1.0, x, x)
add_to_expression!(ex, 2.0, x, y)
add_to_expression!(ex, 1.0, y, y)
# output
x² + 2 x*y + y² + x + y - 1
Removing zero terms
Use drop_zeros!
to remove terms from a quadratic expression with a 0
coefficient.
julia> model = Model();
julia> @variable(model, x)
x
julia> @expression(model, ex, x^2 + x + 1 - x^2)
0 x² + x + 1
julia> drop_zeros!(ex)
julia> ex
x + 1
Nonlinear expressions
Nonlinear expressions can be constructed only using the @NLexpression
macro and can be used only in @NLobjective
, @NLconstraint
, and other @NLexpression
s. Moreover, quadratic and affine expressions cannot be used in the nonlinear macros. For more details, see the Nonlinear Modeling section.
Reference
JuMP.@expression
— Macro.@expression(args...)
Efficiently builds a linear or quadratic expression but does not add to model immediately. Instead, returns the expression which can then be inserted in other constraints. For example:
@expression(m, shared, sum(i*x[i] for i=1:5))
@constraint(m, shared + y >= 5)
@constraint(m, shared + z <= 10)
The ref
accepts index sets in the same way as @variable
, and those indices can be used in the construction of the expressions:
@expression(m, expr[i=1:3], i*sum(x[j] for j=1:3))
Anonymous syntax is also supported:
expr = @expression(m, [i=1:3], i*sum(x[j] for j=1:3))
JuMP.add_to_expression!
— Function.add_to_expression!(expression, terms...)
Updates expression
in place to expression + (*)(terms...)
. This is typically much more efficient than expression += (*)(terms...)
. For example, add_to_expression!(expression, a, b)
produces the same result as expression += a*b
, and add_to_expression!(expression, a)
produces the same result as expression += a
.
Only a few methods are defined, mostly for internal use, and only for the cases when (1) they can be implemented efficiently and (2) expression
is capable of storing the result. For example, add_to_expression!(::AffExpr, ::VariableRef, ::VariableRef)
is not defined because a GenericAffExpr
cannot store the product of two variables.
JuMP.drop_zeros!
— Function.drop_zeros!(expr::GenericAffExpr)
Remove terms in the affine expression with 0
coefficients.
drop_zeros!(expr::GenericQuadExpr)
Remove terms in the quadratic expression with 0
coefficients.