1
0
mirror of https://github.com/kalmarek/PropertyT.jl.git synced 2024-11-19 07:20:28 +01:00

make augmented compute_sos fast

This commit is contained in:
Marek Kaluba 2022-11-14 19:45:41 +01:00
parent 65286e09d2
commit 227e82d551
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
2 changed files with 40 additions and 87 deletions

View File

@ -5,80 +5,50 @@ function augment_columns!(Q::AbstractMatrix)
return Q return Q
end end
function _fma_SOS_thr!( function __sos_via_sqr!(
result::AbstractVector{T}, res::StarAlgebras.AlgebraElement,
mstructure::AbstractMatrix{<:Integer}, P::AbstractMatrix;
Q::AbstractMatrix{T}, augmented::Bool
acc_matrix=zeros(T, size(mstructure)...), )
) where {T} StarAlgebras.zero!(res)
A = parent(res)
b = basis(A)
@assert size(A.mstructure) == size(P)
e = b[one(b[1])]
s1, s2 = size(mstructure) for i in axes(A.mstructure, 1)
x = StarAlgebras._istwisted(A.mstructure) ? StarAlgebras.star(b[i]) : b[i]
@inbounds for k = 1:s2 for j in axes(A.mstructure, 2)
let k = k, s1 = s1, s2 = s2, Q = Q, acc_matrix = acc_matrix p = P[i, j]
Threads.@threads for j = 1:s2 xy = b[A.mstructure[i, j]]
for i = 1:s1 # either result += P[x,y]*(x*y)
@inbounds acc_matrix[i, j] = res[xy] += p
muladd(Q[i, k], Q[j, k], acc_matrix[i, j]) if augmented
end # or result += P[x,y]*(1-x)*(1-y) == P[x,y]*(2-x-y+xy)
y = b[j]
res[e] += p
res[x] -= p
res[y] -= p
end end
end end
end end
@inbounds for j = 1:s2 return res
for i = 1:s1
result[mstructure[i, j]] += acc_matrix[i, j]
end
end
return result
end end
function _cnstr_sos!(res::StarAlgebras.AlgebraElement, Q::AbstractMatrix, cnstrs) function __sos_via_cnstr!(res::StarAlgebras.AlgebraElement, ::AbstractMatrix, cnstrs)
StarAlgebras.zero!(res) StarAlgebras.zero!(res)
= Q' * Q
for (g, A_g) in cnstrs for (g, A_g) in cnstrs
res[g] = dot(A_g, ) res[g] = dot(A_g, )
end end
return res return res
end end
function _augmented_sos!(res::StarAlgebras.AlgebraElement, Q::AbstractMatrix)
A = parent(res)
StarAlgebras.zero!(res)
= Q' * Q
N = LinearAlgebra.checksquare(A.mstructure)
augmented_basis = [A(1) - A(b) for b in @view basis(A)[1:N]]
tmp = zero(res)
for (j, y) in enumerate(augmented_basis)
for (i, x) in enumerate(augmented_basis)
# res += Q²[i, j] * x * y
StarAlgebras.mul!(tmp, x, y)
StarAlgebras.mul!(tmp, tmp, [i, j])
StarAlgebras.add!(res, res, tmp)
end
end
return res
end
function compute_sos(A::StarAlgebras.StarAlgebra, Q::AbstractMatrix; augmented::Bool) function compute_sos(A::StarAlgebras.StarAlgebra, Q::AbstractMatrix; augmented::Bool)
if augmented = Q' * Q
z = zeros(eltype(Q), length(basis(A))) res = StarAlgebras.AlgebraElement(zeros(eltype(), length(basis(A))), A)
res = StarAlgebras.AlgebraElement(z, A) res = __sos_via_sqr!(res, , augmented=augmented)
return _augmented_sos!(res, Q) return res
cnstrs = constraints(basis(A), A.mstructure; augmented=true)
return _cnstr_sos!(res, Q, cnstrs)
else
@assert size(A.mstructure) == size(Q)
z = zeros(eltype(Q), length(basis(A)))
_fma_SOS_thr!(z, A.mstructure, Q)
return StarAlgebras.AlgebraElement(z, A)
end
end end
function sufficient_λ(residual::StarAlgebras.AlgebraElement, λ; halfradius) function sufficient_λ(residual::StarAlgebras.AlgebraElement, λ; halfradius)
@ -159,7 +129,7 @@ function certify_solution(
true, compute_sos(parent(elt), Q_int, augmented=augmented) true, compute_sos(parent(elt), Q_int, augmented=augmented)
end end
@info "Checking in $(eltype(sos_int)) arithmetic with" λ @info "Checking in $(eltype(sos_int)) arithmetic with" λ_int
λ_certified = λ_certified =
sufficient_λ(elt, orderunit, λ_int, sos_int, halfradius=halfradius) sufficient_λ(elt, orderunit, λ_int, sos_int, halfradius=halfradius)

View File

@ -6,37 +6,20 @@ function check_positivity(elt, unit, wd; upper_bound=Inf, halfradius=2, optimize
@time status, _ = PropertyT.solve(sos_problem, optimizer) @time status, _ = PropertyT.solve(sos_problem, optimizer)
Q = let Ps = Ps Q = let Ps = Ps
flPs = [real.(sqrt(JuMP.value.(P))) for P in Ps] Qs = [real.(sqrt(JuMP.value.(P))) for P in Ps]
PropertyT.reconstruct(flPs, wd) PropertyT.reconstruct(Qs, wd)
end end
λ = JuMP.value(sos_problem[]) λ = JuMP.value(sos_problem[])
sos = let RG = parent(elt), Q = Q certified, λ_cert = PropertyT.certify_solution(
z = zeros(eltype(Q), length(basis(RG))) elt,
res = AlgebraElement(z, RG) unit,
cnstrs = PropertyT.constraints(basis(RG), RG.mstructure, augmented=true) λ,
PropertyT._cnstr_sos!(res, Q, cnstrs) Q,
end halfradius=2
)
residual = elt - λ * unit - sos return status, certified, λ_cert
λ_fl = PropertyT.sufficient_λ(residual, λ, halfradius=2)
λ_fl < 0 && return status, false, λ_fl
sos = let RG = parent(elt), Q = [PropertyT.IntervalArithmetic.@interval(q) for q in Q]
z = zeros(eltype(Q), length(basis(RG)))
res = AlgebraElement(z, RG)
cnstrs = PropertyT.constraints(basis(RG), RG.mstructure, augmented=true)
PropertyT._cnstr_sos!(res, Q, cnstrs)
end
λ_int = PropertyT.IntervalArithmetic.@interval(λ)
residual_int = elt - λ_int * unit - sos
λ_int = PropertyT.sufficient_λ(residual_int, λ_int, halfradius=2)
return status, λ_int > 0, PropertyT.IntervalArithmetic.inf(λ_int)
end end
@testset "1712.07167 Examples" begin @testset "1712.07167 Examples" begin