#pragma once #include #include #include #include "p-spin.hpp" template Vector findMinimum(const pSpinModel& M, const Vector& z0, Real ε) { Vector z = z0; Real λ = 100; Real H; Vector dH; Matrix ddH; std::tie(H, dH, ddH, std::ignore) = M.hamGradHess(z); Vector g = dH - z.dot(dH) * z / (Real)z.size(); Matrix m = ddH - (dH * z.transpose() + z.dot(dH) * Matrix::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + 2.0 * z * z.transpose(); while (g.norm() / z.size() > ε && λ < 1e8) { Vector dz = (m + λ * (Matrix)abs(m.diagonal().array()).matrix().asDiagonal()).partialPivLu().solve(g); dz -= z.dot(dz) * z / (Real)z.size(); Vector zNew = normalize(z - dz); Real HNew; Vector dHNew; Matrix ddHNew; std::tie(HNew, dHNew, ddHNew, std::ignore) = M.hamGradHess(zNew); if (HNew * 1.0001 <= H) { z = zNew; H = HNew; dH = dHNew; ddH = ddHNew; g = dH - z.dot(dH) * z / (Real)z.size(); m = ddH - (dH * z.transpose() + z.dot(dH) * Matrix::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + 2.0 * z * z.transpose(); λ /= 2; } else { λ *= 1.5; } } return z; } template Vector findSaddle(const pSpinModel& M, const Vector& z0, Real ε) { Vector z = z0; Vector dH; Matrix ddH; std::tie(std::ignore, dH, ddH, std::ignore) = M.hamGradHess(z); Scalar zz = z.transpose() * z; Vector g = dH - (z.transpose() * dH) * z / (Real)z.size() + z * (zz - (Real)z.size()); Matrix m = ddH - (dH * z.transpose() + (z.transpose() * dH) * Matrix::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + Matrix::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose(); while (g.norm() / z.size() > ε) { Vector dz = m.partialPivLu().solve(g); dz -= z.conjugate().dot(dz) / z.squaredNorm() * z.conjugate(); z = normalize(z - dz); std::tie(std::ignore, dH, ddH, std::ignore) = M.hamGradHess(z); zz = z.transpose() * z; g = dH - (z.transpose() * dH) * z / (Real)z.size() + z * (zz - (Real)z.size()); m = ddH - (dH * z.transpose() + (z.transpose() * dH) * Matrix::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + Matrix::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose(); } return z; } template Vector randomVector(unsigned N, Distribution d, Generator& r) { Vector z(N); for (unsigned i = 0; i < N; i++) { z(i) = d(r); } return z; } template Vector randomMinimum(const pSpinModel& M, Distribution d, Generator& r, Real ε) { Vector zSaddle; bool foundSaddle = false; while (!foundSaddle) { Vector z0 = normalize(randomVector(M.dimension(), d, r)); try { zSaddle = findMinimum(M, z0, ε); foundSaddle = true; } catch (std::exception& e) {} } return zSaddle; } template Vector randomSaddle(const pSpinModel& M, Distribution d, Generator& r, Real ε) { Vector zSaddle; bool foundSaddle = false; while (!foundSaddle) { Vector z0 = normalize(randomVector(M.dimension(), d, r)); try { zSaddle = findSaddle(M, z0, ε); foundSaddle = true; } catch (std::exception& e) {} } return zSaddle; }