From b0c0982436141288b136e57539ac95f42984492f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 2 Jan 2019 15:23:08 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Add=20vcat=20for=20SingleVariab?= =?UTF-8?q?le=20and=20VectorOfVariables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Utilities/functions.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Utilities/functions.jl b/src/Utilities/functions.jl index 084434d83d..f87d8299f1 100644 --- a/src/Utilities/functions.jl +++ b/src/Utilities/functions.jl @@ -1334,6 +1334,30 @@ function fill_vector(vector::Vector, ::Type{T}, vector_offset::Int, funcs...) end +function fill_variables(variables::Vector{MOI.VariableIndex}, offset::Int, + output_offset::Int, func::MOI.SingleVariable) + variables[offset + 1] = func.variable +end + +function fill_variables(variables::Vector{MOI.VariableIndex}, offset::Int, + output_offset::Int, func::MOI.VectorOfVariables) + variables[offset .+ (1:length(func.variables))] .= func.variables +end + +function promote_operation(::typeof(vcat), ::Type{T}, + ::Type{<:Union{MOI.SingleVariable, + MOI.VectorOfVariables}}...) where T + return MOI.VectorOfVariables +end +function operate(::typeof(vcat), ::Type{T}, + funcs::Union{MOI.SingleVariable, + MOI.VectorOfVariables}...) where T + out_dim = sum(func -> output_dim(T, func), funcs) + variables = Vector{MOI.VariableIndex}(undef, out_dim) + fill_vector(variables, T, 0, 0, fill_variables, output_dim, funcs...) + return MOI.VectorOfVariables(variables) +end + number_of_affine_terms(::Type{T}, ::T) where T = 0 number_of_affine_terms(::Type, ::SVF) = 1 number_of_affine_terms(::Type, f::VVF) = length(f.variables) From d1bebd5a96b9e67fb3c2412c3742584f8bce9d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 11 Jul 2019 11:36:24 +0200 Subject: [PATCH 2/3] Add tests --- test/Utilities/functions.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/Utilities/functions.jl b/test/Utilities/functions.jl index 2d3d0bb49e..b83e3040f0 100644 --- a/test/Utilities/functions.jl +++ b/test/Utilities/functions.jl @@ -22,8 +22,16 @@ z = MOI.VariableIndex(3) v = MOI.VectorOfVariables([y, w]) wf = MOI.SingleVariable(w) xf = MOI.SingleVariable(x) - @testset "Variable" begin - # TODO #616 + @testset "Variable with $T" for T in [Int, Float64] + @test MOI.VectorOfVariables == MOIU.promote_operation(vcat, T, typeof(wf), typeof(v), typeof(xf)) + vov = MOIU.operate(vcat, T, wf, v, xf) + @test vov.variables == [w, y, w, x] + @test MOI.VectorOfVariables == MOIU.promote_operation(vcat, T, typeof(v), typeof(wf), typeof(xf)) + vov = MOIU.operate(vcat, T, v, wf, xf) + @test vov.variables == [y, w, w, x] + @test MOI.VectorOfVariables == MOIU.promote_operation(vcat, T, typeof(wf), typeof(xf), typeof(v)) + vov = MOIU.operate(vcat, T, wf, xf, v) + @test vov.variables == [w, x, y, w] end f = MOI.ScalarAffineFunction( MOI.ScalarAffineTerm.([2, 4], [x, z]), 5) From 6114219a7b3a6f8d53c4b0ba85bdcef83ff68913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 11 Jul 2019 11:36:36 +0200 Subject: [PATCH 3/3] Fix geomean bridge --- src/Bridges/Constraint/geomean.jl | 20 ++++++++++---------- test/Bridges/Constraint/geomean.jl | 13 +++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Bridges/Constraint/geomean.jl b/src/Bridges/Constraint/geomean.jl index 763d47b981..e8cfc22980 100644 --- a/src/Bridges/Constraint/geomean.jl +++ b/src/Bridges/Constraint/geomean.jl @@ -59,7 +59,8 @@ function bridge_constraint(::Type{GeoMeanBridge{T, F, G}}, model, xl1 = MOI.SingleVariable(xij[1]) sN = one(T) / √N - function _getx(i) + A = MOIU.promote_operation(*, T, T, MOI.SingleVariable) + function _getx(i)::A if i > n return sN * xl1 else @@ -69,10 +70,9 @@ 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(model, - MOIU.operate!(+, T, t, -sN * xl1), - MOI.LessThan(zero(T)), - allow_modify_function=true) + tubc = MOIU.add_scalar_constraint( + model, MOIU.operate!(+, T, t, -sN * xl1), MOI.LessThan(zero(T)), + allow_modify_function=true) socrc = Vector{CI{G, MOI.RotatedSecondOrderCone}}(undef, N-1) offset = offsetnext = 0 @@ -83,13 +83,13 @@ function bridge_constraint(::Type{GeoMeanBridge{T, F, G}}, model, a = _getx(2j-1) b = _getx(2j) else - a = one(T) * MOI.SingleVariable(xij[offsetnext+2j-1]) - b = one(T) * MOI.SingleVariable(xij[offsetnext+2j]) + a = convert(A, MOI.SingleVariable(xij[offsetnext+2j-1])) + b = convert(A, MOI.SingleVariable(xij[offsetnext+2j])) end c = MOI.SingleVariable(xij[offset+j]) - socrc[offset + j] = MOI.add_constraint(model, - MOIU.operate(vcat, T, a, b, c), - MOI.RotatedSecondOrderCone(3)) + socrc[offset + j] = MOI.add_constraint( + model, MOIU.operate(vcat, T, a, b, c), + MOI.RotatedSecondOrderCone(3)) end offset = offsetnext end diff --git a/test/Bridges/Constraint/geomean.jl b/test/Bridges/Constraint/geomean.jl index 70dc430f65..e351f29865 100644 --- a/test/Bridges/Constraint/geomean.jl +++ b/test/Bridges/Constraint/geomean.jl @@ -1,3 +1,16 @@ +using Test + +using MathOptInterface +const MOI = MathOptInterface +const MOIT = MathOptInterface.Test +const MOIU = MathOptInterface.Utilities +const MOIB = MathOptInterface.Bridges + +include("../utilities.jl") + +mock = MOIU.MockOptimizer(MOIU.Model{Float64}()) +config = MOIT.TestConfig() + @testset "GeoMean" begin mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [ones(4); 2; √2; √2]) bridged_mock = MOIB.Constraint.GeoMean{Float64}(mock)