summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--least_squares.cpp93
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;
}