diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 2a592ea5f3..f095ba8a6d 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -212,10 +212,14 @@ VectorQuadraticTerm VectorQuadraticFunction ``` -Functions for getting and setting properties of sets. +Functions for getting and setting properties of functions. ```@docs output_dimension +constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) +constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) +constant(f::SingleVariable, ::DataType) +constant(f::VectorOfVariables, T::DataType) ``` ## Sets @@ -258,6 +262,7 @@ Functions for getting and setting properties of sets. ```@docs dimension +constant(s::EqualTo) ``` ## Modifications diff --git a/src/Bridges/quadtosocbridge.jl b/src/Bridges/quadtosocbridge.jl index 85ac65b1c1..12a6de56a0 100644 --- a/src/Bridges/quadtosocbridge.jl +++ b/src/Bridges/quadtosocbridge.jl @@ -63,7 +63,7 @@ end function QuadtoSOCBridge{T}(model, func::MOI.ScalarQuadraticFunction{T}, set::Union{MOI.LessThan{T}, MOI.GreaterThan{T}}) where T - set_constant = MOIU.getconstant(set) + set_constant = MOI.constant(set) less_than = set isa MOI.LessThan if !less_than set_constant = -set_constant diff --git a/src/Bridges/scalarizebridge.jl b/src/Bridges/scalarizebridge.jl index 0439875782..61be7ccc2e 100644 --- a/src/Bridges/scalarizebridge.jl +++ b/src/Bridges/scalarizebridge.jl @@ -4,11 +4,6 @@ scalar_set_type(::Type{<:MOI.Zeros}, T::Type) = MOI.EqualTo{T} scalar_set_type(::Type{<:MOI.Nonpositives}, T::Type) = MOI.LessThan{T} scalar_set_type(::Type{<:MOI.Nonnegatives}, T::Type) = MOI.GreaterThan{T} -__constant(f::Union{MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction}, T::DataType) = MOI._constant(f) -__constant(f::Union{MOI.VectorAffineFunction, MOI.VectorQuadraticFunction}, T::DataType) = MOI._constant(f) -__constant(f::MOI.SingleVariable, T::DataType) = zero(T) -__constant(f::MOI.VectorOfVariables, T::DataType) = zeros(T, length(f.variables)) - """ ScalarizeBridge{T} @@ -23,7 +18,7 @@ function ScalarizeBridge{T, F, S}(model::MOI.ModelLike, f::MOI.AbstractVectorFunction, set::VectorLPSet) where {T, F, S} dimension = MOI.output_dimension(f) - constants = __constant(f, T) + constants = MOI.constant(f, T) new_f = MOIU.scalarize(f, true) constraints = Vector{CI{F, S}}(undef, dimension) for i in 1:dimension @@ -89,7 +84,7 @@ end function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintFunction, bridge::ScalarizeBridge{T}, func) where T old_constants = bridge.constants - bridge.constants = __constant(func, T) + bridge.constants = MOI.constant(func, T) new_func = MOIU.scalarize(func, true) MOI.set.(model, MOI.ConstraintFunction(), bridge.scalar_constraints, new_func) diff --git a/src/Bridges/vectorizebridge.jl b/src/Bridges/vectorizebridge.jl index c4712079dd..8ad6abef65 100644 --- a/src/Bridges/vectorizebridge.jl +++ b/src/Bridges/vectorizebridge.jl @@ -21,11 +21,11 @@ end function VectorizeBridge{T, F, S}(model::MOI.ModelLike, f::MOI.AbstractScalarFunction, set::MOI.AbstractScalarSet) where {T, F, S} - set_constant = MOIU.getconstant(set) + set_constant = MOI.constant(set) g = MOIU.operate(-, T, f, set_constant) - if -set_constant != MOI._constant(g)[1] + if -set_constant != MOI.constant(g)[1] # This means the constant in `f` was not zero - constant = MOI._constant(g)[1] + set_constant + constant = MOI.constant(g)[1] + set_constant throw(MOI.ScalarFunctionConstantNotZero{typeof(constant), typeof(f), typeof(set)}(constant)) end @@ -98,7 +98,7 @@ function MOI.modify(model::MOI.ModelLike, bridge::VectorizeBridge, end function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintSet, bridge::VectorizeBridge, new_set::LPCone) - bridge.set_constant = MOIU.getconstant(new_set) + bridge.set_constant = MOI.constant(new_set) MOI.modify(model, bridge.vector_constraint, MOI.VectorConstantChange([-bridge.set_constant])) end diff --git a/src/Utilities/functions.jl b/src/Utilities/functions.jl index de6bfed72f..c4d3da0e4a 100644 --- a/src/Utilities/functions.jl +++ b/src/Utilities/functions.jl @@ -64,12 +64,12 @@ function mapvariables(varmap::Function, f::MOI.VectorOfVariables) return MOI.VectorOfVariables(varmap.(f.variables)) end function mapvariables(varmap::Function, f::Union{SAF, VAF}) - typeof(f)(mapvariable.(varmap, f.terms), MOI._constant(f)) + typeof(f)(mapvariable.(varmap, f.terms), MOI.constant(f)) end function mapvariables(varmap::Function, f::Union{SQF, VQF}) lin = mapvariable.(varmap, f.affine_terms) quad = mapvariable.(varmap, f.quadratic_terms) - return typeof(f)(lin, quad, MOI._constant(f)) + return typeof(f)(lin, quad, MOI.constant(f)) end mapvariables(varmap, f::MOI.AbstractFunction) = mapvariables(vi -> varmap[vi], f) mapvariables(varmap::Function, change::Union{MOI.ScalarConstantChange, MOI.VectorConstantChange}) = change @@ -461,11 +461,11 @@ function removevariable(f::VVF, vi) VVF(_rmvar(f.variables, vi)) end function removevariable(f::Union{SAF, VAF}, vi) - typeof(f)(_rmvar(f.terms, vi), MOI._constant(f)) + typeof(f)(_rmvar(f.terms, vi), MOI.constant(f)) end function removevariable(f::Union{SQF, VQF}, vi) terms = _rmvar.((f.affine_terms, f.quadratic_terms), Ref(vi)) - typeof(f)(terms..., MOI._constant(f)) + typeof(f)(terms..., MOI.constant(f)) end """ @@ -1399,7 +1399,7 @@ function scalarize(f::MOI.VectorOfVariables, ignore_constants::Bool = false) end function scalarize(f::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false) where T dimension = MOI.output_dimension(f) - constants = ignore_constants ? zeros(T, dimension) : MOI._constant(f) + constants = ignore_constants ? zeros(T, dimension) : MOI.constant(f) counting = count_terms(dimension, f.terms) functions = MOI.ScalarAffineFunction{T}[ MOI.ScalarAffineFunction{T}(MOI.ScalarAffineTerm{T}[], constants[i]) for i in 1:dimension] @@ -1413,7 +1413,7 @@ function scalarize(f::MOI.VectorAffineFunction{T}, ignore_constants::Bool = fals end function scalarize(f::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false) where T dimension = MOI.output_dimension(f) - constants = ignore_constants ? zeros(T, dimension) : MOI._constant(f) + constants = ignore_constants ? zeros(T, dimension) : MOI.constant(f) counting_scalars = count_terms(dimension, f.affine_terms) counting_quadratics = count_terms(dimension, f.quadratic_terms) functions = MOI.ScalarQuadraticFunction{T}[ diff --git a/src/Utilities/sets.jl b/src/Utilities/sets.jl index c85988c94a..9b526f66d5 100644 --- a/src/Utilities/sets.jl +++ b/src/Utilities/sets.jl @@ -1,12 +1,3 @@ -""" - getconstant(s::Union{MOI.EqualTo, MOI.GreaterThan, MOI.LessThan}) - -Returns the constant of the set. -""" -getconstant(s::MOI.EqualTo) = s.value -getconstant(s::MOI.GreaterThan) = s.lower -getconstant(s::MOI.LessThan) = s.upper - const DimensionUpdatableSets = Union{MOI.Reals, MOI.Zeros, MOI.Nonnegatives, @@ -36,7 +27,7 @@ function shift_constant(set::Union{MOI.LessThan{T}, MOI.GreaterThan{T}, MOI.EqualTo{T}}, offset::T) where T - return typeof(set)(getconstant(set) + offset) + return typeof(set)(MOI.constant(set) + offset) end function shift_constant(set::MOI.Interval, offset) return MOI.Interval(set.lower + offset, set.upper + offset) diff --git a/src/functions.jl b/src/functions.jl index a827ed329d..fbfb80b004 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -352,14 +352,44 @@ function _dicts(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction}) sum_dict(term_pair.(f.quadratic_terms))) end -_constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) = f.constant -_constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) = f.constants +""" + constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) + +Returns the constant term of the scalar function +""" +constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) = f.constant + +""" + constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) + +Returns the vector of constant terms of the vector function +""" +constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) = f.constants function Base.isapprox(f::F, g::G; kwargs...) where {F<:Union{ScalarAffineFunction, ScalarQuadraticFunction, VectorAffineFunction, VectorQuadraticFunction}, G<:Union{ScalarAffineFunction, ScalarQuadraticFunction, VectorAffineFunction, VectorQuadraticFunction}} - isapprox(_constant(f), _constant(g); kwargs...) && all(dict_isapprox.(_dicts(f), _dicts(g); kwargs...)) + isapprox(constant(f), constant(g); kwargs...) && all(dict_isapprox.(_dicts(f), _dicts(g); kwargs...)) end +constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}, T::DataType) = constant(f) +constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}, T::DataType) = constant(f) + +""" + constant(f::SingleVariable, T::DataType) + +The constant term of a `SingleVariable` function is +the zero value of the specified type `T`. +""" +constant(f::SingleVariable, T::DataType) = zero(T) + +""" + constant(f::VectorOfVariables, T::DataType) + +The constant term of a `VectorOfVariables` function is a +vector of zero values of the specified type `T`. +""" +constant(f::VectorOfVariables, T::DataType) = zeros(T, length(f.variables)) + # isbits type, nothing to copy Base.copy(func::SingleVariable) = func @@ -371,7 +401,7 @@ Base.copy(func::VectorOfVariables) = VectorOfVariables(copy(func.variables)) Return a new affine function with a shallow copy of the terms and constant(s) from `func`. """ -Base.copy(func::F) where {F <: Union{ScalarAffineFunction, VectorAffineFunction}} = F(copy(func.terms), copy(_constant(func))) +Base.copy(func::F) where {F <: Union{ScalarAffineFunction, VectorAffineFunction}} = F(copy(func.terms), copy(constant(func))) """ copy(func::Union{ScalarQuadraticFunction, VectorQuadraticFunction}) @@ -379,7 +409,7 @@ Base.copy(func::F) where {F <: Union{ScalarAffineFunction, VectorAffineFunction} Return a new quadratic function with a shallow copy of the terms and constant(s) from `func`. """ -Base.copy(func::F) where {F <: Union{ScalarQuadraticFunction, VectorQuadraticFunction}} = F(copy(func.affine_terms), copy(func.quadratic_terms), copy(_constant(func))) +Base.copy(func::F) where {F <: Union{ScalarQuadraticFunction, VectorQuadraticFunction}} = F(copy(func.affine_terms), copy(func.quadratic_terms), copy(constant(func))) # Define shortcuts for # SingleVariable -> ScalarAffineFunction diff --git a/src/sets.jl b/src/sets.jl index 4797e8ad69..2616bf2cff 100644 --- a/src/sets.jl +++ b/src/sets.jl @@ -136,6 +136,15 @@ Interval(s::LessThan{<:AbstractFloat}) = Interval(typemin(s.upper), s.upper) Interval(s::EqualTo{<:Real}) = Interval(s.value, s.value) Interval(s::Interval) = s +""" + constant(s::Union{EqualTo, GreaterThan, LessThan}) + +Returns the constant of the set. +""" +constant(s::EqualTo) = s.value +constant(s::GreaterThan) = s.lower +constant(s::LessThan) = s.upper + """ SecondOrderCone(dimension) diff --git a/test/Utilities/functions.jl b/test/Utilities/functions.jl index 05bbf35828..80c7eee410 100644 --- a/test/Utilities/functions.jl +++ b/test/Utilities/functions.jl @@ -449,7 +449,7 @@ end @testset "Conversion to canonical form" begin function isapprox_ordered(f1::T, f2::T) where {T <: Union{MOI.ScalarAffineFunction, MOI.VectorAffineFunction}} ((MOI.term_indices.(f1.terms) == MOI.term_indices.(f2.terms)) && - (MOI._constant(f1) ≈ MOI._constant(f2)) && + (MOI.constant(f1) ≈ MOI.constant(f2)) && (MOI.coefficient.(f1.terms) ≈ MOI.coefficient.(f2.terms))) end function test_canonicalization(f::T, expected::T) where {T <: Union{MOI.ScalarAffineFunction, MOI.VectorAffineFunction}} diff --git a/test/Utilities/sets.jl b/test/Utilities/sets.jl index 0bf6d75a7a..6450503095 100644 --- a/test/Utilities/sets.jl +++ b/test/Utilities/sets.jl @@ -1,7 +1,7 @@ @testset "Constant" begin - @test MOIU.getconstant(MOI.EqualTo(3)) == 3 - @test MOIU.getconstant(MOI.GreaterThan(6)) == 6 - @test MOIU.getconstant(MOI.LessThan(2)) == 2 + @test MOI.constant(MOI.EqualTo(3)) == 3 + @test MOI.constant(MOI.GreaterThan(6)) == 6 + @test MOI.constant(MOI.LessThan(2)) == 2 end @testset "Shifts" begin