-
Notifications
You must be signed in to change notification settings - Fork 7
/
zero_polynomial_in_algebraic_set_bridge.jl
81 lines (72 loc) · 4.54 KB
/
zero_polynomial_in_algebraic_set_bridge.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
using LinearAlgebra
struct ZeroPolynomialInAlgebraicSetBridge{T, F <: MOI.AbstractVectorFunction,
BT <: AbstractPolynomialBasis,
DT <: AbstractSemialgebraicSet,
MT <: AbstractMonomial,
MVT <: AbstractVector{MT}} <: MOIB.AbstractBridge
zero_constraint::MOI.ConstraintIndex{F, ZeroPolynomialSet{FullSpace, BT, MT, MVT}}
domain::DT
monomials::MVT
end
function ZeroPolynomialInAlgebraicSetBridge{T, F, BT, DT, MT, MVT}(model::MOI.ModelLike,
f::MOI.AbstractVectorFunction,
s::ZeroPolynomialSet{<:AbstractAlgebraicSet}) where {T, F <: MOI.AbstractVectorFunction,
BT <: AbstractPolynomialBasis,
DT <: AbstractSemialgebraicSet,
MT <: AbstractMonomial,
MVT <: AbstractVector{MT}}
p = polynomial(collect(MOI.Utilities.eachscalar(f)), s.monomials)
# FIXME convert needed because the coefficient type of `r` is `Any` otherwise if `domain` is `AlgebraicSet`
r = convert(typeof(p), rem(p, ideal(s.domain)))
zero_constraint = MOI.add_constraint(model, MOIU.vectorize(coefficients(r)),
ZeroPolynomialSet(FullSpace(), s.basis,
monomials(r)))
return ZeroPolynomialInAlgebraicSetBridge{T, F, BT, DT, MT, MVT}(zero_constraint, s.domain, s.monomials)
end
function MOI.supports_constraint(::Type{ZeroPolynomialInAlgebraicSetBridge{T}},
::Type{<:MOI.AbstractVectorFunction},
::Type{<:ZeroPolynomialSet{<:AbstractAlgebraicSet}}) where T
return true
end
function MOIB.added_constraint_types(::Type{<:ZeroPolynomialInAlgebraicSetBridge{T, F, BT, DT, MT, MVT}}) where {T, F, BT, DT, MT, MVT}
return [(F, ZeroPolynomialSet{FullSpace, BT, MT, MVT})]
end
function MOIB.concrete_bridge_type(::Type{<:ZeroPolynomialInAlgebraicSetBridge{T}},
F::Type{<:MOI.AbstractVectorFunction},
::Type{<:ZeroPolynomialSet{DT, BT, MT, MVT}}) where {T, BT, DT<:AbstractAlgebraicSet, MT, MVT}
G = MOI.Utilities.promote_operation(-, T, F, F)
return ZeroPolynomialInAlgebraicSetBridge{T, G, BT, DT, MT, MVT}
end
# Attributes, Bridge acting as an model
function MOI.get(::ZeroPolynomialInAlgebraicSetBridge{T, F, BT, DT, MT, MVT},
::MOI.NumberOfConstraints{F, ZeroPolynomialSet{FullSpace, BT, MT, MVT}}) where {T, F, BT, DT, MT, MVT}
return 1
end
function MOI.get(b::ZeroPolynomialInAlgebraicSetBridge{T, F, BT, DT, MT, MVT},
::MOI.ListOfConstraintIndices{F, ZeroPolynomialSet{FullSpace, BT, MT, MVT}}) where {T, F, BT, DT, MT, MVT}
return [b.zero_constraint]
end
# Indices
function MOI.delete(model::MOI.ModelLike, c::ZeroPolynomialInAlgebraicSetBridge)
MOI.delete(model, c.zero_constraint)
end
# Attributes, Bridge acting as a constraint
# TODO ConstraintPrimal
# Let A be the linear map corresponding to A(p) = rem(p, ideal(set.domain))
# We want to compute A*(μ) (where A* is the conjugate of A); see
# slide 9 of https://www.youtube.com/watch?v=C8dHxJCUHYw.
# That is, for every monomial of the basis `mono`, we want to compute
# `⟨mono, A*(μ)⟩`. By definition of the conjugacy, we have `⟨mono, A*(μ)⟩ = ⟨A(mono), μ⟩`
# so we can compute compute it by `⟨rem(mono, ideal(set.domain)), μ⟩`
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintDual,
bridge::ZeroPolynomialInAlgebraicSetBridge)
dual = MOI.get(model, attr, bridge.zero_constraint)
set = MOI.get(model, MOI.ConstraintSet(), bridge.zero_constraint)
μ = measure(dual, set.monomials)
I = ideal(bridge.domain)
return [dot(rem(mono, I), μ) for mono in bridge.monomials]
end
function MOI.get(model::MOI.ModelLike, attr::MomentsAttribute,
bridge::ZeroPolynomialInAlgebraicSetBridge)
return MOI.get(model, attr, bridge.zero_constraint)
end