Mesh-processing-library/test/tLLS.cpp

172 строки
5.9 KiB
C++

// -*- C++ -*- Copyright (c) Microsoft Corporation; see license.txt
#include "LLS.h"
#include "SingularValueDecomposition.h"
#include "Random.h"
#include "MatrixOp.h" // identity_mat()
#include "Stat.h"
using namespace hh;
static unique_ptr<LLS> make_lls(int c, int m, int n, int nd) {
if (c==0) return make_unique<SparseLLS>(m, n, nd);
if (c==1) return make_unique<LudLLS>(m, n, nd);
if (c==2) return make_unique<GivensLLS>(m, n, nd);
if (c==3) return make_unique<SvdLLS>(m, n, nd);
if (c==4) return make_unique<SvdDoubleLLS>(m, n, nd);
if (c==5) return make_unique<QrdLLS>(m, n, nd);
assertnever("");
}
int main() {
{
SvdLLS lls(1, 1, 1);
lls.enter_a_rc(0, 0, 1.f);
lls.enter_b_rc(0, 0, 10.f);
lls.enter_xest_rc(0, 0, 1.f);
assertx(lls.solve());
SHOW(lls.get_x_rc(0, 0));
}
{
Vec1<float> X1 = {-100.f}, B1 = {2.f};
Vec1<float> X2 = {-100.f}, B2 = {2.f};
SvdLLS lls(1, 1, 2);
lls.enter_a_rc(0, 0, 4.f);
lls.enter_b_c(0, B1);
lls.enter_xest_c(0, X1);
lls.enter_b_c(1, B2);
lls.enter_xest_c(1, X2);
assertx(lls.solve());
lls.get_x_c(0, X1);
lls.get_x_c(1, X2);
SHOW(X1[0]);
SHOW(X2[0]);
}
{
float X1[1] = {-100.f};
float X2[1] = {-100.f};
SparseLLS lls(1, 1, 2);
lls.enter_a_rc(0, 0, 4.f);
lls.enter_b_c(0, V(2.f));
lls.enter_xest_c(0, X1);
lls.enter_b_c(1, V(2.f));
lls.enter_xest_c(1, X2);
if (0) {
lls.set_max_iter(200);
lls.set_tolerance(1e-4f);
}
assertx(lls.solve());
lls.get_x_c(0, X1);
lls.get_x_c(1, X2);
SHOW(X1[0]);
SHOW(X2[0]);
// SparseLLS::Ival::pool.destroy();
}
{
Vec1<float> X1 = {-100.f}, X2 = {-100.f};
const Vec1<float> B1 = {2.f}, B2 = {2.f};
LudLLS lls(1, 1, 2);
lls.enter_a_rc(0, 0, 4.f);
lls.enter_b_c(0, B1);
lls.enter_xest_c(0, X1);
lls.enter_b_c(1, B2);
lls.enter_xest_c(1, X2);
assertx(lls.solve());
lls.get_x_c(0, X1);
lls.get_x_c(1, X2);
SHOW(X1[0]);
SHOW(X2[0]);
}
{
const int n = 3;
Matrix<float> a(n, n);
Array<float> b(n);
for_int(i, n) {
for_int(j, n) {
a[i][j] = 1.f+i*3+j+abs(2-i)*abs(5-j+i)*j+i*i*j*j;
// showf("[%d, %d]=%g\n", i, j, a[i][j]);
}
b[i] = float(abs(i-4));
// SHOW(b[i]);
}
for_int(c, 6) {
SHOW(c);
const int nd = 2;
auto up_lls = make_lls(c, n, n, nd); LLS& lls = *up_lls;
for_int(i, n) {
for_int(j, n) { lls.enter_a_rc(i, j, a[i][j]); }
lls.enter_b_rc(i, 0, b[i]);
lls.enter_b_rc(i, 1, b[i]*2);
lls.enter_xest_rc(i, 0, 0.f);
lls.enter_xest_rc(i, 1, 0.f);
}
assertx(lls.solve());
for_int(i, n) { SHOW(round_fraction_digits(lls.get_x_rc(i, 0))); }
for_int(i, n) { SHOW(round_fraction_digits(lls.get_x_rc(i, 1))); }
}
}
{
for_int(c, 6) {
SHOW(c);
auto up_lls = make_lls(c, 2, 1, 1); LLS& lls = *up_lls;
lls.enter_a_rc(0, 0, 1.f);
lls.enter_a_rc(1, 0, 1.f);
lls.enter_b_rc(0, 0, 10.f);
lls.enter_b_rc(1, 0, 20.f);
lls.enter_xest_rc(0, 0 , 50.f);
assertx(lls.solve());
SHOW(lls.get_x_rc(0, 0));
}
}
{
for_int(c, 6) {
SHOW(c);
auto up_lls = make_lls(c, 3, 2, 1); LLS& lls = *up_lls;
lls.enter_a_rc(0, 0, 1.f);
lls.enter_a_rc(0, 1, 1.f);
lls.enter_a_rc(1, 0, 1.f);
lls.enter_a_rc(1, 1, 0.f);
lls.enter_a_rc(2, 0, 0.f);
lls.enter_a_rc(2, 1, 1.f);
lls.enter_b_rc(0, 0, 10.f);
lls.enter_b_rc(1, 0, 2.f);
lls.enter_b_rc(2, 0, 12.f);
lls.enter_xest_rc(0, 0 , 50.f);
lls.enter_xest_rc(1, 0 , 50.f);
assertx(lls.solve());
SHOW(round_fraction_digits(lls.get_x_rc(0, 0)));
SHOW(round_fraction_digits(lls.get_x_rc(1, 0)));
}
}
{
using Real = float;
for_int(imode, 2) {
for_int(inormalize, 2) {
for_intL(m, 1, 11) for_intL(n, 1, 11) {
if (m<n) continue;
Matrix<Real> A(m, n);
switch (imode) {
bcase 0: for (Real& v : A) { v = possible_cast<Real>(Random::G.dunif()); }
bcase 1: identity_mat(A);
bdefault: assertnever("");
}
if (inormalize) for_int(i, n) normalize(column(A, i)); // possibly normalize the columns
if (1) {
Matrix<Real> U(m, n);
Array<Real> S(n);
Matrix<Real> VT(n, n);
bool success = singular_value_decomposition(A, U, S, VT);
sort_singular_values(U, S, VT);
Matrix<Real> R = mat_mul(mat_mul(U, diag_mat(S)), transpose(VT));
Matrix<Real> UTU = mat_mul(transpose(U), U);
Matrix<Real> VTV = mat_mul(transpose(VT), VT);
float Rerr = Stat(R-A).max_abs();
float UTUerr = Stat(UTU-identity_mat<Real>(n)).max_abs();
float VTVerr = Stat(VTV-identity_mat<Real>(n)).max_abs();
if (0 || !assertw(Rerr<1e-6f && UTUerr<1e-6f && VTVerr<1e-6f))
SHOW(inormalize, m, n, success, Rerr, UTUerr, VTVerr);
}
}
}
}
}
}