/
Certificate.jl
176 lines (141 loc) · 6.11 KB
/
Certificate.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
module Certificate
import MultivariatePolynomials
const MP = MultivariatePolynomials
import MultivariateBases
const MB = MultivariateBases
using SemialgebraicSets
using SumOfSquares
include("newton_polytope.jl")
# Certificate denominator * p = ... domain
# Polya (1 + x1 + ... + xn)^(2d) * p = ∑ λ_α x.^α λ_α ∈ R_+ R_+^n
# Putinar p = σ_0 + ∑ σ_i g_i σ_i SOS g_i ≥ 0
# Krivine p = ∑ λ_{αβ} g.^α (1 .- g).^β λ_{αβ} ≥ 0 0 ≤ g_i ≤ 1
# Schmüdgen p = ∑ σ_α g^α σ_α SOS g_i ≥ 0
# Hilbert d * p = σ d, σ SOS R^n
struct PreorderIndex
value::Int
end
struct IdealIndex
value::Int
end
const Index = Union{PreorderIndex, IdealIndex}
abstract type Attribute end
# For get
struct Cone <: Attribute end
struct GramBasis <: Attribute end
struct GramBasisType <: Attribute end
struct ReducedPolynomial <: Attribute end
struct IdealCertificate <: Attribute end
struct PreprocessedDomain <: Attribute end
# Only for PreorderIndex
struct PreorderIndices <: Attribute end
struct Generator <: Attribute end
struct MultiplierBasis <: Attribute end
struct MultiplierBasisType <: Attribute end
# For set
#struct Monomials <: Attribute end
# PreorderCertificate
# IdealCertificate
# FullSpaceCertificate
abstract type AbstractCertificate end
abstract type AbstractPreorderCertificate <: AbstractCertificate end
abstract type AbstractIdealCertificate <: AbstractCertificate end
struct Putinar{IC <: AbstractIdealCertificate, CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: AbstractPreorderCertificate
ideal_certificate::IC
cone::CT
basis::Type{BT}
maxdegree::Int
end
get(certificate::Putinar, ::Cone) = certificate.cone
struct DomainWithVariables{S, V}
domain::S
variables::V
end
function get(::Putinar, ::PreprocessedDomain, domain::BasicSemialgebraicSet, p)
return DomainWithVariables(domain, MP.variables(p))
end
function get(::Putinar, index::PreorderIndices, domain::DomainWithVariables)
return map(PreorderIndex, eachindex(domain.domain.p))
end
function maxdegree_gram_basis(B::Type, variables, maxdegree::Int)
return MB.maxdegree_basis(B, variables, div(maxdegree, 2))
end
function get(certificate::Putinar, ::MultiplierBasis, index::PreorderIndex, domain::DomainWithVariables)
q = domain.domain.p[index.value]
vars = sort!([domain.variables..., MP.variables(q)...], rev = true)
unique!(vars)
maxdegree_s2 = certificate.maxdegree - MP.maxdegree(q)
# If maxdegree_s2 is odd, `div(maxdegree_s2, 2)` would make s^2 have degree up to maxdegree_s2-1
# for this reason, we take `div(maxdegree_s2 + 1, 2)` so that s^2 have degree up to maxdegree_s2+1
return maxdegree_gram_basis(certificate.basis, vars, maxdegree_s2 + 1)
end
function get(::Type{Putinar{IC, CT, BT}}, ::MultiplierBasisType) where {IC, CT, BT}
return BT
end
function get(::Putinar, ::Generator, index::PreorderIndex, domain::DomainWithVariables)
return domain.domain.p[index.value]
end
get(certificate::Putinar, ::IdealCertificate) = certificate.ideal_certificate
get(::Type{<:Putinar{IC}}, ::IdealCertificate) where {IC} = IC
SumOfSquares.matrix_cone_type(::Type{<:Putinar{IC, CT}}) where {IC, CT} = SumOfSquares.matrix_cone_type(CT)
######################
# Ideal certificates #
######################
abstract type SimpleIdealCertificate{CT, BT} <: AbstractIdealCertificate end
get(::SimpleIdealCertificate, ::ReducedPolynomial, poly, domain) = poly
get(certificate::SimpleIdealCertificate, ::Cone) = certificate.cone
SumOfSquares.matrix_cone_type(::Type{<:SimpleIdealCertificate{CT}}) where {CT} = SumOfSquares.matrix_cone_type(CT)
# TODO return something else when `PolyJuMP` support other bases.
zero_basis(certificate::SimpleIdealCertificate) = MB.MonomialBasis
zero_basis_type(::Type{<:SimpleIdealCertificate{CT, BT}}) where {CT, BT} = MB.MonomialBasis
struct MaxDegree{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}
cone::CT
basis::Type{BT}
maxdegree::Int
end
function get(certificate::MaxDegree, ::GramBasis, poly) where CT
return maxdegree_gram_basis(certificate.basis, MP.variables(poly), certificate.maxdegree)
end
function get(::Type{MaxDegree{CT, BT}}, ::GramBasisType) where {CT, BT}
return BT
end
struct FixedBasis{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}
cone::CT
basis::BT
end
function get(certificate::FixedBasis, ::GramBasis, poly) where CT
return certificate.basis
end
function get(::Type{FixedBasis{CT, BT}}, ::GramBasisType) where {CT, BT}
return BT
end
struct Newton{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis, NPT <: Tuple} <: SimpleIdealCertificate{CT, BT}
cone::CT
basis::Type{BT}
variable_groups::NPT
end
function get(certificate::Newton{CT, B}, ::GramBasis, poly) where {CT, B}
return MB.basis_covering_monomials(B, monomials_half_newton_polytope(MP.monomials(poly), certificate.variable_groups))
end
function get(::Type{<:Newton{CT, BT}}, ::GramBasisType) where {CT, BT}
return BT
end
struct Remainder{GCT<:AbstractIdealCertificate} <: AbstractIdealCertificate
gram_certificate::GCT
end
function get(::Remainder, ::ReducedPolynomial, poly, domain)
return convert(typeof(poly), rem(poly, ideal(domain)))
end
function get(certificate::Remainder, attr::GramBasis, poly)
return get(certificate.gram_certificate, attr, poly)
end
function get(::Type{Remainder{GCT}}, attr::GramBasisType) where GCT
return get(GCT, attr)
end
get(certificate::Remainder, attr::Cone) = get(certificate.gram_certificate, attr)
SumOfSquares.matrix_cone_type(::Type{Remainder{GCT}}) where {GCT} = SumOfSquares.matrix_cone_type(GCT)
zero_basis(certificate::Remainder) = zero_basis(certificate.gram_certificate)
zero_basis_type(::Type{Remainder{GCT}}) where {GCT} = zero_basis_type(GCT)
include("csp/ChordalExtensionGraph.jl")
include("csp/sparse_putinar.jl")
end