Skip to content

Commit c24cae2

Browse files
authored
Change interpretation and default maxdegree (#227)
* Change interpretation and default maxdegree * Fix * Add default_maxdegree to docs * Add tolerance to test in doc * Fix for Julia v1.0
1 parent 6ae8bb5 commit c24cae2

File tree

7 files changed

+40
-12
lines changed

7 files changed

+40
-12
lines changed

docs/src/constraints.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ ArXiv e-prints, **2017**.
248248

249249
## Reference
250250

251+
Default choice for the `maxdegree` keyword:
252+
```@docs
253+
SumOfSquares.default_maxdegree
254+
```
255+
251256
Special case that is second-order cone representable:
252257
```@docs
253258
SumOfSquares.PositiveSemidefinite2x2ConeTriangle

docs/src/tutorials/Symmetry/permutation_symmetry.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ model = Model(solver)
4343
pattern = Symmetry.Pattern(G, Symmetry.VariablePermutation())
4444
con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)
4545
optimize!(model)
46-
@test value(t) -1 #src
46+
@test value(t) -1 rtol=1e-6 #src
4747
value(t)
4848

4949
# We indeed find `-1`, let's verify that symmetry was exploited:

src/Certificate/Certificate.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,7 @@ end
9797
function maxdegree_gram_basis(B::Type, variables, maxdegree::Int)
9898
return MB.maxdegree_basis(B, variables, div(maxdegree, 2))
9999
end
100-
function multiplier_maxdegree(maxdegree, q)
101-
maxdegree_s2 = maxdegree - MP.maxdegree(q)
102-
# If maxdegree_s2 is odd, `div(maxdegree_s2, 2)` would make s^2 have degree up to maxdegree_s2-1
103-
# for this reason, we take `div(maxdegree_s2 + 1, 2)` so that s^2 have degree up to maxdegree_s2+1
104-
return maxdegree_s2 + 1
105-
end
100+
multiplier_maxdegree(maxdegree, q) = maxdegree - MP.maxdegree(q)
106101
function get(certificate::Putinar, ::MultiplierBasis, index::PreorderIndex, domain::DomainWithVariables)
107102
q = domain.domain.p[index.value]
108103
vars = sort!([domain.variables..., MP.variables(q)...], rev = true)

src/constraint.jl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,41 @@ function default_certificate(::BasicSemialgebraicSet, ::Certificate.NoSparsity,
129129
return Certificate.Putinar(
130130
ideal_certificate, cone, basis, maxdegree)
131131
end
132+
133+
# Julia v1.0 does not support `init` keyword
134+
#_max_maxdegree(p) = maximum(MP.maxdegree, p, init=0)
135+
_max_maxdegree(p) = mapreduce(MP.maxdegree, max, p, init=0)
136+
137+
_maxdegree(domain) = 0
138+
139+
function _maxdegree(domain::AlgebraicSet)
140+
return _max_maxdegree(domain.I.p)
141+
end
142+
143+
function _maxdegree(domain::BasicSemialgebraicSet)
144+
return max(_max_maxdegree(domain.p), _maxdegree(domain.V))
145+
end
146+
147+
"""
148+
default_maxdegree(monos, domain)
149+
150+
Return the default `maxdegree` to use for certifying a polynomial with
151+
monomials `monos` to be Sum-of-Squares over the domain `domain`.
152+
By default, the maximum of the maxdegree of `monos` and of all multipliers
153+
of the domain are used so that at least constant multipliers can be used
154+
with a Putinar certificate.
155+
"""
156+
function default_maxdegree(monos, domain)
157+
return max(MP.maxdegree(monos), _maxdegree(domain))
158+
end
159+
132160
function JuMP.moi_set(
133161
cone::SOSLikeCone,
134162
monos::AbstractVector{<:MP.AbstractMonomial};
135163
domain::AbstractSemialgebraicSet=FullSpace(),
136164
basis=MonomialBasis,
137165
newton_polytope::Tuple=tuple(),
138-
maxdegree::Union{Nothing, Int}=MP.maxdegree(monos),
166+
maxdegree::Union{Nothing, Int}=default_maxdegree(monos, domain),
139167
sparsity::Certificate.Sparsity=Certificate.NoSparsity(),
140168
symmetry::Union{Nothing,Certificate.Symmetry.Pattern}=nothing,
141169
newton_of_remainder::Bool=false,

test/Tests/chebyshev.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ function chebyshev_test(optimizer, config::MOIT.Config)
2121
p = p1 + γ * x^ndeg # the leading coeff of p is γ
2222

2323
dom = @set x >= -1 && x <= 1
24-
@constraint(model, 1 - p in SOSCone(), domain = dom)
25-
@constraint(model, p + 1 in SOSCone(), domain = dom)
24+
@constraint(model, 1 - p in SOSCone(), domain = dom, maxdegree = 9)
25+
@constraint(model, p + 1 in SOSCone(), domain = dom, maxdegree = 9)
2626

2727
@objective(model, Max, γ)
2828

test/Tests/rearrangement.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function rearrangement_test(optimizer, config::MOIT.Config)
1818
S = @set y x && y z && x 0 && z 0
1919
# In fact, it is nonnegative everywhere so let's add terms `x + z`:
2020
cref = @constraint(model, x^2 + z^2 + 2y^2 - 2x * y - 2y * z + x + z in SOSCone(),
21-
domain = S, sparsity = VariableSparsity())
21+
domain = S, sparsity = VariableSparsity(), maxdegree = 3)
2222

2323
optimize!(model)
2424

test/equalitypolyconstr.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
m = SOSModel(factory)
55

6-
@constraint(m, x^3 + x*y^2 == x, domain=(@set x^2 + y^2 >= 1 && x^2 + y^2 <= 1))
6+
@constraint(m, x^3 + x*y^2 == x, domain=(@set x^2 + y^2 >= 1 && x^2 + y^2 <= 1), maxdegree=4)
77

88
JuMP.optimize!(m)
99

0 commit comments

Comments
 (0)