Skip to content

Commit 98fc3af

Browse files
authored
Sparse submodule (#228)
* sparse -> Sparse * Sparse module * Sparse -> Sparsity * Renamings * Sparse -> Sparsity * Renamings * Update tests * Add deprecation * Fixes * Fix for MOI v0.10.6 * Doc fixes * Doc fixes * Fix examples
1 parent c24cae2 commit 98fc3af

32 files changed

+273
-225
lines changed

docs/src/constraints.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,9 @@ SumOfSquares.CopositiveInner
292292

293293
Types of sparsity
294294
```@docs
295-
SumOfSquares.Certificate.VariableSparsity
296-
SumOfSquares.Certificate.MonomialSparsity
297-
SumOfSquares.Certificate.SignSymmetry
295+
SumOfSquares.Certificate.Sparsity.Variable
296+
SumOfSquares.Certificate.Sparsity.Monomial
297+
SumOfSquares.Certificate.Sparsity.SignSymmetry
298298
```
299299

300300
Ideal certificates:
@@ -303,13 +303,14 @@ SumOfSquares.Certificate.MaxDegree
303303
SumOfSquares.Certificate.FixedBasis
304304
SumOfSquares.Certificate.Newton
305305
SumOfSquares.Certificate.Remainder
306-
SumOfSquares.Certificate.SparseIdeal
306+
SumOfSquares.Certificate.Sparsity.Ideal
307+
SumOfSquares.Certificate.Symmetry.Ideal
307308
```
308309

309310
Preorder certificates:
310311
```@docs
311312
SumOfSquares.Certificate.Putinar
312-
SumOfSquares.Certificate.SparsePreorder
313+
SumOfSquares.Certificate.Sparsity.Preorder
313314
```
314315

315316
Attributes
@@ -341,12 +342,12 @@ SumOfSquares.PolyJuMP.bridges
341342

342343
Chordal extension:
343344
```@docs
344-
SumOfSquares.Certificate.ChordalExtensionGraph.neighbors
345-
SumOfSquares.Certificate.ChordalExtensionGraph.fill_in
346-
SumOfSquares.Certificate.ChordalExtensionGraph.is_clique
347-
SumOfSquares.Certificate.ChordalExtensionGraph.LabelledGraph
348-
SumOfSquares.Certificate.ChordalExtensionGraph.add_node!
349-
SumOfSquares.Certificate.ChordalExtensionGraph.add_edge!
350-
SumOfSquares.Certificate.ChordalExtensionGraph.add_clique!
351-
SumOfSquares.Certificate.ChordalExtensionGraph.completion
345+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.neighbors
346+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.fill_in
347+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.is_clique
348+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.LabelledGraph
349+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_node!
350+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_edge!
351+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_clique!
352+
SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.completion
352353
```

docs/src/tutorials/Sparsity/term_sparsity.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function sos_min(sparsity)
3434
return value(t), moment_matrix(con_ref)
3535
end
3636

37-
bound, ν = sos_min(NoSparsity())
37+
bound, ν = sos_min(Sparsity.NoPattern())
3838
@test bound 0 atol=1e-6 #src
3939
bound
4040

@@ -50,7 +50,7 @@ extractatoms(ν, 1e-6)
5050

5151
# Using the monomial/term sparsity method of [WML20a] based on cluster completion, we find the same bound.
5252

53-
bound, ν = sos_min(MonomialSparsity())
53+
bound, ν = sos_min(Sparsity.Monomial())
5454
@test bound 0 atol=1e-6 #src
5555
bound
5656

@@ -62,7 +62,7 @@ bound
6262

6363
# Using the monomial/term sparsity method of [WML20b] based on chordal completion, the lower bound is smaller than 0.
6464

65-
bound, ν = sos_min(MonomialSparsity(ChordalCompletion()))
65+
bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion()))
6666
@test bound -0.00355 rtol=1e-3 #src
6767
bound
6868

examples/chordal_sparsity.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ using Test
55
include("sparse_polynomials.jl")
66

77
function test(test_function, optimizer_constructor)
8-
sparse_model = sos_lower_bound(test_function, optimizer_constructor, VariableSparsity())
9-
dense_model = sos_lower_bound(test_function, optimizer_constructor, NoSparsity())
8+
sparse_model = sos_lower_bound(test_function, optimizer_constructor, Sparsity.Variable())
9+
dense_model = sos_lower_bound(test_function, optimizer_constructor, Sparsity.NoPattern())
1010
return abs(objective_value(sparse_model) - objective_value(dense_model))
1111
end
1212

examples/chordal_sparsity_with_domain.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ using SumOfSquares
22
using DynamicPolynomials
33
using Test
44

5-
function sos_lower_bound(factory, sparsity::Sparsity)
5+
function sos_lower_bound(factory, sparsity::Sparsity.Pattern)
66
@polyvar x y z
77
K = @set 1 - x^2 - y^2 >= 0 && 1 - y^2 - z^2 >= 0
88
p = 1 - x*y - y*z
@@ -16,10 +16,10 @@ end
1616

1717
function sparse_vs_dense(optimizer_constructor)
1818
# use chordal sparsity
19-
sparse_value = sos_lower_bound(optimizer_constructor, VariableSparsity())
19+
sparse_value = sos_lower_bound(optimizer_constructor, Sparsity.Variable())
2020

2121
# no chordal sparsity
22-
dense_value = sos_lower_bound(optimizer_constructor, NoSparsity())
22+
dense_value = sos_lower_bound(optimizer_constructor, Sparsity.NoPattern())
2323

2424
@test abs(sparse_value - dense_value) < 1e-6
2525
end

examples/sparse_polynomials.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function generalized_rosenbrock(n::Int)
4444
return p
4545
end
4646

47-
function sos_lower_bound(p, factory, sparsity::Sparsity)
47+
function sos_lower_bound(p, factory, sparsity::Sparsity.Pattern)
4848
model = Model(factory)
4949
@variable(model, t)
5050
@objective(model, Max, t)

src/Certificate/Certificate.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,9 @@ SumOfSquares.matrix_cone_type(::Type{Remainder{GCT}}) where {GCT} = SumOfSquares
244244
zero_basis(certificate::Remainder) = zero_basis(certificate.gram_certificate)
245245
zero_basis_type(::Type{Remainder{GCT}}) where {GCT} = zero_basis_type(GCT)
246246

247-
include("sparse/ChordalExtensionGraph.jl")
248-
using .ChordalExtensionGraph: ChordalCompletion, ClusterCompletion
249-
export ChordalCompletion, ClusterCompletion
250-
251-
include("sparse/sparse_putinar.jl")
247+
include("Sparsity/Sparsity.jl")
248+
using .Sparsity: SignSymmetry, ChordalCompletion, ClusterCompletion
249+
export Sparsity, SignSymmetry, ChordalCompletion, ClusterCompletion
252250

253251
include("Symmetry/Symmetry.jl")
254252
export Symmetry

src/Certificate/Sparsity/Sparsity.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module Sparsity
2+
3+
import MultivariatePolynomials
4+
const MP = MultivariatePolynomials
5+
import MultivariateBases
6+
const MB = MultivariateBases
7+
using SemialgebraicSets
8+
9+
include("ChordalExtensionGraph.jl")
10+
using .ChordalExtensionGraph: ChordalCompletion, ClusterCompletion
11+
export ChordalCompletion, ClusterCompletion
12+
13+
import SumOfSquares
14+
15+
export SignSymmetry
16+
abstract type Pattern end
17+
struct NoPattern <: Pattern end
18+
19+
include("xor_space.jl")
20+
include("sign.jl")
21+
include("variable.jl")
22+
include("monomial.jl")
23+
24+
include("preorder.jl")
25+
include("ideal.jl")
26+
27+
end

src/Certificate/Sparsity/ideal.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
struct Sparsity.Ideal{S <: Sparsity.Pattern, C <: AbstractIdealCertificate} <: SumOfSquares.Certificate.AbstractIdealCertificate
3+
sparsity::S
4+
certificate::C
5+
end
6+
7+
Same certificate as `certificate` except that the Sum-of-Squares polynomial `σ`
8+
is modelled as a sum of Sum-of-Squares polynomials with smaller bases
9+
using the sparsity reduction `sparsity`.
10+
"""
11+
struct Ideal{S <: Pattern, C <: SumOfSquares.Certificate.AbstractIdealCertificate} <: SumOfSquares.Certificate.AbstractIdealCertificate
12+
sparsity::S
13+
certificate::C
14+
end
15+
16+
function Ideal(sp::Variable, basis, cone, maxdegree::Nothing, newton_polytope)
17+
error("`maxdegree` cannot be `nothing` when `sparsity` is `Sparsity.Variable`.")
18+
end
19+
function Ideal(sp::Variable, basis, cone, maxdegree::Integer, newton_polytope)
20+
return Ideal(sp, SumOfSquares.Certificate.MaxDegree(cone, basis, maxdegree))
21+
end
22+
function Ideal(sp::Union{Monomial, SignSymmetry}, basis, cone, maxdegree, newton_polytope)
23+
return Ideal(sp, SumOfSquares.Certificate.Newton(cone, basis, newton_polytope))
24+
end
25+
26+
function sparsity(poly::MP.AbstractPolynomial, ::Variable, certificate::SumOfSquares.Certificate.MaxDegree)
27+
H, cliques = chordal_csp_graph(poly, SemialgebraicSets.FullSpace())
28+
return map(cliques) do clique
29+
return SumOfSquares.Certificate.maxdegree_gram_basis(certificate.basis, clique, certificate.maxdegree)
30+
end
31+
end
32+
function sparsity(monos, sp::Union{SignSymmetry, Monomial}, gram_basis::MB.MonomialBasis)
33+
return MB.MonomialBasis.(sparsity(monos, sp, gram_basis.monomials))
34+
end
35+
function sparsity(poly::MP.AbstractPolynomial, sp::Union{SignSymmetry, Monomial}, certificate::SumOfSquares.Certificate.AbstractIdealCertificate)
36+
return sparsity(MP.monomials(poly), sp, SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.GramBasis(), poly))
37+
end
38+
function SumOfSquares.Certificate.get(certificate::Ideal, ::SumOfSquares.Certificate.GramBasis, poly)
39+
return sparsity(poly, certificate.sparsity, certificate.certificate)
40+
end
41+
function SumOfSquares.Certificate.get(::Type{Ideal{S, C}}, attr::SumOfSquares.Certificate.GramBasisType) where {S, C}
42+
return Vector{<:SumOfSquares.Certificate.get(C, attr)}
43+
end
44+
function SumOfSquares.Certificate.get(certificate::Ideal, attr::SumOfSquares.Certificate.ReducedPolynomial, poly, domain)
45+
return SumOfSquares.Certificate.get(certificate.certificate, attr, poly, domain)
46+
end
47+
function SumOfSquares.Certificate.get(certificate::Ideal, attr::SumOfSquares.Certificate.Cone)
48+
return SumOfSquares.Certificate.get(certificate.certificate, attr)
49+
end
50+
SumOfSquares.matrix_cone_type(::Type{Ideal{S, C}}) where {S, C} = SumOfSquares.matrix_cone_type(C)
51+
52+
SumOfSquares.Certificate.zero_basis(certificate::Ideal) = SumOfSquares.Certificate.zero_basis(certificate.certificate)
53+
SumOfSquares.Certificate.zero_basis_type(::Type{Ideal{S, C}}) where {S, C} = SumOfSquares.Certificate.zero_basis_type(C)

src/Certificate/sparse/monomial_sparsity.jl renamed to src/Certificate/Sparsity/monomial.jl

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const CEG = SumOfSquares.Certificate.ChordalExtensionGraph
1+
const CEG = ChordalExtensionGraph
22

33
"""
4-
struct MonomialSparsity{C<:CEG.AbstractCompletion} <: Sparsity
4+
struct Sparsity.Monomial{C<:CEG.AbstractCompletion} <: Sparsity.Pattern
55
completion::C
66
k::Int
77
use_all_monomials::Bool
@@ -23,11 +23,11 @@ arXiv preprint arXiv:1912.08899 (2020).
2323
*Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension*.
2424
arXiv preprint arXiv:2003.03210 (2020).
2525
"""
26-
struct MonomialSparsity{C<:CEG.AbstractCompletion} <: Sparsity
26+
struct Monomial{C<:CEG.AbstractCompletion} <: Pattern
2727
completion::C
2828
k::Int
2929
use_all_monomials::Bool
30-
function MonomialSparsity(
30+
function Monomial(
3131
completion::CEG.AbstractCompletion=CEG.ClusterCompletion(),
3232
k::Int=0,
3333
use_all_monomials::Bool=false,
@@ -122,7 +122,7 @@ function monomial_sparsity_iteration(P, completion, use_all_monomials::Bool, mon
122122
end
123123
_monovec(cliques::AbstractVector{<:MP.AbstractMonomial}) = MP.monovec(cliques)
124124
_monovec(cliques) = _monovec.(cliques)
125-
function sparsity(monos::AbstractVector{<:MP.AbstractMonomial}, sp::MonomialSparsity,
125+
function sparsity(monos::AbstractVector{<:MP.AbstractMonomial}, sp::Monomial,
126126
gram_monos::AbstractVector = SumOfSquares.Certificate.monomials_half_newton_polytope(monos, tuple()),
127127
args...)
128128
P = Set(monos)
@@ -149,21 +149,21 @@ function sparsity(monos::AbstractVector{<:MP.AbstractMonomial}, sp::MonomialSpar
149149
end
150150
# This also checks that it is indeed a monomial basis
151151
_monos(basis::MB.MonomialBasis) = basis.monomials
152-
function _gram_monos(vars, certificate::MaxDegree{CT, MB.MonomialBasis}) where CT
153-
return _monos(maxdegree_gram_basis(MB.MonomialBasis, vars, certificate.maxdegree))
152+
function _gram_monos(vars, certificate::SumOfSquares.Certificate.MaxDegree{CT, MB.MonomialBasis}) where CT
153+
return _monos(SumOfSquares.Certificate.maxdegree_gram_basis(MB.MonomialBasis, vars, certificate.maxdegree))
154154
end
155-
function sparsity(poly::MP.AbstractPolynomial, domain::BasicSemialgebraicSet, sp::MonomialSparsity, certificate::AbstractPreorderCertificate)
155+
function sparsity(poly::MP.AbstractPolynomial, domain::SemialgebraicSets.BasicSemialgebraicSet, sp::Monomial, certificate::SumOfSquares.Certificate.AbstractPreorderCertificate)
156156
gram_monos = _gram_monos(
157-
reduce((v, q) -> unique!(sort!([v..., variables(q)...], rev=true)),
158-
domain.p, init = variables(poly)),
159-
get(certificate, IdealCertificate())
157+
reduce((v, q) -> unique!(sort!([v..., MP.variables(q)...], rev=true)),
158+
domain.p, init = MP.variables(poly)),
159+
SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.IdealCertificate())
160160
)
161-
processed = get(certificate, PreprocessedDomain(), domain, poly)
161+
processed = SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.PreprocessedDomain(), domain, poly)
162162
multiplier_generator_monos = [
163-
(_monos(get(certificate, MultiplierBasis(), index, processed)),
164-
monomials(get(certificate, Generator(), index, processed)))
165-
for index in get(certificate, PreorderIndices(), processed)
163+
(_monos(SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.MultiplierBasis(), index, processed)),
164+
MP.monomials(SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.Generator(), index, processed)))
165+
for index in SumOfSquares.Certificate.get(certificate, SumOfSquares.Certificate.PreorderIndices(), processed)
166166
]
167-
cliques, multiplier_cliques = sparsity(monomials(poly), sp, gram_monos, multiplier_generator_monos)
167+
cliques, multiplier_cliques = sparsity(MP.monomials(poly), sp, gram_monos, multiplier_generator_monos)
168168
return MB.MonomialBasis.(cliques), [MB.MonomialBasis.(clique) for clique in multiplier_cliques]
169169
end

src/Certificate/Sparsity/preorder.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
struct Sparsity.Preorder{S <: Sparsity.Pattern, C <: SumOfSquares.Certificate.AbstractPreorderCertificate} <: SumOfSquares.Certificate.AbstractPreorderCertificate
3+
sparsity::S
4+
certificate::C
5+
end
6+
7+
Same certificate as `C` except that the Sum-of-Squares polynomials `σ_i`
8+
are modelled as a sum of Sum-of-Squares polynomials with smaller basis
9+
using the sparsity reduction `sparsity`.
10+
"""
11+
struct Preorder{S <: Pattern, C <: SumOfSquares.Certificate.AbstractPreorderCertificate} <: SumOfSquares.Certificate.AbstractPreorderCertificate
12+
sparsity::S
13+
certificate::C
14+
end
15+
16+
SumOfSquares.Certificate.get(certificate::Preorder, attr::SumOfSquares.Certificate.Cone) = SumOfSquares.Certificate.get(certificate.certificate, attr)
17+
18+
struct Domain{S, P, B}
19+
domain::S
20+
processed::P
21+
bases::Vector{Vector{B}}
22+
end
23+
24+
function SumOfSquares.Certificate.get(certificate::Preorder, attr::SumOfSquares.Certificate.PreprocessedDomain, domain::SemialgebraicSets.BasicSemialgebraicSet, p)
25+
basis, Preorder_bases = sparsity(p, domain, certificate.sparsity, certificate.certificate)
26+
return Domain(domain, SumOfSquares.Certificate.get(certificate.certificate, attr, domain, p), Preorder_bases)
27+
end
28+
29+
function SumOfSquares.Certificate.get(certificate::Preorder, attr::SumOfSquares.Certificate.PreorderIndices, domain::Domain)
30+
return SumOfSquares.Certificate.get(certificate.certificate, attr, domain.processed)
31+
end
32+
33+
function SumOfSquares.Certificate.get(::Preorder, ::SumOfSquares.Certificate.MultiplierBasis, index::SumOfSquares.Certificate.PreorderIndex, domain::Domain)
34+
return domain.bases[index.value]
35+
end
36+
function SumOfSquares.Certificate.get(::Type{Preorder{S, C}}, attr::SumOfSquares.Certificate.MultiplierBasisType) where {S, C}
37+
return Vector{SumOfSquares.Certificate.get(C, attr)}
38+
end
39+
40+
function SumOfSquares.Certificate.get(certificate::Preorder, attr::SumOfSquares.Certificate.Generator, index::SumOfSquares.Certificate.PreorderIndex, domain::Domain)
41+
return SumOfSquares.Certificate.get(certificate.certificate, attr, index, domain.processed)
42+
end
43+
44+
SumOfSquares.Certificate.get(certificate::Preorder, attr::SumOfSquares.Certificate.IdealCertificate) = Ideal(certificate.sparsity, SumOfSquares.Certificate.get(certificate.certificate, attr))
45+
SumOfSquares.Certificate.get(::Type{<:Preorder{S, C}}, attr::SumOfSquares.Certificate.IdealCertificate) where {S, C} = Ideal{S, SumOfSquares.Certificate.get(C, attr)}
46+
47+
SumOfSquares.matrix_cone_type(::Type{Preorder{S, C}}) where {S, C} = SumOfSquares.matrix_cone_type(C)

src/Certificate/sparse/sign.jl renamed to src/Certificate/Sparsity/sign.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""
2-
struct SignSymmetry <: Sparsity end
2+
struct SignSymmetry <: Sparsity.Pattern end
33
44
Sign symmetry as developed in [Section III.C, L09].
55
66
[L09] Lofberg, Johan.
77
*Pre-and post-processing sum-of-squares programs in practice*.
88
IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011.
99
"""
10-
struct SignSymmetry <: Sparsity end
10+
struct SignSymmetry <: Pattern end
1111

1212
function binary_exponent(exponents, ::Type{T}) where T
1313
cur = zero(T)

src/Certificate/sparse/variable_sparsity.jl renamed to src/Certificate/Sparsity/variable.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""
2-
struct VariableSparsity <: Sparsity end
2+
struct Sparsity.Variable <: Sparsity.Pattern end
33
44
Variable or correlative sparsity as developed in [WSMM06].
55
66
[WSMM06] Waki, Hayato, Sunyoung Kim, Masakazu Kojima, and Masakazu Muramatsu. "Sums of squares and semidefinite program relaxations for polynomial optimization problems with structured sparsity." SIAM Journal on Optimization 17, no. 1 (2006): 218-242.
77
"""
8-
struct VariableSparsity <: Sparsity end
8+
struct Variable <: Pattern end
99

1010
const CEG = ChordalExtensionGraph
1111

@@ -44,13 +44,13 @@ function chordal_csp_graph(poly::MP.APL, domain::AbstractBasicSemialgebraicSet)
4444
end
4545

4646
function sparsity(poly::MP.AbstractPolynomial, domain::BasicSemialgebraicSet,
47-
sp::VariableSparsity, certificate::Putinar)
47+
sp::Variable, certificate::SumOfSquares.Certificate.Putinar)
4848
H, cliques = chordal_csp_graph(poly, domain)
4949
function bases(q)
5050
return [
51-
maxdegree_gram_basis(certificate.basis, clique,
52-
multiplier_maxdegree(certificate.maxdegree, q))
53-
for clique in cliques if variables(q) clique
51+
SumOfSquares.Certificate.maxdegree_gram_basis(certificate.basis, clique,
52+
SumOfSquares.Certificate.multiplier_maxdegree(certificate.maxdegree, q))
53+
for clique in cliques if MP.variables(q) clique
5454
]
5555
end
5656
return bases(poly), map(bases, domain.p)

src/Certificate/Symmetry/wedderburn.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ function MP.polynomialtype(
5656
return MP.polynomialtype(PT, V)
5757
end
5858

59+
"""
60+
struct Symmetry.Ideal{C,GT,AT<:SymbolicWedderburn.Action} <: SumOfSquares.Certificate.AbstractIdealCertificate
61+
pattern::Symmetry.Pattern{GT,AT}
62+
certificate::C
63+
end
64+
65+
Same certificate as `certificate` except that the Sum-of-Squares polynomial `σ`
66+
is modelled as a sum of Sum-of-Squares polynomials with smaller bases
67+
using the Symbolic Wedderburn decomposition of the symmetry pattern specified
68+
by `pattern`.
69+
"""
5970
struct Ideal{C,GT,AT<:SymbolicWedderburn.Action} <: SumOfSquares.Certificate.AbstractIdealCertificate
6071
pattern::Pattern{GT,AT}
6172
certificate::C

0 commit comments

Comments
 (0)