From 5715f5fbd77b86edbf8ff78f511fe88870e7b37e Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Mon, 8 Nov 2021 15:45:57 +0100 Subject: Better method for finding saddles. --- dynamics.hpp | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'dynamics.hpp') diff --git a/dynamics.hpp b/dynamics.hpp index 561714e..0597f35 100644 --- a/dynamics.hpp +++ b/dynamics.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include "p-spin.hpp" #include "stereographic.hpp" @@ -45,35 +47,39 @@ std::tuple> gradientDescent(const Tensor& J, con template Vector findSaddle(const Tensor& J, const Vector& z0, Real ε, Real δW = 2, Real γ0 = 1, Real δγ = 2) { Vector z = z0; - Vector ζ = euclideanToStereographic(z); - - Real W; - std::tie(W, std::ignore) = WdW(J, z); Vector dH; Matrix ddH; - std::tie(std::ignore, dH, ddH) = stereographicHamGradHess(J, ζ, z); + std::tie(std::ignore, dH, ddH) = hamGradHess(J, z); - while (W > ε) { - // ddH is complex symmetric, which is (almost always) invertible, so a - // partial pivot LU decomposition can be used. - Vector dζ = ddH.partialPivLu().solve(dH); - Vector ζNew = ζ - dζ; - Vector zNew = stereographicToEuclidean(ζNew); + Scalar zz = z.transpose() * z; + Vector ż = zDot(z, dH) + z * (zz - (Real)z.size()); + Matrix dż = dzDot(z, dH) + Matrix::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose(); + Matrix dżc = dzDotConjugate(z, dH, ddH); - Real WNew; - std::tie(WNew, std::ignore) = WdW(J, zNew); + Vector b(2 * z.size()); + Matrix M(2 * z.size(), 2 * z.size()); - if (WNew < W) { // If Newton's step lowered the objective, accept it! - ζ = ζNew; - z = zNew; - W = WNew; - } else { // Otherwise, do gradient descent until W is a factor δW smaller. - std::tie(W, z) = gradientDescent(J, z, W / δW, γ0, δγ); - ζ = euclideanToStereographic(z); - } + b << ż.conjugate(), ż; + M << dż.conjugate(), dżc, dżc.conjugate(), dż; + + while (ż.norm() > ε) { + Vector dz = M.partialPivLu().solve(b).tail(z.size()); + dz -= z.conjugate().dot(dz) / z.squaredNorm() * z.conjugate(); + z = normalize(z - dz); + + std::cout << "error : " << z.transpose() * z << " "<< ż.norm() << " " << dz.norm() << std::endl; + getchar(); + + std::tie(std::ignore, dH, ddH) = hamGradHess(J, z); + + zz = z.transpose() * z; + ż = zDot(z, dH) + z * (zz - (Real)z.size()); + dż = dzDot(z, dH) + Matrix::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose(); + dżc = dzDotConjugate(z, dH, ddH); - std::tie(std::ignore, dH, ddH) = stereographicHamGradHess(J, ζ, z); + b << ż.conjugate(), ż; + M << dż.conjugate(), dżc, dżc.conjugate(), dż; } return z; -- cgit v1.2.3-54-g00ecf