Skip to content

Commit a6c2fc2

Browse files
authored
precise central point for relative entropy #857
2 parents e350ede + d0cc23f commit a6c2fc2

File tree

2 files changed

+30
-36
lines changed

2 files changed

+30
-36
lines changed

src/Cones/epirelentropy.jl

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ end
9090

9191
get_nu(cone::EpiRelEntropy) = cone.dim
9292

93-
function set_initial_point!(arr::AbstractVector, cone::EpiRelEntropy)
94-
(arr[1], v, w) = get_central_ray_epirelentropy(cone.w_dim)
93+
function set_initial_point!(arr::AbstractVector, cone::EpiRelEntropy{T}) where {T}
94+
(arr[1], v, w) = get_central_ray_epirelentropy(T(cone.w_dim))
9595
@views arr[cone.v_idxs] .= v
9696
@views arr[cone.w_idxs] .= w
9797
return arr
@@ -385,39 +385,33 @@ function inv_hess_nz_idxs_col_tril(cone::EpiRelEntropy, j::Int)
385385
return (j == 1 ? (1:(cone.dim)) : (j <= (1 + cone.w_dim) ? [j, j + cone.w_dim] : [j]))
386386
end
387387

388-
# see analysis in
389-
# https://github.com/lkapelevich/HypatiaSupplements.jl/tree/master/centralpoints
390-
function get_central_ray_epirelentropy(w_dim::Int)
391-
if w_dim <= 10
392-
return central_rays_epirelentropy[w_dim, :]
393-
end
394-
# use nonlinear fit for higher dimensions
395-
rtw_dim = sqrt(w_dim)
396-
if w_dim <= 20
397-
u = 1.2023 / rtw_dim - 0.015
398-
v = 0.432 / rtw_dim + 1.0125
399-
w = -0.3057 / rtw_dim + 0.972
400-
elseif w_dim <= 300
401-
u = 1.1513 / rtw_dim - 0.0069
402-
v = 0.4873 / rtw_dim + 1.0008
403-
w = -0.4247 / rtw_dim + 0.9961
404-
else # use asymptotic expansion for the highest dimensions
405-
u = 1 / rtw_dim + 0.75 / w_dim
406-
v = 1 + 0.5 / rtw_dim
407-
w = 1 - 0.5 / rtw_dim + 0.25 / w_dim
388+
function get_central_ray_epirelentropy(d::T) where {T <: AbstractFloat}
389+
w2 = (1 - 1 / sqrt(4d) + 1 / 4d)^2
390+
tol = sqrt(eps(T))
391+
maxiter = 2ceil(log2(-log2(tol)))
392+
counter = 0
393+
while counter < maxiter
394+
counter += 1
395+
step = newton_ratio(w2, d)
396+
w2 -= step
397+
if abs(step) < tol
398+
break
399+
end
408400
end
409-
return [u, v, w]
401+
counter == maxiter && error("Failed to compute initial point.")
402+
w = w2
403+
rt = sqrt(w2 + d * w2 * (1 - w2) + d^2 * w2^2 / 4)
404+
v = sqrt(1 - d * w2 / 2 + rt)
405+
D = d * w * log(w / v)
406+
u = D / 2 + sqrt(1 + D^2 / 4)
407+
return u, v, w
410408
end
411409

412-
const central_rays_epirelentropy = [
413-
0.827838399 1.290927714 0.805102005
414-
0.708612491 1.256859155 0.818070438
415-
0.622618845 1.231401008 0.829317079
416-
0.558111266 1.211710888 0.838978357
417-
0.508038611 1.196018952 0.847300431
418-
0.468039614 1.183194753 0.854521307
419-
0.435316653 1.172492397 0.860840992
420-
0.408009282 1.163403374 0.866420017
421-
0.38483862 1.155570329 0.871385499
422-
0.364899122 1.148735192 0.875838068
423-
]
410+
function newton_ratio(w2, d)
411+
rt = sqrt(w2 + d * w2 * (1 - w2) + d^2 * w2^2 / 4)
412+
v2 = 1 - d * w2 / 2 + rt
413+
f = 1 + (w2 - 1) / (v2 - 1) + log(w2 / v2) / 2
414+
dv2 = -d / 2 + (1 + d * (1 - 2w2) + d^2 * w2 / 2) / 2rt
415+
df = 1 / (v2 - 1) - (w2 - 1) * dv2 / (v2 - 1)^2 + (1 / w2 - dv2 / v2) / 2
416+
return f / df
417+
end

src/Cones/epitrrelentropytri.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ function set_initial_point!(
162162
incr = (cone.is_complex ? 2 : 1)
163163
arr .= 0
164164
# at the initial point V and W are diagonal, equivalent to epirelentropy
165-
(arr[1], v, w) = get_central_ray_epirelentropy(cone.d)
165+
(arr[1], v, w) = get_central_ray_epirelentropy(T(cone.d))
166166
k = 1
167167
for i in 1:(cone.d)
168168
arr[1 + k] = v

0 commit comments

Comments
 (0)