diff --git a/src/Bridges/Constraint/bridges/GeoMeanBridge.jl b/src/Bridges/Constraint/bridges/GeoMeanBridge.jl index e7adf77262..ba721d879d 100644 --- a/src/Bridges/Constraint/bridges/GeoMeanBridge.jl +++ b/src/Bridges/Constraint/bridges/GeoMeanBridge.jl @@ -373,6 +373,8 @@ function MOI.get( output[1] += MOI.get(model, _variable_attribute(attr), bridge.xij[1]) / sqrt(N) end + set = MOI.get(model, MOI.ConstraintSet(), bridge.t_upper_bound_constraint) + output[1] += MOI.constant(set) return output end @@ -382,8 +384,10 @@ function MOI.set( bridge::GeoMeanBridge{T}, value, ) where {T} + set = MOI.get(model, MOI.ConstraintSet(), bridge.t_upper_bound_constraint) + t_constant = MOI.constant(set) if bridge.d == 2 - new_value = value[1] - value[2] + new_value = value[1] - value[2] - t_constant MOI.set(model, attr, bridge.t_upper_bound_constraint, new_value) MOI.set(model, attr, bridge.x_nonnegative_constraint, [value[2]]) return @@ -396,9 +400,12 @@ function MOI.set( xij = zeros(T, N - 1) xij[1] = xl1 _get_x(i) = i > n ? sN * xl1 : value[1+i] - # With sqrt(2)^l*t - xl1, we should scale both the ConstraintPrimal and - # ConstraintDual - MOI.set(model, attr, bridge.t_upper_bound_constraint, value[1] - sN * xl1) + MOI.set( + model, + attr, + bridge.t_upper_bound_constraint, + value[1] - sN * xl1 - t_constant, + ) offset = length(bridge.rsoc_constraints) for i in l:-1:1 offset_next = offset diff --git a/test/Bridges/Constraint/test_GeoMeanBridge.jl b/test/Bridges/Constraint/test_GeoMeanBridge.jl index 673752890b..8d90095b90 100644 --- a/test/Bridges/Constraint/test_GeoMeanBridge.jl +++ b/test/Bridges/Constraint/test_GeoMeanBridge.jl @@ -519,6 +519,118 @@ function test_runtests() return end +function test_with_constant_d2() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1 + [t + 1.0, x1] in GeometricMeanCone(2) + """, + """ + variables: t, x1 + 1.0 * t + -1.0 * x1 <= -1.0 + [1.0 * x1] in Nonnegatives(1) + """, + ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1 + [t + -3.0, x1 + 1.0] in GeometricMeanCone(2) + """, + """ + variables: t, x1 + 1.0 * t + -1.0 * x1 <= 4.0 + [1.0 * x1 + 1.0] in Nonnegatives(1) + """, + ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1 + [t, x1 + 1.0] in GeometricMeanCone(2) + """, + """ + variables: t, x1 + 1.0 * t + -1.0 * x1 <= 1.0 + [1.0 + x1] in Nonnegatives(1) + """, + ) + return +end + +function test_with_constant_d3() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1, x2 + [t + 1.0, x1, x2] in GeometricMeanCone(3) + """, + """ + variables: t, x1, x2, y + 1.0 * t + -0.7071067811865475 * y <= -1.0 + [1.0 * x1, 1.0 * x2, 1.0 * y] in RotatedSecondOrderCone(3) + """, + ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1, x2 + [t, x1 + 1.0, x2] in GeometricMeanCone(3) + """, + """ + variables: t, x1, x2, y + 1.0 * t + -0.7071067811865475 * y <= 0.0 + [1.0 + 1.0 * x1, 1.0 * x2, 1.0 * y] in RotatedSecondOrderCone(3) + """, + ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1, x2 + [t + -1.0, x1 + 2.0, x2] in GeometricMeanCone(3) + """, + """ + variables: t, x1, x2, y + 1.0 * t + -0.7071067811865475 * y <= 1.0 + [1.0 * x1 + 2.0, 1.0 * x2, 1.0 * y] in RotatedSecondOrderCone(3) + """, + ) + return +end + +function test_with_constant_d4() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1, x2, x3 + [t + -1.0, x1, x2, x3] in GeometricMeanCone(4) + """, + """ + variables: t, x1, x2, x3, y1, y2, y3 + 1.0 * t + -0.5 * y1 <= 1.0 + [1.0 * x1, 1.0 * x2, 1.0 * y2] in RotatedSecondOrderCone(3) + [1.0 * y2, 1.0 * y3, 1.0 * y1] in RotatedSecondOrderCone(3) + [1.0 * x3, 0.5 * y1, 1.0 * y3] in RotatedSecondOrderCone(3) + """, + ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GeoMeanBridge, + """ + variables: t, x1, x2, x3 + [t + -3.0, x1, x2, x3] in GeometricMeanCone(4) + """, + """ + variables: t, x1, x2, x3, y1, y2, y3 + 1.0 * t + -0.5 * y1 <= 3.0 + [1.0 * x1, 1.0 * x2, 1.0 * y2] in RotatedSecondOrderCone(3) + [1.0 * y2, 1.0 * y3, 1.0 * y1] in RotatedSecondOrderCone(3) + [1.0 * x3, 0.5 * y1, 1.0 * y3] in RotatedSecondOrderCone(3) + """, + ) + return +end + end # module TestConstraintGeomean.runtests()