diff --git a/src/Bridges/Variable/kernel.jl b/src/Bridges/Variable/kernel.jl index fb83a7ad7..def2a0022 100644 --- a/src/Bridges/Variable/kernel.jl +++ b/src/Bridges/Variable/kernel.jl @@ -19,8 +19,12 @@ function MOI.Bridges.Variable.bridge_constrained_variable( gram, vars, con = SOS.add_gram_matrix(model, M, gram_basis, T) push!(variables, vars) push!(constraints, con) - MA.operate_to!(cache, +, gram) - MA.operate!(SA.UnsafeAddMul(*), acc, cache, weight) + if isone(weight) + MA.operate!(SA.UnsafeAdd(), acc, gram) + else + MA.operate_to!(cache, +, gram) + MA.operate!(SA.UnsafeAddMul(*), acc, cache, weight) + end end MA.operate!(SA.canonical, SA.coeffs(acc)) return KernelBridge{T,M}( diff --git a/src/Certificate/ideal.jl b/src/Certificate/ideal.jl index 4def1276a..3e1f7fe0e 100644 --- a/src/Certificate/ideal.jl +++ b/src/Certificate/ideal.jl @@ -37,12 +37,22 @@ function _combine_with_gram( ) end for (gram, weight) in zip(gram_bases, weights) - MA.operate_to!( - cache, - +, - GramMatrix{_NonZero}((_, _) -> _NonZero(), gram), - ) - MA.operate!(SA.UnsafeAddMul(*), p, cache, weight) + if isone(weight) + MA.operate!( + SA.UnsafeAdd(), + p, + SA.QuadraticForm( + GramMatrix{_NonZero}((_, _) -> _NonZero(), gram), + ), + ) + else + MA.operate_to!( + cache, + +, + GramMatrix{_NonZero}((_, _) -> _NonZero(), gram), + ) + MA.operate!(SA.UnsafeAddMul(*), p, cache, weight) + end end MA.operate!(SA.canonical, SA.coeffs(p)) return SA.sub_basis(parent(basis), keys(SA.coeffs(p))) diff --git a/test/Bridges/Variable/kernel.jl b/test/Bridges/Variable/kernel.jl index e82aa67b9..45acc0ab4 100644 --- a/test/Bridges/Variable/kernel.jl +++ b/test/Bridges/Variable/kernel.jl @@ -68,6 +68,105 @@ function test_runtests() return end +function test_runtests_weighted() + @polyvar x y + MOI.Bridges.runtests( + SumOfSquares.Bridges.Variable.KernelBridge, + model -> begin + p, _ = MOI.add_constrained_variables( + model, + SumOfSquares.WeightedSOSCone{ + MOI.PositiveSemidefiniteConeTriangle, + }( + MB.SubBasis{MB.Monomial}([ + y^4, + x * y^3, + x^2 * y^2, + x^3 * y, + x^4, + ]), + [MB.SubBasis{MB.Monomial}([y^2, x * y, x^2])], + [MB.algebra_element(2.0 * x^0 * y^0)], + ), + ) + a = float.(1:length(p)) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([a' * p]), + MOI.Zeros(1), + ) + end, + model -> begin + q, _ = MOI.add_constrained_variables( + model, + MOI.PositiveSemidefiniteConeTriangle(3), + ) + a = float.(1:length(q)) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([ + 2.0 * q[1] + + 8.0 * q[2] + + 6.0 * (1.0q[3] + 2.0q[4]) + + 16.0 * q[5] + + 10.0 * q[6], + ]), + MOI.Zeros(1), + ) + end; + cannot_unbridge = true, + ) + return +end + +# weight (1 + x), gram basis [1, x] +# (1 + x) * (Q11 + 2*Q12*x + Q22*x^2) +# = Q11 + (2*Q12 + Q11)*x + (Q22 + 2*Q12)*x^2 + Q22*x^3 +function test_runtests_polynomial_weight() + @polyvar x + MOI.Bridges.runtests( + SumOfSquares.Bridges.Variable.KernelBridge, + model -> begin + p, _ = MOI.add_constrained_variables( + model, + SumOfSquares.WeightedSOSCone{ + MOI.PositiveSemidefiniteConeTriangle, + }( + MB.SubBasis{MB.Monomial}([x^0, x, x^2, x^3]), + [MB.SubBasis{MB.Monomial}([x^0, x])], + [MB.algebra_element(1.0 * x^0 + 1.0 * x)], + ), + ) + a = float.(1:length(p)) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([a' * p]), + MOI.Zeros(1), + ) + end, + model -> begin + q, _ = MOI.add_constrained_variables( + model, + SumOfSquares.PositiveSemidefinite2x2ConeTriangle(), + ) + # p[1] = 1.0*q[1], p[2] = 1.0*q[1] + 2.0*q[2], + # p[3] = 2.0*q[2] + 1.0*q[3], p[4] = 1.0*q[3] + MOI.add_constraint( + model, + MOI.Utilities.vectorize([ + 1.0 * q[1] + + 2.0 * (1.0q[1] + 2.0q[2]) + + 3.0 * (2.0q[2] + 1.0q[3]) + + 4.0 * q[3], + ]), + MOI.Zeros(1), + ) + end; + cannot_unbridge = true, + ) + return +end + end # module TestVariableKernel.runtests()