diff --git a/src/aff_expr.jl b/src/aff_expr.jl index d4eebb36f7b..279b122db6a 100644 --- a/src/aff_expr.jl +++ b/src/aff_expr.jl @@ -273,14 +273,46 @@ Base.:(==)(x::GenericAffExpr, y::Number) = isempty(x.terms) && x.constant == y coefficient(a::GenericAffExpr{C,V}, v::V) where {C,V} Return the coefficient associated with variable `v` in the affine expression `a`. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x); + +julia> expr = 2.0 * x + 1.0; + +julia> coefficient(expr, x) +2.0 +``` """ coefficient(a::GenericAffExpr{C,V}, v::V) where {C,V} = get(a.terms, v, zero(C)) + coefficient(::GenericAffExpr{C,V}, ::V, ::V) where {C,V} = zero(C) """ drop_zeros!(expr::GenericAffExpr) Remove terms in the affine expression with `0` coefficients. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:2]); + +julia> expr = x[1] + x[2]; + +julia> add_to_expression!(expr, -1.0, x[1]) +0 x[1] + x[2] + +julia> drop_zeros!(expr) + +julia> expr +x[2] +``` """ function drop_zeros!(expr::GenericAffExpr) _drop_zeros!(expr.terms) @@ -380,7 +412,7 @@ function value(var_value::Function, ex::GenericAffExpr{T,V}) where {T,V} end """ - constant(aff::GenericAffExpr{C, V})::C + constant(aff::GenericAffExpr{C,V})::C Return the constant of the affine expression. @@ -410,7 +442,7 @@ struct LinearTermIterator{GAE<:GenericAffExpr} end """ - linear_terms(aff::GenericAffExpr{C, V}) + linear_terms(aff::GenericAffExpr{C,V}) Provides an iterator over coefficient-variable tuples `(a_i::C, x_i::V)` in the linear part of the affine expression. diff --git a/src/constraints.jl b/src/constraints.jl index b11bbe5a79b..5979bf54026 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -724,17 +724,95 @@ moi_set(constraint::AbstractConstraint) = constraint.set """ constraint_object(con_ref::ConstraintRef) -Return the underlying constraint data for the constraint referenced by `ref`. +Return the underlying constraint data for the constraint referenced by `con_ref`. + +## Example + +A scalar constraint: +```jldoctest +julia> model = Model(); + +julia> @variable(model, x); + +julia> @constraint(model, c, 2x <= 1) +c : 2 x ≤ 1 + +julia> object = constraint_object(c) +ScalarConstraint{AffExpr, MathOptInterface.LessThan{Float64}}(2 x, MathOptInterface.LessThan{Float64}(1.0)) + +julia> typeof(object) +ScalarConstraint{AffExpr, MathOptInterface.LessThan{Float64}} + +julia> object.func +2 x + +julia> object.set +MathOptInterface.LessThan{Float64}(1.0) +``` + +A vector constraint: +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:3]); + +julia> @constraint(model, c, x in SecondOrderCone()) +c : [x[1], x[2], x[3]] ∈ MathOptInterface.SecondOrderCone(3) + +julia> object = constraint_object(c) +VectorConstraint{VariableRef, MathOptInterface.SecondOrderCone, VectorShape}(VariableRef[x[1], x[2], x[3]], MathOptInterface.SecondOrderCone(3), VectorShape()) + +julia> typeof(object) +VectorConstraint{VariableRef, MathOptInterface.SecondOrderCone, VectorShape} + +julia> object.func +3-element Vector{VariableRef}: + x[1] + x[2] + x[3] + +julia> object.set +MathOptInterface.SecondOrderCone(3) +``` """ function constraint_object end """ struct ScalarConstraint -The data for a scalar constraint. The `func` field contains a JuMP object -representing the function and the `set` field contains the MOI set. +The data for a scalar constraint. + See also the [documentation](@ref Constraints) on JuMP's representation of constraints for more background. + +## Fields + + * `.func`: field contains a JuMP object representing the function + * `.set`: field contains the MOI set + +## Example + +A scalar constraint: +```jldoctest +julia> model = Model(); + +julia> @variable(model, x); + +julia> @constraint(model, c, 2x <= 1) +c : 2 x ≤ 1 + +julia> object = constraint_object(c) +ScalarConstraint{AffExpr, MathOptInterface.LessThan{Float64}}(2 x, MathOptInterface.LessThan{Float64}(1.0)) + +julia> typeof(object) +ScalarConstraint{AffExpr, MathOptInterface.LessThan{Float64}} + +julia> object.func +2 x + +julia> object.set +MathOptInterface.LessThan{Float64}(1.0) +``` """ struct ScalarConstraint{ F<:Union{Number,AbstractJuMPScalar}, @@ -745,6 +823,7 @@ struct ScalarConstraint{ end reshape_set(set::MOI.AbstractScalarSet, ::ScalarShape) = set + shape(::ScalarConstraint) = ScalarShape() function constraint_object( @@ -765,12 +844,47 @@ end """ struct VectorConstraint -The data for a vector constraint. The `func` field contains a JuMP object -representing the function and the `set` field contains the MOI set. The -`shape` field contains an [`AbstractShape`](@ref) matching the form in which -the constraint was constructed (for example, by using matrices or flat vectors). +The data for a vector constraint. + See also the [documentation](@ref Constraints) on JuMP's representation of constraints. + +## Fields + + * `func`: field contains a JuMP object representing the function + * `set`: field contains the MOI set. + * `shape`: field contains an [`AbstractShape`](@ref) matching the form in which + the constraint was constructed (for example, by using matrices or flat + vectors). + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:3]); + +julia> @constraint(model, c, x in SecondOrderCone()) +c : [x[1], x[2], x[3]] ∈ MathOptInterface.SecondOrderCone(3) + +julia> object = constraint_object(c) +VectorConstraint{VariableRef, MathOptInterface.SecondOrderCone, VectorShape}(VariableRef[x[1], x[2], x[3]], MathOptInterface.SecondOrderCone(3), VectorShape()) + +julia> typeof(object) +VectorConstraint{VariableRef, MathOptInterface.SecondOrderCone, VectorShape} + +julia> object.func +3-element Vector{VariableRef}: + x[1] + x[2] + x[3] + +julia> object.set +MathOptInterface.SecondOrderCone(3) + +julia> object.shape +VectorShape() +``` """ struct VectorConstraint{ F<:Union{Number,AbstractJuMPScalar}, @@ -806,7 +920,9 @@ function VectorConstraint( end reshape_set(set::MOI.AbstractVectorSet, ::VectorShape) = set + shape(con::VectorConstraint) = con.shape + function constraint_object( con_ref::ConstraintRef{ <:AbstractModel, @@ -818,6 +934,7 @@ function constraint_object( s = MOI.get(model, MOI.ConstraintSet(), con_ref)::SetType return VectorConstraint(jump_function(model, f), s, con_ref.shape) end + function check_belongs_to_model(con::VectorConstraint, model) for func in con.func check_belongs_to_model(func, model) @@ -1165,7 +1282,7 @@ end Return the dual value of constraint `con_ref` associated with result index `result` of the most-recent solution returned by the solver. -Use `has_dual` to check if a result exists before asking for values. +Use [`has_dual`](@ref) to check if a result exists before asking for values. See also: [`result_count`](@ref), [`shadow_price`](@ref). """ @@ -1195,8 +1312,10 @@ constraint. This value is computed from [`dual`](@ref) and can be queried only when `has_duals` is `true` and the objective sense is `MIN_SENSE` or `MAX_SENSE` -(not `FEASIBILITY_SENSE`). For linear constraints, the shadow prices differ at -most in sign from the `dual` value depending on the objective sense. +(not `FEASIBILITY_SENSE`). + +For linear constraints, the shadow prices differ at most in sign from the `dual` +value depending on the objective sense. See also [`reduced_cost`](@ref JuMP.reduced_cost). diff --git a/src/nlp.jl b/src/nlp.jl index 64f87b75a08..4837cdc6c47 100644 --- a/src/nlp.jl +++ b/src/nlp.jl @@ -658,11 +658,6 @@ end ### Nonlinear dual solutions ### -""" - dual(c::NonlinearConstraintRef) - -Return the dual of the nonlinear constraint `c`. -""" function dual(c::NonlinearConstraintRef) _init_NLP(c.model) evaluator = diff --git a/src/optimizer_interface.jl b/src/optimizer_interface.jl index 955e8630091..31d375bfde9 100644 --- a/src/optimizer_interface.jl +++ b/src/optimizer_interface.jl @@ -323,7 +323,7 @@ function _try_get_solver_name(model_like) end """ - solver_name(model::GenericModel) --> String + solver_name(model::GenericModel) If available, returns the [`MOI.SolverName`](@ref) property of the underlying optimizer. diff --git a/src/print.jl b/src/print.jl index d2b8bea758d..055e4b20f18 100644 --- a/src/print.jl +++ b/src/print.jl @@ -894,7 +894,8 @@ end constraint_string( mode::MIME, ref::ConstraintRef; - in_math_mode::Bool = false) + in_math_mode::Bool = false, + ) Return a string representation of the constraint `ref`, given the `mode`. """ diff --git a/src/quad_expr.jl b/src/quad_expr.jl index efa08b1c11b..bdada8b9150 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -191,11 +191,31 @@ end Base.:(==)(x::GenericQuadExpr, y::Number) = isempty(x.terms) && x.aff == y """ - coefficient(a::GenericAffExpr{C,V}, v1::V, v2::V) where {C,V} + coefficient(a::GenericQuadExpr{C,V}, v1::V, v2::V) where {C,V} -Return the coefficient associated with the term `v1 * v2` in the quadratic expression `a`. +Return the coefficient associated with the term `v1 * v2` in the quadratic +expression `a`. Note that `coefficient(a, v1, v2)` is the same as `coefficient(a, v2, v1)`. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:2]); + +julia> expr = 2.0 * x[1] * x[2]; + +julia> coefficient(expr, x[1], x[2]) +2.0 + +julia> coefficient(expr, x[2], x[1]) +2.0 + +julia> coefficient(expr, x[1], x[1]) +0.0 +``` """ function coefficient(q::GenericQuadExpr{C,V}, v1::V, v2::V) where {C,V} return get(q.terms, UnorderedPair(v1, v2), zero(C)) @@ -204,7 +224,21 @@ end """ coefficient(a::GenericQuadExpr{C,V}, v::V) where {C,V} -Return the coefficient associated with variable `v` in the affine component of `a`. +Return the coefficient associated with variable `v` in the affine component of +`a`. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x); + +julia> expr = 2.0 * x^2 + 3.0 * x; + +julia> coefficient(expr, x) +3.0 +``` """ coefficient(q::GenericQuadExpr{C,V}, v::V) where {C,V} = coefficient(q.aff, v) @@ -212,6 +246,24 @@ coefficient(q::GenericQuadExpr{C,V}, v::V) where {C,V} = coefficient(q.aff, v) drop_zeros!(expr::GenericQuadExpr) Remove terms in the quadratic expression with `0` coefficients. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:2]); + +julia> expr = x[1]^2 + x[2]^2; + +julia> add_to_expression!(expr, -1.0, x[1], x[1]) +0 x[1]² + x[2]² + +julia> drop_zeros!(expr) + +julia> expr +x[2]² +``` """ function drop_zeros!(expr::GenericQuadExpr) drop_zeros!(expr.aff) @@ -318,7 +370,7 @@ julia> constant(quad) constant(quad::GenericQuadExpr) = constant(quad.aff) """ - linear_terms(quad::GenericQuadExpr{C, V}) + linear_terms(quad::GenericQuadExpr{C,V}) Provides an iterator over tuples `(coefficient::C, variable::V)` in the linear part of the quadratic expression. @@ -336,7 +388,7 @@ struct QuadTermIterator{GQE<:GenericQuadExpr} end """ - quad_terms(quad::GenericQuadExpr{C, V}) + quad_terms(quad::GenericQuadExpr{C,V}) Provides an iterator over tuples `(coefficient::C, var_1::V, var_2::V)` in the quadratic part of the quadratic expression. diff --git a/src/variables.jl b/src/variables.jl index feb9ad43047..7e273561bea 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -381,10 +381,24 @@ end """ coefficient(v1::GenericVariableRef{T}, v2::GenericVariableRef{T}) where {T} -Return `one(T)` if `v1 == v2`, and `zero(T)` otherwise. +Return `one(T)` if `v1 == v2` and `zero(T)` otherwise. This is a fallback for other [`coefficient`](@ref) methods to simplify code in which the expression may be a single variable. + +## Example + +```jldoctest +julia> model = Model(); + +julia> @variable(model, x[1:2]); + +julia> coefficient(x[1], x[1]) +1.0 + +julia> coefficient(x[1], x[2]) +0.0 +``` """ function coefficient( v1::GenericVariableRef{T},