From d3b5a3ef1fb47624d16866fbafedad8f8b3a7ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 21 Jul 2019 21:43:09 -0400 Subject: [PATCH 1/4] Add normalize_constant --- src/Utilities/constraints.jl | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Utilities/constraints.jl b/src/Utilities/constraints.jl index 340e6511f6..71ff04e7a0 100644 --- a/src/Utilities/constraints.jl +++ b/src/Utilities/constraints.jl @@ -10,20 +10,26 @@ the set in `model`. If `allow_modify_function` is `true` then the function """ function add_scalar_constraint end -function add_scalar_constraint(model::MOI.ModelLike, func::MOI.SingleVariable, - set::MOI.AbstractScalarSet; - allow_modify_function::Bool=false) - return MOI.add_constraint(model, func, set) -end function add_scalar_constraint(model::MOI.ModelLike, - func::Union{MOI.ScalarAffineFunction{T}, - MOI.ScalarQuadraticFunction{T}}, + func::MOI.AbstractScalarFunction, set::MOI.AbstractScalarSet; allow_modify_function::Bool=false) where T + return MOI.add_constraint( + model, normalize_constant( + func, set; allow_modify_function=allow_modify_function)...) +end + +function normalize_constant(func::MOI.AbstractFunction, set::MOI.AbstractSet; + allow_modify_function::Bool=false) + return func, set +end +function normalize_constant( + func::Union{MOI.ScalarAffineFunction{T}, MOI.ScalarQuadraticFunction{T}}, + set::MOI.AbstractScalarSet; allow_modify_function::Bool=false) where T set = shift_constant(set, -func.constant) if !allow_modify_function func = copy(func) end func.constant = zero(T) - return MOI.add_constraint(model, func, set) + return func, set end From e3e3c224c78b1e6562e84141600d5c6fcf82c387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 21 Jul 2019 22:55:31 -0400 Subject: [PATCH 2/4] Update doc --- docs/src/apireference.md | 7 +++++-- src/Utilities/constraints.jl | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 4b0968fcc6..83d83f0c8c 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -677,11 +677,14 @@ Utilities.operate! Utilities.vectorize ``` -## Set utilities +## Constraint utilities -The following utilities are available for sets: +The following utilities are available for moving the function constant to the +set for scalar constraints: ```@docs Utilities.shift_constant +Utilities.add_scalar_constraint +Utilities.normalize_constant ``` ## Benchmarks diff --git a/src/Utilities/constraints.jl b/src/Utilities/constraints.jl index 71ff04e7a0..dd208eb655 100644 --- a/src/Utilities/constraints.jl +++ b/src/Utilities/constraints.jl @@ -6,7 +6,7 @@ Adds the scalar constraint obtained by moving the constant term in `func` to the set in `model`. If `allow_modify_function` is `true` then the function -`func`, can be modified. +`func` can be modified. """ function add_scalar_constraint end @@ -19,6 +19,16 @@ function add_scalar_constraint(model::MOI.ModelLike, func, set; allow_modify_function=allow_modify_function)...) end +""" + normalize_constant(func::MOI.AbstractScalarFunction, + set::MOI.AbstractScalarSet; + allow_modify_function::Bool=false) + +Return the `func`-in-`set` constraint in normalized form. That is, if `func` is +[`ScalarQuadraticFunction`](@ref) or [`ScalarAffineFunction`](@ref), the +constant is moved to the set. If `allow_modify_function` is `true` then the +function `func` can be modified. +""" function normalize_constant(func::MOI.AbstractFunction, set::MOI.AbstractSet; allow_modify_function::Bool=false) return func, set From 8bf113331a714348abdc7a3828d3d8b33b872c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 21 Jul 2019 23:01:21 -0400 Subject: [PATCH 3/4] use MOI --- src/Utilities/constraints.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Utilities/constraints.jl b/src/Utilities/constraints.jl index dd208eb655..a41a2b5d1a 100644 --- a/src/Utilities/constraints.jl +++ b/src/Utilities/constraints.jl @@ -25,7 +25,8 @@ end allow_modify_function::Bool=false) Return the `func`-in-`set` constraint in normalized form. That is, if `func` is -[`ScalarQuadraticFunction`](@ref) or [`ScalarAffineFunction`](@ref), the +[`MOI.ScalarQuadraticFunction`](@ref) or +[`MOI.ScalarAffineFunction`](@ref), the constant is moved to the set. If `allow_modify_function` is `true` then the function `func` can be modified. """ From a4a5191015932cc79c4451e469260b96de5d8318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 24 Jul 2019 09:37:43 -0400 Subject: [PATCH 4/4] Rename add_scalar_constraint --- NEWS.md | 2 ++ docs/src/apireference.md | 2 +- src/Bridges/Constraint/det.jl | 4 ++-- src/Bridges/Constraint/geomean.jl | 2 +- src/Bridges/Constraint/scalarize.jl | 2 +- src/Bridges/Constraint/square.jl | 5 ++--- src/Utilities/constraints.jl | 18 +++++++++--------- src/constraints.jl | 2 +- test/Utilities/constraints.jl | 10 +++++----- 9 files changed, 24 insertions(+), 23 deletions(-) diff --git a/NEWS.md b/NEWS.md index 02651edad6..ac8aa245a8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,6 +38,8 @@ v0.9.0 (May 2?, 2019) * The `Utilities.constant` function was renamed to `Utilities.constant_vector` (#740). * Implement optimizer attributes for CachingOptimizer (#745). + * Rename `Utilities.add_scalar_constraint` to + `Utilities.normalize_and_add_constraint` (#801). * `operate` with `vcat`, `SingleVariable` and `VectorOfVariables` now returns a `VectorOfVariables` (#616). * Fix a type piracy of `operate` (#784). diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 83d83f0c8c..319db570ba 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -683,7 +683,7 @@ The following utilities are available for moving the function constant to the set for scalar constraints: ```@docs Utilities.shift_constant -Utilities.add_scalar_constraint +Utilities.normalize_and_add_constraint Utilities.normalize_constant ``` diff --git a/src/Bridges/Constraint/det.jl b/src/Bridges/Constraint/det.jl index 00c052852c..ba354e3b7e 100644 --- a/src/Bridges/Constraint/det.jl +++ b/src/Bridges/Constraint/det.jl @@ -119,8 +119,8 @@ Constrains ``t \\le l_1 + \\cdots + l_n`` where `n` is the length of `l` and ret function subsum(model, t::MOI.ScalarAffineFunction, l::Vector{MOI.VariableIndex}, ::Type{T}) where T n = length(l) f = MOIU.operate!(-, T, t, MOIU.operate(sum, T, l)) - return MOIU.add_scalar_constraint(model, f, MOI.LessThan(zero(T)), - allow_modify_function=true) + return MOIU.normalize_and_add_constraint(model, f, MOI.LessThan(zero(T)), + allow_modify_function=true) end # Attributes, Bridge acting as a model diff --git a/src/Bridges/Constraint/geomean.jl b/src/Bridges/Constraint/geomean.jl index e8cfc22980..1f2d56ec3a 100644 --- a/src/Bridges/Constraint/geomean.jl +++ b/src/Bridges/Constraint/geomean.jl @@ -70,7 +70,7 @@ function bridge_constraint(::Type{GeoMeanBridge{T, F, G}}, model, t = f_scalars[1] # With sqrt(2)^l*t - xl1, we should scale both the ConstraintPrimal and ConstraintDual - tubc = MOIU.add_scalar_constraint( + tubc = MOIU.normalize_and_add_constraint( model, MOIU.operate!(+, T, t, -sN * xl1), MOI.LessThan(zero(T)), allow_modify_function=true) diff --git a/src/Bridges/Constraint/scalarize.jl b/src/Bridges/Constraint/scalarize.jl index ab2c89039e..15cd855307 100644 --- a/src/Bridges/Constraint/scalarize.jl +++ b/src/Bridges/Constraint/scalarize.jl @@ -23,7 +23,7 @@ function bridge_constraint(::Type{ScalarizeBridge{T, F, S}}, new_f = MOIU.scalarize(f, true) constraints = Vector{CI{F, S}}(undef, dimension) for i in 1:dimension - constraints[i] = MOIU.add_scalar_constraint(model, new_f[i], S(-constants[i])) + constraints[i] = MOIU.normalize_and_add_constraint(model, new_f[i], S(-constants[i])) end return ScalarizeBridge{T, F, S}(constraints, constants) end diff --git a/src/Bridges/Constraint/square.jl b/src/Bridges/Constraint/square.jl index ce0009ae0d..4233f9abe2 100644 --- a/src/Bridges/Constraint/square.jl +++ b/src/Bridges/Constraint/square.jl @@ -105,9 +105,8 @@ function bridge_constraint(::Type{SquareBridge{T, F, G, TT, ST}}, " coefficients is smaller than 1e-8 but larger than" * " 1e-10." end - push!(sym, (i, j) => MOIU.add_scalar_constraint(model, diff, - MOI.EqualTo(zero(T)), - allow_modify_function=true)) + push!(sym, (i, j) => MOIU.normalize_and_add_constraint( + model, diff, MOI.EqualTo(zero(T)), allow_modify_function=true)) end end k += dim - j diff --git a/src/Utilities/constraints.jl b/src/Utilities/constraints.jl index a41a2b5d1a..d060e583e5 100644 --- a/src/Utilities/constraints.jl +++ b/src/Utilities/constraints.jl @@ -1,19 +1,19 @@ """ - add_scalar_constraint(model::MOI.ModelLike, - func::MOI.AbstractScalarFunction, - set::MOI.AbstractScalarSet; - allow_modify_function::Bool=false) + normalize_and_add_constraint(model::MOI.ModelLike, + func::MOI.AbstractScalarFunction, + set::MOI.AbstractScalarSet; + allow_modify_function::Bool=false) Adds the scalar constraint obtained by moving the constant term in `func` to the set in `model`. If `allow_modify_function` is `true` then the function `func` can be modified. """ -function add_scalar_constraint end +function normalize_and_add_constraint end -function add_scalar_constraint(model::MOI.ModelLike, - func::MOI.AbstractScalarFunction, - set::MOI.AbstractScalarSet; - allow_modify_function::Bool=false) where T +function normalize_and_add_constraint(model::MOI.ModelLike, + func::MOI.AbstractScalarFunction, + set::MOI.AbstractScalarSet; + allow_modify_function::Bool=false) where T return MOI.add_constraint( model, normalize_constant( func, set; allow_modify_function=allow_modify_function)...) diff --git a/src/constraints.jl b/src/constraints.jl index 36ca0fbe22..375003a4e0 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -78,7 +78,7 @@ function Base.showerror(io::IO, err::ScalarFunctionConstantNotZero{T, F, S}) where {T, F, S} print(io, "In `$F`-in-`$S` constraint: Constant $(err.constant) of the ", "function is not zero. The function constant should be moved to the ", - "set. You can use `MOI.Utilities.add_scalar_constraint` which does ", + "set. You can use `MOI.Utilities.normalize_and_add_constraint` which does ", "this automatically.") end diff --git a/test/Utilities/constraints.jl b/test/Utilities/constraints.jl index e7927e9d2a..857fc2dce3 100644 --- a/test/Utilities/constraints.jl +++ b/test/Utilities/constraints.jl @@ -7,20 +7,20 @@ const MOI = MathOptInterface x = MOI.add_variable(model) @testset "SingleVariable" begin f = MOI.SingleVariable(x) - ci = MOIU.add_scalar_constraint(model, f, MOI.EqualTo(1.0), - allow_modify_function = false) + ci = MOIU.normalize_and_add_constraint(model, f, MOI.EqualTo(1.0), + allow_modify_function = false) @test MOI.get(model, MOI.ConstraintFunction(), ci) == f @test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.EqualTo(1.0) end @testset "ScalarAffineFunction" begin f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 2.0) g = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0) - ci = MOIU.add_scalar_constraint(model, f, MOI.EqualTo(3.0)) + ci = MOIU.normalize_and_add_constraint(model, f, MOI.EqualTo(3.0)) @test f.constant == 2.0 @test MOI.get(model, MOI.ConstraintFunction(), ci) ≈ g @test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.EqualTo(1.0) - ci = MOIU.add_scalar_constraint(model, f, MOI.Interval(-1.0, 1.0), - allow_modify_function = true) + ci = MOIU.normalize_and_add_constraint(model, f, MOI.Interval(-1.0, 1.0), + allow_modify_function = true) @test f.constant == 0.0 @test MOI.get(model, MOI.ConstraintFunction(), ci) ≈ g @test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.Interval(-3.0,