summaryrefslogtreecommitdiff
path: root/dynamics.hpp
blob: e578cdba1d6edf97bbe7155a469f56efadd087c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once

#include <exception>
#include <eigen3/Eigen/LU>
#include <random>

#include "p-spin.hpp"

template <class Real, int ...ps>
Vector<Real> findMinimum(const pSpinModel<Real, ps...>& M, const Vector<Real>& z0, Real ε) {
  Vector<Real> z = z0;
  Real λ = 100;

  Real H;
  Vector<Real> dH;
  Matrix<Real> ddH;
  std::tie(H, dH, ddH, std::ignore) = M.hamGradHess(z);

  Vector<Real> g = dH - z.dot(dH) * z / (Real)z.size();
  Matrix<Real> m = ddH - (dH * z.transpose() + z.dot(dH) * Matrix<Real>::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + 2.0 * z * z.transpose();

  while (g.norm() / z.size() > ε && λ < 1e8) {
    Vector<Real> dz = (m + λ * (Matrix<Real>)abs(m.diagonal().array()).matrix().asDiagonal()).partialPivLu().solve(g);
    dz -= z.dot(dz) * z / (Real)z.size();
    Vector<Real> zNew = normalize(z - dz);

    Real HNew;
    Vector<Real> dHNew;
    Matrix<Real> 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<Real>::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size() + 2.0 * z * z.transpose();

      λ /= 2;
    } else {
      λ *= 1.5;
    }
  }

  return z;
}

template <class Real, class Scalar, int ...ps>
Vector<Scalar> findSaddle(const pSpinModel<Scalar, ps...>& M, const Vector<Scalar>& z0, Real ε) {
  Vector<Scalar> z = z0;

  Vector<Scalar> dH;
  Matrix<Scalar> ddH;
  std::tie(std::ignore, dH, ddH, std::ignore) = M.hamGradHess(z);

  Scalar zz = z.transpose() * z;
  Vector<Scalar> g = dH - (z.transpose() * dH) * z / (Real)z.size() + z * (zz - (Real)z.size());
  Matrix<Scalar> m = ddH - (dH * z.transpose() + (z.transpose() * dH) * Matrix<Scalar>::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size()  + Matrix<Scalar>::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose();

  while (g.norm() / z.size() > ε) {
    Vector<Scalar> 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<Scalar>::Identity(z.size(), z.size()) + (ddH * z) * z.transpose()) / (Real)z.size()  + Matrix<Scalar>::Identity(z.size(), z.size()) * (zz - (Real)z.size()) + 2.0 * z * z.transpose();
  }

  return z;
}

template <class Scalar, class Distribution, class Generator>
Vector<Scalar> randomVector(unsigned N, Distribution d, Generator& r) {
  Vector<Scalar> z(N);

  for (unsigned i = 0; i < N; i++) {
    z(i) = d(r);
  }

  return z;
}

template <class Real, class Distribution, class Generator, int ...ps>
Vector<Real> randomMinimum(const pSpinModel<Real, ps...>& M, Distribution d, Generator& r, Real ε) {
  Vector<Real> zSaddle;
  bool foundSaddle = false;

  while (!foundSaddle) {
    Vector<Real> z0 = normalize(randomVector<Real>(M.dimension(), d, r));

    try {
      zSaddle = findMinimum(M, z0, ε);
      foundSaddle = true;
    } catch (std::exception& e) {}
  }

  return zSaddle;
}

template <class Real, class Scalar, class Distribution, class Generator, int ... ps>
Vector<Scalar> randomSaddle(const pSpinModel<Real, ps...>& M, Distribution d, Generator& r, Real ε) {
  Vector<Scalar> zSaddle;
  bool foundSaddle = false;

  while (!foundSaddle) {
    Vector<Scalar> z0 = normalize(randomVector<Scalar>(M.dimension(), d, r));

    try {
      zSaddle = findSaddle(M, z0, ε);
      foundSaddle = true;
    } catch (std::exception& e) {}
  }

  return zSaddle;
}