From 7bf6e952b53699977f5091a78f0f9f48f7b359c5 Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Tue, 9 Nov 2021 10:13:59 +0100 Subject: Generalized code to easily allow mixed p-spins. --- langevin.cpp | 95 ++++++++++-------------------------------------------------- 1 file changed, 16 insertions(+), 79 deletions(-) (limited to 'langevin.cpp') diff --git a/langevin.cpp b/langevin.cpp index 86aeb9e..dc3d07d 100644 --- a/langevin.cpp +++ b/langevin.cpp @@ -27,63 +27,6 @@ using ComplexTensor = Tensor; using Rng = randutils::random_generator; -std::list> saddlesCloserThan(const std::unordered_map& saddles, Real δ) { - std::list> pairs; - - for (auto it1 = saddles.begin(); it1 != saddles.end(); it1++) { - for (auto it2 = std::next(it1); it2 != saddles.end(); it2++) { - if ((it1->second - it2->second).norm() < δ) { - pairs.push_back({it1->second, it2->second}); - } - } - } - - return pairs; -} - -template -std::tuple matchImaginaryEnergies(const ComplexTensor& J0, const ComplexVector& z10, const ComplexVector& z20, Real ε, Real Δ, Generator& r) { - Real σ = sqrt(factorial(p) / (Real(2) * pow(z10.size(), p - 1))); - complex_normal_distribution dJ(0, σ, 0); - - ComplexTensor J = J0; - ComplexVector z1, z2; - Real ΔH = abs(imag(getHamiltonian(J, z10) - getHamiltonian(J, z20))) / z10.size(); - Real γ = ΔH; - - std::function)> perturbJ = - [&γ, &dJ, &r] (ComplexTensor& JJ, std::array ind) { - Complex Ji = getJ(JJ, ind); - setJ(JJ, ind, Ji + γ * dJ(r.engine())); - }; - - while (ΔH > ε) { - ComplexTensor Jp = J; - iterateOver(Jp, perturbJ); - - try { - z1 = findSaddle(Jp, z10, Δ); - z2 = findSaddle(Jp, z20, Δ); - - Real Δz = (z1 - z2).norm(); - - if (Δz > 1e-2) { - Real ΔHNew = abs(imag(getHamiltonian(Jp, z1) - getHamiltonian(Jp, z2))) / z1.size(); - - if (ΔHNew < ΔH) { - J = Jp; - ΔH = ΔHNew; - γ = ΔH; - - std::cerr << "Match imaginary energies: Found couplings with ΔH = " << ΔH << std::endl; - } - } - } catch (std::exception& e) {} - } - - return {J, z1, z2}; -} - int main(int argc, char* argv[]) { // model parameters unsigned N = 10; // number of spins @@ -143,24 +86,29 @@ int main(int argc, char* argv[]) { Rng r; - Tensor ReJ = generateCouplings(N, std::normal_distribution(0, σ), r.engine()); + pSpinModel pSpin; + + std::get<0>(pSpin.Js) = generateCouplings(N, std::normal_distribution(0, σ), r.engine()); std::normal_distribution Red(0, 1); - RealVector zMin = randomMinimum(ReJ, Red, r, ε); - auto [Hr, dHr, ddHr] = hamGradHess(ReJ, zMin); + RealVector zMin = randomMinimum(pSpin, Red, r, ε); + Real Hr; + RealVector dHr; + RealMatrix ddHr; + std::tie(Hr, dHr, ddHr, std::ignore) = pSpin.hamGradHess(zMin); Eigen::EigenSolver> eigenS(ddHr - (dHr * zMin.transpose() + zMin.dot(dHr) * Matrix::Identity(zMin.size(), zMin.size()) + (ddHr * zMin) * zMin.transpose()) / (Real)zMin.size() + 2.0 * zMin * zMin.transpose()); std::cout << eigenS.eigenvalues().transpose() << std::endl; for (unsigned i = 0; i < N; i++) { RealVector zNew = normalize(zMin + 0.01 * eigenS.eigenvectors().col(i).real()); - std::cout << getHamiltonian(ReJ, zNew) - Hr << " " << real(eigenS.eigenvectors().col(i).dot(zMin)) << std::endl; + std::cout << pSpin.getHamiltonian(zNew) - Hr << " " << real(eigenS.eigenvectors().col(i).dot(zMin)) << std::endl; } std::cout << std::endl; getchar(); complex_normal_distribution d(0, 1, 0); - ComplexTensor J = ReJ.cast(); + pSpinModel complexPSpin = pSpin.cast();; ComplexVector zSaddle = zMin.cast(); ComplexVector zSaddleNext; @@ -168,7 +116,7 @@ int main(int argc, char* argv[]) { while (!foundSaddle) { ComplexVector z0 = normalize(zSaddle + δ * randomVector(N, d, r.engine())); try { - zSaddleNext = findSaddle(J, z0, ε); + zSaddleNext = findSaddle(complexPSpin, z0, ε); Real saddleDistance = (zSaddleNext - zSaddle).norm(); if (saddleDistance / N > 1e-2) { std::cout << saddleDistance << std::endl; @@ -177,27 +125,16 @@ int main(int argc, char* argv[]) { } catch (std::exception& e) {} } - auto [H1, dH1, ddH1] = hamGradHess(J, zSaddle); - auto [H2, dH2, ddH2] = hamGradHess(J, zSaddleNext); - - Eigen::ComplexEigenSolver ces; - ces.compute(ddH1); + Complex H1 = complexPSpin.getHamiltonian(zSaddle); + Complex H2 = complexPSpin.getHamiltonian(zSaddleNext); Real φ = atan2( H2.imag() - H1.imag(), H1.real() - H2.real()); std::cerr << (zSaddle - zSaddleNext).norm() / (Real)N << " " << φ << " " << H1 * exp(Complex(0, φ)) << " " << H2 * exp(Complex(0, φ)) << std::endl; - Real smallestNorm = std::numeric_limits::infinity(); - for (Complex z : ces.eigenvalues()) { - if (norm(z) < smallestNorm) { - smallestNorm = norm(z); - } - } - std::cerr << smallestNorm << std::endl; - getchar(); - J = exp(Complex(0, φ)) * J; + std::get<0>(complexPSpin.Js) = exp(Complex(0, φ)) * std::get<0>(complexPSpin.Js); - Cord test(J, zSaddle, zSaddleNext, 3); - test.relaxNewton(J, 10, 1, 1e4); + Cord test(complexPSpin, zSaddle, zSaddleNext, 3); + test.relaxNewton(10, 1, 1e4); std::cout << test.z0.transpose() << std::endl; std::cout << test.z1.transpose() << std::endl; -- cgit v1.2.3-70-g09d2