Skip to content

Commit 530ba09

Browse files
authored
Fix Sparse.Putinar with Newton polytope (#278)
* Fix Sparse.Putinar with Newton polytope * Fixes
1 parent 5823575 commit 530ba09

File tree

3 files changed

+69
-35
lines changed

3 files changed

+69
-35
lines changed

src/Certificate/Sparsity/monomial.jl

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,39 @@ _monos(basis::MB.MonomialBasis) = basis.monomials
152152
function _gram_monos(vars, certificate::SumOfSquares.Certificate.MaxDegree{CT, MB.MonomialBasis}) where CT
153153
return _monos(SumOfSquares.Certificate.maxdegree_gram_basis(MB.MonomialBasis, vars, certificate.maxdegree))
154154
end
155+
# poly = s0 + sum si gi
156+
# where `s1` are the multipliers with basis `multiplier_generator_monos`
157+
# we want to get the gram basis of `s0`
158+
function _ideal_monos(poly_monos, multiplier_gram_monos)
159+
monos_set = Set(poly_monos)
160+
for (gram_monos, gen_monos) in multiplier_gram_monos
161+
for a in gram_monos
162+
for b in gram_monos
163+
for m in gen_monos
164+
push!(monos_set, a * b * m)
165+
end
166+
end
167+
end
168+
end
169+
return MP.monovec(collect(monos_set))
170+
end
171+
# The ideal certificate should only ask for `MP.monomial`
172+
struct DummyPolynomial{M}
173+
monomials::M
174+
end
175+
MP.monomials(p::DummyPolynomial) = p.monomials
176+
MP.variables(p::DummyPolynomial) = MP.variables(p.monomials)
155177
function sparsity(poly::MP.AbstractPolynomial, domain::SemialgebraicSets.BasicSemialgebraicSet, sp::Monomial, certificate::SumOfSquares.Certificate.AbstractPreorderCertificate)
156-
gram_monos = _gram_monos(
157-
reduce((v, q) -> unique!(sort!([v..., MP.variables(q)...], rev=true)),
158-
domain.p, init = MP.variables(poly)),
159-
SumOfSquares.Certificate.ideal_certificate(certificate)
160-
)
161178
processed = SumOfSquares.Certificate.preprocessed_domain(certificate, domain, poly)
162179
multiplier_generator_monos = [
163180
(_monos(SumOfSquares.Certificate.multiplier_basis(certificate, index, processed)),
164181
MP.monomials(SumOfSquares.Certificate.generator(certificate, index, processed)))
165182
for index in SumOfSquares.Certificate.preorder_indices(certificate, processed)
166183
]
184+
gram_monos = _monos(SumOfSquares.Certificate.gram_basis(
185+
SumOfSquares.Certificate.ideal_certificate(certificate),
186+
DummyPolynomial(_ideal_monos(MP.monomials(poly), multiplier_generator_monos)),
187+
))
167188
cliques, multiplier_cliques = sparsity(MP.monomials(poly), sp, gram_monos, multiplier_generator_monos)
168189
return MB.MonomialBasis.(cliques), [MB.MonomialBasis.(clique) for clique in multiplier_cliques]
169190
end

src/constraint.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ function default_ideal_certificate(domain::FullSpace, basis, cone, maxdegree, ne
8181
end
8282

8383
function default_ideal_certificate(
84-
domain::AbstractAlgebraicSet, sparsity::Certificate.Sparsity.NoPattern, basis::AbstractPolynomialBasis, cone, args...)
84+
::AbstractAlgebraicSet, ::Certificate.Sparsity.NoPattern, basis::AbstractPolynomialBasis, cone, args...)
8585
return Certificate.FixedBasis(cone, basis)
8686
end
8787
function default_ideal_certificate(
88-
domain::AbstractAlgebraicSet, sparsity::Certificate.Sparsity.NoPattern, args...)
88+
domain::AbstractAlgebraicSet, ::Certificate.Sparsity.NoPattern, args...)
8989
return default_ideal_certificate(domain, args...)
9090
end
9191
function default_ideal_certificate(
92-
domain::AbstractAlgebraicSet, sparsity::Certificate.Sparsity.Pattern, args...)
92+
::AbstractAlgebraicSet, sparsity::Certificate.Sparsity.Pattern, args...)
9393
return Certificate.Sparsity.Ideal(sparsity, args...)
9494
end
9595

test/sparsity.jl

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ end
1818

1919
set_monos(bases::Vector{<:MB.MonomialBasis}) = Set([basis.monomials for basis in bases])
2020

