Extensions
More information can be found in the Extensions section of the manual.
Define a new set
JuMP.AbstractVectorSet
— TypeAbstractVectorSet
An abstract type for defining new sets in JuMP.
Implement moi_set(::AbstractVectorSet, dim::Int)
to convert the type into an MOI set.
See also: moi_set
.
JuMP.AbstractScalarSet
— TypeAbstractScalarSet
An abstract type for defining new scalar sets in JuMP.
Implement moi_set(::AbstractScalarSet)
to convert the type into an MOI set.
See also: moi_set
.
Extend @variable
JuMP.ScalarVariable
— TypeScalarVariable{S,T,U,V} <: AbstractVariable
A struct used when adding variables.
See also: add_variable
.
JuMP.VariableInfo
— TypeVariableInfo{S,T,U,V}
A struct by JuMP internally when creating variables. This may also be used by JuMP extensions to create new types of variables.
See also: ScalarVariable
.
JuMP.add_variable
— Functionadd_variable(m::Model, v::AbstractVariable, name::String="")
Add a variable v
to Model m
and sets its name.
JuMP.build_variable
— Functionbuild_variable(
_error::Function,
info::VariableInfo,
args...;
kwargs...,
)
Return a new AbstractVariable
object.
This method should only be implemented by developers creating JuMP extensions. It should never be called by users of JuMP.
Arguments
_error
: a function to call instead oferror
._error
annotates the error message with additional information for the user.info
: an instance ofVariableInfo
. This has a variety of fields relating to the variable such asinfo.lower_bound
andinfo.binary
.args
: optional additional positional arguments for extending the@variable
macro.kwargs
: optional keyword arguments for extending the@variable
macro.
See also: @variable
Extensions should define a method with ONE positional argument to dispatch the call to a different method. Creating an extension that relies on multiple positional arguments leads to MethodError
s if the user passes the arguments in the wrong order.
Example
@variable(model, x, Foo)
will call
build_variable(_error::Function, info::VariableInfo, ::Type{Foo})
Passing special-case positional arguments such as Bin
, Int
, and PSD
is okay, along with keyword arguments:
@variable(model, x, Int, Foo(), mykwarg = true)
# or
@variable(model, x, Foo(), Int, mykwarg = true)
will call
build_variable(_error::Function, info::VariableInfo, ::Foo; mykwarg)
and info.integer
will be true.
Note that the order of the positional arguments does not matter.
build_variable(_error::Function, variables, ::SymmetricMatrixSpace)
Return a VariablesConstrainedOnCreation
of shape SymmetricMatrixShape
creating variables in MOI.Reals
, i.e. "free" variables unless they are constrained after their creation.
This function is used by the @variable
macro as follows:
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2], Symmetric)
2×2 LinearAlgebra.Symmetric{VariableRef, Matrix{VariableRef}}:
Q[1,1] Q[1,2]
Q[1,2] Q[2,2]
build_variable(_error::Function, variables, ::SkewSymmetricMatrixSpace)
Return a VariablesConstrainedOnCreation
of shape SkewSymmetricMatrixShape
creating variables in MOI.Reals
, i.e. "free" variables unless they are constrained after their creation.
This function is used by the @variable
macro as follows:
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2] in SkewSymmetricMatrixSpace())
2×2 Matrix{AffExpr}:
0 Q[1,2]
-Q[1,2] 0
build_variable(_error::Function, variables, ::HermitianMatrixSpace)
Return a VariablesConstrainedOnCreation
of shape HermitianMatrixShape
creating variables in MOI.Reals
, i.e. "free" variables unless they are constrained after their creation.
This function is used by the @variable
macro as follows:
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2] in HermitianMatrixSpace())
2×2 LinearAlgebra.Hermitian{GenericAffExpr{ComplexF64, VariableRef}, Matrix{GenericAffExpr{ComplexF64, VariableRef}}}:
real(Q[1,1]) real(Q[1,2]) + (0.0 + 1.0im) imag(Q[1,2])
real(Q[1,2]) + (0.0 - 1.0im) imag(Q[1,2]) real(Q[2,2])
build_variable(_error::Function, variables, ::PSDCone)
Return a VariablesConstrainedOnCreation
of shape SymmetricMatrixShape
constraining the variables to be positive semidefinite.
This function is used by the @variable
macro as follows:
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2], PSD)
2×2 LinearAlgebra.Symmetric{VariableRef, Matrix{VariableRef}}:
Q[1,1] Q[1,2]
Q[1,2] Q[2,2]
Extend @constraint
JuMP.build_constraint
— Functionbuild_constraint(
_error::Function,
Q::LinearAlgebra.Symmetric{V, M},
::PSDCone,
) where {V<:AbstractJuMPScalar,M<:AbstractMatrix{V}}
Return a VectorConstraint
of shape SymmetricMatrixShape
constraining the matrix Q
to be positive semidefinite.
This function is used by the @constraint
macros as follows:
julia> import LinearAlgebra
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2]);
julia> @constraint(model, LinearAlgebra.Symmetric(Q) in PSDCone())
[Q[1,1] Q[1,2];
Q[1,2] Q[2,2]] ∈ PSDCone()
The form above is usually used when the entries of Q
are affine or quadratic expressions, but it can also be used when the entries are variables to get the reference of the semidefinite constraint, e.g.,
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2], Symmetric)
2×2 LinearAlgebra.Symmetric{VariableRef, Matrix{VariableRef}}:
Q[1,1] Q[1,2]
Q[1,2] Q[2,2]
julia> @constraint(model, Q in PSDCone())
[Q[1,1] Q[1,2];
Q[1,2] Q[2,2]] ∈ PSDCone()
build_constraint(
_error::Function,
Q::AbstractMatrix{<:AbstractJuMPScalar},
::PSDCone,
)
Return a VectorConstraint
of shape SquareMatrixShape
constraining the matrix Q
to be symmetric and positive semidefinite.
This function is used by the @constraint
macro as follows:
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2]);
julia> @constraint(model, Q in PSDCone())
[Q[1,1] Q[1,2];
Q[2,1] Q[2,2]] ∈ PSDCone()
build_constraint(
_error::Function,
Q::LinearAlgebra.Hermitian{V,M},
::HermitianPSDCone,
) where {V<:AbstractJuMPScalar,M<:AbstractMatrix{V}}
Return a VectorConstraint
of shape HermitianMatrixShape
constraining the matrix Q
to be Hermitian positive semidefinite.
This function is used by the @constraint
macros as follows:
julia> import LinearAlgebra
julia> model = Model();
julia> @variable(model, Q[1:2, 1:2]);
julia> @constraint(model, LinearAlgebra.Hermitian(Q) in HermitianPSDCone())
[Q[1,1] Q[1,2];
Q[1,2] Q[2,2]] ∈ HermitianPSDCone()
build_constraint(
_error::Function,
f::AbstractVector{<:AbstractJuMPScalar},
::Nonnegatives,
extra::Union{MOI.AbstractVectorSet,AbstractVectorSet},
)
A helper method that re-writes
@constraint(model, X >= Y, extra)
into
@constraint(model, X - Y in extra)
build_constraint(
_error::Function,
f::AbstractVector{<:AbstractJuMPScalar},
::Nonpositives,
extra::Union{MOI.AbstractVectorSet,AbstractVectorSet},
)
A helper method that re-writes
@constraint(model, Y <= X, extra)
into
@constraint(model, X - Y in extra)
JuMP.add_constraint
— Functionadd_constraint(model::Model, con::AbstractConstraint, name::String="")
Add a constraint con
to Model model
and sets its name.
JuMP.AbstractShape
— TypeAbstractShape
Abstract vectorizable shape. Given a flat vector form of an object of shape shape
, the original object can be obtained by reshape_vector
.
JuMP.shape
— Functionshape(c::AbstractConstraint)::AbstractShape
Return the shape of the constraint c
.
JuMP.reshape_vector
— Functionreshape_vector(vectorized_form::Vector, shape::AbstractShape)
Return an object in its original shape shape
given its vectorized form vectorized_form
.
Example
Given a SymmetricMatrixShape
of vectorized form [1, 2, 3]
, the following code returns the matrix Symmetric(Matrix[1 2; 2 3])
:
julia> reshape_vector([1, 2, 3], SymmetricMatrixShape(2))
2×2 LinearAlgebra.Symmetric{Int64,Array{Int64,2}}:
1 2
2 3
JuMP.reshape_set
— Functionreshape_set(vectorized_set::MOI.AbstractSet, shape::AbstractShape)
Return a set in its original shape shape
given its vectorized form vectorized_form
.
Example
Given a SymmetricMatrixShape
of vectorized form [1, 2, 3] in MOI.PositiveSemidefinieConeTriangle(2)
, the following code returns the set of the original constraint Symmetric(Matrix[1 2; 2 3]) in PSDCone()
:
julia> reshape_set(MOI.PositiveSemidefiniteConeTriangle(2), SymmetricMatrixShape(2))
PSDCone()
JuMP.dual_shape
— Functiondual_shape(shape::AbstractShape)::AbstractShape
Returns the shape of the dual space of the space of objects of shape shape
. By default, the dual_shape
of a shape is itself. See the examples section below for an example for which this is not the case.
Example
Consider polynomial constraints for which the dual is moment constraints and moment constraints for which the dual is polynomial constraints. Shapes for polynomials can be defined as follows:
struct Polynomial
coefficients::Vector{Float64}
monomials::Vector{Monomial}
end
struct PolynomialShape <: AbstractShape
monomials::Vector{Monomial}
end
JuMP.reshape_vector(x::Vector, shape::PolynomialShape) = Polynomial(x, shape.monomials)
and a shape for moments can be defined as follows:
struct Moments
coefficients::Vector{Float64}
monomials::Vector{Monomial}
end
struct MomentsShape <: AbstractShape
monomials::Vector{Monomial}
end
JuMP.reshape_vector(x::Vector, shape::MomentsShape) = Moments(x, shape.monomials)
Then dual_shape
allows the definition of the shape of the dual of polynomial and moment constraints:
dual_shape(shape::PolynomialShape) = MomentsShape(shape.monomials)
dual_shape(shape::MomentsShape) = PolynomialShape(shape.monomials)
JuMP.ScalarShape
— TypeScalarShape
Shape of scalar constraints.
JuMP.VectorShape
— TypeVectorShape
Vector for which the vectorized form corresponds exactly to the vector given.
JuMP.SquareMatrixShape
— TypeSquareMatrixShape
Shape object for a square matrix of side_dimension
rows and columns. The vectorized form contains the entries of the the matrix given column by column (or equivalently, the entries of the lower-left triangular part given row by row).
JuMP.SymmetricMatrixShape
— TypeSymmetricMatrixShape
Shape object for a symmetric square matrix of side_dimension
rows and columns. The vectorized form contains the entries of the upper-right triangular part of the matrix given column by column (or equivalently, the entries of the lower-left triangular part given row by row).
JuMP.operator_to_set
— Functionoperator_to_set(_error::Function, ::Val{sense_symbol})
Converts a sense symbol to a set set
such that @constraint(model, func sense_symbol 0)
is equivalent to @constraint(model, func in set)
for any func::AbstractJuMPScalar
.
Example
Once a custom set is defined you can directly create a JuMP constraint with it:
julia> struct CustomSet{T} <: MOI.AbstractScalarSet
value::T
end
julia> Base.copy(x::CustomSet) = CustomSet(x.value)
julia> model = Model();
julia> @variable(model, x)
x
julia> cref = @constraint(model, x in CustomSet(1.0))
x ∈ CustomSet{Float64}(1.0)
However, there might be an appropriate sign that could be used in order to provide a more convenient syntax:
julia> JuMP.operator_to_set(::Function, ::Val{:⊰}) = CustomSet(0.0)
julia> MOIU.shift_constant(set::CustomSet, value) = CustomSet(set.value + value)
julia> cref = @constraint(model, x ⊰ 1)
x ∈ CustomSet{Float64}(1.0)
Note that the whole function is first moved to the right-hand side, then the sign is transformed into a set with zero constant and finally the constant is moved to the set with MOIU.shift_constant
.
JuMP.parse_constraint
— Functionparse_constraint(_error::Function, expr::Expr)
The entry-point for all constraint-related parsing.
Arguments
- The
_error
function is passed everywhere to provide better error messages expr
comes from the@constraint
macro. There are two possibilities:@constraint(model, expr)
@constraint(model, name[args], expr)
expr
is the main component of the constraint.
Supported syntax
JuMP currently supports the following expr
objects:
lhs <= rhs
lhs == rhs
lhs >= rhs
l <= body <= u
u >= body >= l
lhs ⟂ rhs
lhs in rhs
lhs ∈ rhs
z => {constraint}
!z => {constraint}
as well as all broadcasted variants.
Extensions
The infrastructure behind parse_constraint
is extendable. See parse_constraint_head
and parse_constraint_call
for details.
JuMP.parse_constraint_head
— Functionparse_constraint_head(_error::Function, ::Val{head}, args...)
Implement this method to intercept the parsing of an expression with head head
.
Extending the constraint macro at parse time is an advanced operation and has the potential to interfere with existing JuMP syntax. Please discuss with the developer chatroom before publishing any code that implements these methods.
Arguments
_error
: a function that accepts aString
and throws the string as an error, along with some descriptive information of the macro from which it was thrown.head
: the.head
field of theExpr
to interceptargs...
: the.args
field of theExpr
.
Returns
This function must return:
is_vectorized::Bool
: whether the expression represents a broadcasted expression likex .<= 1
parse_code::Expr
: an expression containing any setup or rewriting code that needs to be called beforebuild_constraint
build_code::Expr
: an expression that callsbuild_constraint(
orbuild_constraint.(
depending onis_vectorized
.
Existing implementations
JuMP currently implements:
::Val{:call}
, which forwards calls toparse_constraint_call
::Val{:comparison}
, which handles the special case ofl <= body <= u
.
See also: parse_constraint_call
, build_constraint
JuMP.parse_constraint_call
— Functionparse_constraint_call(
_error::Function,
is_vectorized::Bool,
::Val{op},
args...,
)
Implement this method to intercept the parsing of a :call
expression with operator op
.
Extending the constraint macro at parse time is an advanced operation and has the potential to interfere with existing JuMP syntax. Please discuss with the developer chatroom before publishing any code that implements these methods.
Arguments
_error
: a function that accepts aString
and throws the string as an error, along with some descriptive information of the macro from which it was thrown.is_vectorized
: a boolean to indicate ifop
should be broadcast or notop
: the first element of the.args
field of theExpr
to interceptargs...
: the.args
field of theExpr
.
Returns
This function must return:
parse_code::Expr
: an expression containing any setup or rewriting code that needs to be called beforebuild_constraint
build_code::Expr
: an expression that callsbuild_constraint(
orbuild_constraint.(
depending onis_vectorized
.
See also: parse_constraint_head
, build_constraint
parse_constraint_call(
_error::Function,
vectorized::Bool,
::Val{op},
lhs,
rhs,
) where {op}
Fallback handler for binary operators. These might be infix operators like @constraint(model, lhs op rhs)
, or normal operators like @constraint(model, op(lhs, rhs))
.
In both cases, we rewrite as lhs - rhs in operator_to_set(_error, op)
.
See operator_to_set
for details.