|
90 | 90 |
|
91 | 91 | get_nu(cone::EpiRelEntropy) = cone.dim
|
92 | 92 |
|
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)) |
95 | 95 | @views arr[cone.v_idxs] .= v
|
96 | 96 | @views arr[cone.w_idxs] .= w
|
97 | 97 | return arr
|
@@ -385,39 +385,33 @@ function inv_hess_nz_idxs_col_tril(cone::EpiRelEntropy, j::Int)
|
385 | 385 | return (j == 1 ? (1:(cone.dim)) : (j <= (1 + cone.w_dim) ? [j, j + cone.w_dim] : [j]))
|
386 | 386 | end
|
387 | 387 |
|
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 |
408 | 400 | 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 |
410 | 408 | end
|
411 | 409 |
|
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 |
0 commit comments