21-
function Certificate.Sparsity.sparsity(monos::AbstractVector{<:MP.AbstractMonomial}, domain::SemialgebraicSets.BasicSemialgebraicSet, sp::Sparsity.Monomial, maxdegree, degs)
22-
half_monos = Certificate.maxdegree_gram_basis(MB.MonomialBasis, variables, div(maxdegree, 2))
23-
P = Set(monos)
24-
end
25-
2621
"""
2722
wml19()
2823
@@ -82,8 +77,11 @@ function wml19()
8277
]))
8378
@test set_monos(Certificate.Sparsity.sparsity(f, SignSymmetry(), certificate)) == expected
8479
end
85-
@testset "Example 5.4" begin
86-
preorder_certificate = Certificate.Putinar(Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 4), SOSCone(), MB.MonomialBasis, 4)
80+
@testset "Example 5.4 $(typeof(ideal_certificate))" for ideal_certificate in [
81+
Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 4),
82+
Certificate.Newton(SOSCone(), MB.MonomialBasis, tuple()),
83+
]
84+
preorder_certificate = Certificate.Putinar(ideal_certificate, SOSCone(), MB.MonomialBasis, 4)
8785
@polyvar x[1:2]
8886
f = x[1]^4 + x[2]^4 + x[1] * x[2]
8987
K = @set 1 - 2x[1]^2 - x[2]^2 >= 0
@@ -168,9 +166,8 @@ function l09()
168166
]))
169167
end
170168
end
171-
function square_domain()
172-
d = 6
173-
preorder_certificate = Certificate.Putinar(Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 6), SOSCone(), MB.MonomialBasis, 6)
169+
function square_domain(ideal_certificate, d)
170+
preorder_certificate = Certificate.Putinar(ideal_certificate, SOSCone(), MB.MonomialBasis, d)
174171
@polyvar x y
175172
f = x^2*y^4 + x^4*y^2 - 3*x^2*y*2 + 1
176173
K = @set(1 - x^2 >= 0 && 1 - y^2 >= 0)
@@ -238,22 +235,37 @@ function drop_monomials()
238235
end
239236
@test set_monos(Certificate.Sparsity.sparsity(f, Sparsity.Monomial(ChordalCompletion(), k, use_all_monomials), certificate)) == expected
240237
end
241-
preorder_certificate = Certificate.Putinar(Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 4), SOSCone(), MB.MonomialBasis, 3)
242-
f = polynomial(x^3)
243-
K = @set x >= 0
244-
@testset "$k $use_all_monomials" for k in 0:3, use_all_monomials in [false, true]
245-
basis, preorder_bases = Certificate.Sparsity.sparsity(f, K, Sparsity.Monomial(ChordalCompletion(), k, use_all_monomials), preorder_certificate)
246-
if k == 1 && !use_all_monomials
247-
@test set_monos(basis) == Set(monovec.([[x^2, x]]))
248-
elseif (k == 2 && !use_all_monomials) || (k == 1 && use_all_monomials)
249-
@test set_monos(basis) == Set(monovec.([[x^2, 1], [x^2, x]]))
250-
else
251-
@test set_monos(basis) == Set(monovec.([[x^2, x, 1]]))
252-
end
253-
if k == 1 && !use_all_monomials
254-
@test set_monos(preorder_bases[1]) == Set(monovec.([[x]]))
255-
else
256-
@test set_monos(preorder_bases[1]) == Set(monovec.([[x, 1]]))
238+
@testset "$(typeof(ideal_certificate))" for ideal_certificate in [
239+
Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 4),
240+
Certificate.Newton(SOSCone(), MB.MonomialBasis, tuple()),
241+
]
242+
preorder_certificate = Certificate.Putinar(ideal_certificate, SOSCone(), MB.MonomialBasis, 3)
243+
f = polynomial(x^3)
244+
K = @set x >= 0
245+
@testset "$k $use_all_monomials" for k in 0:3, use_all_monomials in [false, true]
246+
basis, preorder_bases = Certificate.Sparsity.sparsity(f, K, Sparsity.Monomial(ChordalCompletion(), k, use_all_monomials), preorder_certificate)
247+
if ideal_certificate isa Certificate.Newton
248+
if use_all_monomials
249+
@test set_monos(basis) == Set(monovec.([[x]]))
250+
@test set_monos(preorder_bases[1]) == Set(monovec.([[x, 1]]))
251+
else
252+
@test isempty(basis)
253+
@test set_monos(preorder_bases[1]) == Set(monovec.([[x]]))
254+
end
255+
else
256+
if k == 1 && !use_all_monomials
257+
@test set_monos(basis) == Set(monovec.([[x^2, x]]))
258+
elseif (k == 2 && !use_all_monomials) || (k == 1 && use_all_monomials)
259+
@test set_monos(basis) == Set(monovec.([[x^2, 1], [x^2, x]]))
260+
else
261+
@test set_monos(basis) == Set(monovec.([[x^2, x, 1]]))
262+
end
263+
if (k == 1 && !use_all_monomials)
264+
@test set_monos(preorder_bases[1]) == Set(monovec.([[x]]))
265+
else
266+
@test set_monos(preorder_bases[1]) == Set(monovec.([[x, 1]]))
267+
end
268+
end
257269
end
258270
end
259271
end
@@ -262,7 +274,8 @@ end
262274
xor_complement_test()
263275
wml19()
264276
l09()
265-
square_domain()
277+
square_domain(Certificate.MaxDegree(SOSCone(), MB.MonomialBasis, 6), 6)
278+
square_domain(Certificate.Newton(SOSCone(), MB.MonomialBasis, tuple()), 6)
266279
sum_square(8)
267280
@test Certificate.Sparsity.appropriate_type(32) == Int64
268281
sum_square(32)

0 commit comments

Comments
 (0)