diff options
| -rw-r--r-- | least_squares.cpp | 93 | 
1 files changed, 46 insertions, 47 deletions
diff --git a/least_squares.cpp b/least_squares.cpp index 2ece781..648592f 100644 --- a/least_squares.cpp +++ b/least_squares.cpp @@ -1,15 +1,13 @@  #include <eigen3/Eigen/Dense> -#include <getopt.h> -  #include <eigen3/unsupported/Eigen/CXX11/Tensor> -#include <random> +#include <getopt.h>  #include "pcg-cpp/include/pcg_random.hpp"  #include "randutils/randutils.hpp"  using Rng = randutils::random_generator<pcg32>; -using Real = double; +using Real = float;  using Vector = Eigen::Matrix<Real, Eigen::Dynamic, 1>;  using Matrix = Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>; @@ -97,31 +95,29 @@ private:  public:    QuadraticModel(unsigned N, unsigned M, Rng& r, double μ1, double μ2, double μ3) : Model(N, M), J(M, N, N), A(M, N), b(M) { -    for (unsigned i = 0; i < M; i++) { +    for (unsigned k = 0; k < N; k++) {        for (unsigned j = 0; j < N; j++) { -        for (unsigned k = 0; k < N; k++) { -          J(i, j, k) = (2 * μ3 / N) * r.variate<Real, std::normal_distribution>(); +        for (unsigned i = 0; i < M; i++) { +          J(i, j, k) = r.variate<Real, std::normal_distribution>(0, 2 * μ3 / N);          }        }      } -    for (unsigned i = 0; i < M; i++) { -      for (unsigned j = 0; j < N; j++) { -        A(i, j) = (μ2 / sqrt(N)) * r.variate<Real, std::normal_distribution>(); -      } +    for (Real& Aij : A.reshaped()) { +      Aij = r.variate<Real, std::normal_distribution>(0, μ2 / sqrt(N));      } -    for (unsigned i = 0; i < M; i++) { -      b(i) = μ1 * r.variate<Real, std::normal_distribution>(); +    for (Real& bi : b) { +      bi = r.variate<Real, std::normal_distribution>(0, μ1);      }    }    std::tuple<Vector, Matrix, const Tensor&> VdVddV(const Vector& x) const {      Matrix Jx = J * x; -    Vector V1 = (A + 0.5 * Jx) * x; +    Vector V = b + (A + 0.5 * Jx) * x;      Matrix dV = A + Jx; -    return {b + V1, dV, J}; +    return {V, dV, J};    }    std::tuple<Real, Vector, Matrix> HdHddH(const Vector& x) const override { @@ -154,22 +150,20 @@ public:        }      } -    for (unsigned i = 0; i < M; i++) { +    for (unsigned k = 0; k < N; k++) {        for (unsigned j = 0; j < N; j++) { -        for (unsigned k = 0; k < N; k++) { -          J2(i, j, k) = (2 * μ3 / N) * r.variate<Real, std::normal_distribution>(); +        for (unsigned i = 0; i < M; i++) { +          J2(i, j, k) = r.variate<Real, std::normal_distribution>(0, 2 * μ3 / N);          }        }      } -    for (unsigned i = 0; i < M; i++) { -      for (unsigned j = 0; j < N; j++) { -        A(i, j) = (μ2 / sqrt(N)) * r.variate<Real, std::normal_distribution>(); -      } +    for (Real& Aij : A.reshaped()) { +      Aij = r.variate<Real, std::normal_distribution>(0, μ2 / sqrt(N));      } -    for (unsigned i = 0; i < M; i++) { -      b(i) = μ1 * r.variate<Real, std::normal_distribution>(); +    for (Real& bi : b) { +      bi = r.variate<Real, std::normal_distribution>(0, μ1);      }    } @@ -195,20 +189,20 @@ public:    }  }; -Vector findMinimum(const Model& M, const Vector& x0, Real ε) { +Vector findMinimum(const Model& M, const Vector& x0, Real ε = 1e-12) {    Vector x = x0;    Real λ = 100;    auto [H, g, m] = M.hamGradHess(x0); -  while (g.norm() / x.size() > ε && λ < 1e8) { -    Vector dx = (m + λ * (Matrix)abs(m.diagonal().array()).matrix().asDiagonal()).partialPivLu().solve(g); +  while (g.norm() / M.N > ε && λ < 1e8) { +    Vector dx = (m + λ * (Matrix)m.diagonal().cwiseAbs().asDiagonal()).partialPivLu().solve(g);      dx -= x.dot(dx) * x / M.N;      Vector xNew = normalize(x - dx);      auto [HNew, gNew, mNew] = M.hamGradHess(xNew); -    if (HNew * 1.0001 <= H) { +    if (HNew < H) {        x = xNew;        H = HNew;        g = gNew; @@ -258,10 +252,13 @@ int main(int argc, char* argv[]) {    Real σ = 1;    Real A = 1;    Real J = 1; +  Real β = 1; +  unsigned sweeps = 10; +  unsigned samples = 10;    int opt; -  while ((opt = getopt(argc, argv, "N:a:s:A:J:")) != -1) { +  while ((opt = getopt(argc, argv, "N:a:s:A:J:b:S:n:")) != -1) {      switch (opt) {      case 'N':        N = (unsigned)atof(optarg); @@ -278,6 +275,15 @@ int main(int argc, char* argv[]) {      case 'J':        J = atof(optarg);        break; +    case 'b': +      β = atof(optarg); +      break; +    case 'S': +      sweeps = atoi(optarg); +      break; +    case 'n': +      samples = atoi(optarg); +      break;      default:        exit(1);      } @@ -287,28 +293,21 @@ int main(int argc, char* argv[]) {    Rng r; -  QuadraticModel leastSquares(N, M, r, σ, A, J); - -  Vector x0 = Vector::Zero(N); -  x0(0) = sqrt(N); - -  std::cout << leastSquares.getHamiltonian(x0) / N << std::endl; +  Vector x = Vector::Zero(N); +  x(0) = sqrt(N); -  Vector xMin1 = findMinimum(leastSquares, x0, 1e-12); +  std::cout << N << " " << α << " " << β; -  std::cout << leastSquares.getHamiltonian(xMin1) / N << std::endl; - -  Vector x = x0; - -  for (unsigned i = 0; i < 10; i++) { -    x = metropolisSweep(leastSquares, x, 0.5, r); +  for (unsigned sample = 0; sample < samples; sample++) { +    QuadraticModel leastSquares(N, M, r, σ, A, J); +    for (unsigned i = 0; i < sweeps; i++) { +      x = metropolisSweep(leastSquares, x, β, r); +    } +    x = findMinimum(leastSquares, x); +    std::cout << " " << leastSquares.getHamiltonian(x) / N;    } -  std::cout << leastSquares.getHamiltonian(x) / N << std::endl; - -  Vector xMin2 = findMinimum(leastSquares, x, 1e-12); - -  std::cout << leastSquares.getHamiltonian(xMin2) / N << std::endl; +  std::cout << std::endl;    return 0;  }  | 
