PropertyT.jl/src/certify.jl

146 lines
3.9 KiB
Julia
Raw Normal View History

2022-11-07 16:01:35 +01:00
function augment_columns!(Q::AbstractMatrix)
for c in eachcol(Q)
c .-= sum(c) ./ length(c)
end
return Q
end
2022-11-14 19:45:41 +01:00
function __sos_via_sqr!(
res::StarAlgebras.AlgebraElement,
P::AbstractMatrix;
2023-03-19 20:26:42 +01:00
augmented::Bool,
id = (b = basis(parent(res)); b[one(first(b))]),
2022-11-14 19:45:41 +01:00
)
A = parent(res)
2023-03-19 20:26:42 +01:00
mstr = A.mstructure
@assert size(mstr) == size(P)
2022-11-14 19:45:41 +01:00
2023-03-19 20:26:42 +01:00
StarAlgebras.zero!(res)
for j in axes(mstr, 2)
for i in axes(mstr, 1)
2022-11-14 19:45:41 +01:00
p = P[i, j]
2023-03-19 20:26:42 +01:00
x_star_y = mstr[-i, j]
res[x_star_y] += p
# either result += P[x,y]*(x'*y)
2022-11-14 19:45:41 +01:00
if augmented
2023-03-19 20:26:42 +01:00
# or result += P[x,y]*(1-x)'*(1-y) == P[x,y]*(1-x'-y+x'y)
res[id] += p
x_star, y = mstr[-i, id], j
res[x_star] -= p
2022-11-14 19:45:41 +01:00
res[y] -= p
2022-11-07 16:01:35 +01:00
end
end
end
2022-11-14 19:45:41 +01:00
return res
2022-11-07 16:01:35 +01:00
end
2023-03-19 20:33:28 +01:00
function __sos_via_cnstr!(
res::StarAlgebras.AlgebraElement,
::AbstractMatrix,
cnstrs,
)
2022-11-07 16:01:35 +01:00
StarAlgebras.zero!(res)
for (g, A_g) in cnstrs
res[g] = dot(A_g, )
end
return res
end
2023-03-19 20:33:28 +01:00
function compute_sos(
A::StarAlgebras.StarAlgebra,
Q::AbstractMatrix;
augmented::Bool,
)
2022-11-07 16:01:35 +01:00
= Q' * Q
2022-11-14 19:45:41 +01:00
res = StarAlgebras.AlgebraElement(zeros(eltype(), length(basis(A))), A)
2023-03-19 20:33:28 +01:00
res = __sos_via_sqr!(res, ; augmented = augmented)
2022-11-07 16:01:35 +01:00
return res
end
2022-11-07 17:01:06 +01:00
function sufficient_λ(residual::StarAlgebras.AlgebraElement, λ; halfradius)
2022-11-07 16:01:35 +01:00
L1_norm = norm(residual, 1)
suff_λ = λ - 2.0^(2ceil(log2(halfradius))) * L1_norm
eq_sign = let T = eltype(residual)
if T <: Interval
""
elseif T <: Union{Rational,Integer}
"="
else # if T <: AbstractFloat
""
end
end
info_strs = [
"Numerical metrics of the obtained SOS:",
2022-11-07 17:01:06 +01:00
"ɛ(elt - λu - ∑ξᵢ*ξᵢ) $eq_sign $(StarAlgebras.aug(residual))",
2022-11-07 16:01:35 +01:00
"‖elt - λu - ∑ξᵢ*ξᵢ‖₁ $eq_sign $(L1_norm)",
" λ $eq_sign $suff_λ",
]
@info join(info_strs, "\n")
return suff_λ
end
function sufficient_λ(
2022-11-07 17:01:06 +01:00
elt::StarAlgebras.AlgebraElement,
order_unit::StarAlgebras.AlgebraElement,
2022-11-07 16:01:35 +01:00
λ,
2022-11-07 17:01:06 +01:00
sos::StarAlgebras.AlgebraElement;
2023-03-19 20:33:28 +01:00
halfradius,
2022-11-07 16:01:35 +01:00
)
@assert parent(elt) === parent(order_unit) == parent(sos)
residual = (elt - λ * order_unit) - sos
2023-03-19 20:33:28 +01:00
return sufficient_λ(residual, λ; halfradius = halfradius)
2022-11-07 16:01:35 +01:00
end
function certify_solution(
2022-11-07 17:01:06 +01:00
elt::StarAlgebras.AlgebraElement,
orderunit::StarAlgebras.AlgebraElement,
2022-11-07 16:01:35 +01:00
λ,
Q::AbstractMatrix{<:AbstractFloat};
halfradius,
2023-03-19 20:33:28 +01:00
augmented = iszero(StarAlgebras.aug(elt)) &&
iszero(StarAlgebras.aug(orderunit)),
2022-11-07 16:01:35 +01:00
)
2023-03-19 20:33:28 +01:00
should_we_augment =
!augmented && StarAlgebras.aug(elt) == StarAlgebras.aug(orderunit) == 0
2022-11-07 16:01:35 +01:00
Q = should_we_augment ? augment_columns!(Q) : Q
2023-03-19 20:33:28 +01:00
@time sos = compute_sos(parent(elt), Q; augmented = augmented)
2022-11-07 16:01:35 +01:00
@info "Checking in $(eltype(sos)) arithmetic with" λ
2023-03-19 20:33:28 +01:00
λ_flpoint = sufficient_λ(elt, orderunit, λ, sos; halfradius = halfradius)
2022-11-07 16:01:35 +01:00
if λ_flpoint 0
return false, λ_flpoint
end
λ_int = @interval(λ)
Q_int = [@interval(q) for q in Q]
check, sos_int = @time if should_we_augment
@info("Projecting columns of Q to the augmentation ideal...")
Q_int = augment_columns!(Q_int)
@info "Checking that sum of every column contains 0.0..."
check_augmented = all(0 sum(c) for c in eachcol(Q_int))
check_augmented || @error(
"Augmentation failed! The following numbers are not certified!"
)
2023-03-19 20:33:28 +01:00
sos_int = compute_sos(parent(elt), Q_int; augmented = augmented)
2022-11-07 16:01:35 +01:00
check_augmented, sos_int
else
2023-03-19 20:33:28 +01:00
true, compute_sos(parent(elt), Q_int; augmented = augmented)
2022-11-07 16:01:35 +01:00
end
2022-11-14 19:45:41 +01:00
@info "Checking in $(eltype(sos_int)) arithmetic with" λ_int
2022-11-07 16:01:35 +01:00
λ_certified =
2023-03-19 20:33:28 +01:00
sufficient_λ(elt, orderunit, λ_int, sos_int; halfradius = halfradius)
2022-11-07 16:01:35 +01:00
2023-03-19 20:33:28 +01:00
return check && inf(λ_certified) > 0.0, λ_certified
2022-11-07 16:01:35 +01:00
end