Extensions

More information can be found in the Extensions section of the manual.

Define a new set

JuMP.AbstractVectorSetType
AbstractVectorSet

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.

source
JuMP.AbstractScalarSetType
AbstractScalarSet

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.

source

Extend @variable

JuMP.VariableInfoType
VariableInfo{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.

source
JuMP.add_variableFunction
add_variable(m::Model, v::AbstractVariable, name::String="")

Add a variable v to Model m and sets its name.

source
JuMP.build_variableFunction
build_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 of error. _error annotates the error message with additional information for the user.
  • info: an instance of VariableInfo. This has a variety of fields relating to the variable such as info.lower_bound and info.binary.
  • args: optional additional positional arguments for extending the @variable macro.
  • kwargs: optional keyword arguments for extending the @variable macro.

See also: @variable

Warning

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 MethodErrors 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.

source
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]
source
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
source
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])
source
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]
source

Extend @constraint

JuMP.build_constraintFunction
build_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()
source
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()
source
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()
source
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)
source
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)
source
JuMP.add_constraintFunction
add_constraint(model::Model, con::AbstractConstraint, name::String="")

Add a constraint con to Model model and sets its name.

source
JuMP.shapeFunction
shape(c::AbstractConstraint)::AbstractShape

Return the shape of the constraint c.

source
JuMP.reshape_vectorFunction
reshape_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
source
JuMP.reshape_setFunction
reshape_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()
source
JuMP.dual_shapeFunction
dual_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)
source
JuMP.VectorShapeType
VectorShape

Vector for which the vectorized form corresponds exactly to the vector given.

source
JuMP.SquareMatrixShapeType
SquareMatrixShape

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).

source
JuMP.SymmetricMatrixShapeType
SymmetricMatrixShape

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).

source
JuMP.operator_to_setFunction
operator_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.

source
JuMP.parse_constraintFunction
parse_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)
    In both cases, 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.

source
JuMP.parse_constraint_headFunction
parse_constraint_head(_error::Function, ::Val{head}, args...)

Implement this method to intercept the parsing of an expression with head head.

Warning

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 a String 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 the Expr to intercept
  • args...: the .args field of the Expr.

Returns

This function must return:

  • is_vectorized::Bool: whether the expression represents a broadcasted expression like x .<= 1
  • parse_code::Expr: an expression containing any setup or rewriting code that needs to be called before build_constraint
  • build_code::Expr: an expression that calls build_constraint( or build_constraint.( depending on is_vectorized.

Existing implementations

JuMP currently implements:

  • ::Val{:call}, which forwards calls to parse_constraint_call
  • ::Val{:comparison}, which handles the special case of l <= body <= u.

See also: parse_constraint_call, build_constraint

source
JuMP.parse_constraint_callFunction
parse_constraint_call(
    _error::Function,
    is_vectorized::Bool,
    ::Val{op},
    args...,
)

Implement this method to intercept the parsing of a :call expression with operator op.

Warning

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 a String 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 if op should be broadcast or not
  • op: the first element of the .args field of the Expr to intercept
  • args...: the .args field of the Expr.

Returns

This function must return:

  • parse_code::Expr: an expression containing any setup or rewriting code that needs to be called before build_constraint
  • build_code::Expr: an expression that calls build_constraint( or build_constraint.( depending on is_vectorized.

See also: parse_constraint_head, build_constraint

source
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.

source