-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
156 lines (136 loc) · 5 KB
/
main.cpp
File metadata and controls
156 lines (136 loc) · 5 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <iostream>
#include <vector>
#include <iomanip>
#include <cmath>
#include <complex>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include "tensorcross.h"
#include "tensortrain.h"
#include "mindex.h"
// ============================================================
// The function to learn:
//
// f(x_0, ..., x_{N-1}) = exp(-0.1 * sum_i x_i)
// * cos(0.3 * sum_i (i+1)*x_i)
// / (1 + 0.05 * sum_i x_i^2)
//
// Indices x_i in {0, ..., d-1}. d=6, N=8 -> 6^8 ~ 1.7M entries.
// The function is smooth but nontrivial in every variable.
// ============================================================
// ----- double version -----
double f_double(const MultiIndex& mi)
{
const int N = static_cast<int>(mi.data.size());
double s1 = 0.0, s2 = 0.0, s3 = 0.0;
for (int k = 0; k < N; ++k) {
double xk = static_cast<double>(mi.data[k]);
s1 += xk;
s2 += static_cast<double>(k + 1) * xk;
s3 += xk * xk;
}
return std::exp(-0.1 * s1) * std::cos(0.3 * s2) / (1.0 + 0.05 * s3);
}
// ----- quad version -----
using float128 = boost::multiprecision::float128;
float128 f_quad(const MultiIndex& mi)
{
const int N = static_cast<int>(mi.data.size());
float128 s1 = 0, s2 = 0, s3 = 0;
for (int k = 0; k < N; ++k) {
float128 xk(mi.data[k]);
s1 += xk;
s2 += float128(k + 1) * xk;
s3 += xk * xk;
}
using boost::multiprecision::exp;
using boost::multiprecision::cos;
return exp(float128("-0.1") * s1)
* cos(float128("0.3") * s2)
/ (float128(1) + float128("0.05") * s3);
}
// ============================================================
// Helper: run TCI and report errors
// ============================================================
template <typename Scalar, typename Func>
void run_demo(const std::string& label,
Func f_eval,
int N, // number of sites
int d, // physical dimension per site
int n_iter, // TCI sweeps
const std::vector<std::vector<int>>& test_points)
{
std::cout << "\n========================================\n";
std::cout << " " << label << "\n";
std::cout << " N=" << N << " d=" << d
<< " sweeps=" << n_iter << "\n";
std::cout << "========================================\n";
using RealScalar = typename Eigen::NumTraits<Scalar>::Real;
std::vector<int> l_d(N, d);
MultiIndex pivot0(std::vector<int>(N, 0));
TCI<Scalar> tci(f_eval, l_d, pivot0);
for (int it = 0; it < n_iter; ++it) {
tci.iterate();
std::cout << " sweep " << std::setw(3) << (it + 1)
<< " |pivot error| = "
<< std::setprecision(6) << std::scientific
<< static_cast<double>(tci.last_pivot_error())
<< "\n";
}
auto tt = tci.get_TensorTrain();
std::cout << "\n Point-wise check (TT vs exact):\n";
std::cout << std::setprecision(20) << std::fixed;
for (const auto& idx : test_points) {
MultiIndex mi(idx);
Scalar tt_val = tt.eval(idx);
Scalar exact = f_eval(mi);
// For complex Scalar use abs; for real scalars std::abs works fine.
double err = static_cast<double>(
Eigen::numext::abs(tt_val - exact));
std::cout << " idx=";
for (int v : idx) std::cout << v << " ";
std::cout << "\n";
std::cout << " exact = " << exact << "\n";
std::cout << " TT = " << tt_val << "\n";
std::cout << " |err| = " << std::setprecision(6)
<< std::scientific << err << "\n";
}
std::cout << "\n sum over all entries (TT): "
<< std::setprecision(20) << std::fixed
<< tt.sum1() << "\n";
}
int main()
{
// ----------------------------------------------------------
// Problem parameters
// ----------------------------------------------------------
const int N = 8; // number of tensor modes
const int d = 6; // physical dimension (indices 0..5)
const int sweeps = 40; // TCI sweeps
// A few test points to check pointwise accuracy
std::vector<std::vector<int>> test_pts = {
{0, 1, 2, 3, 4, 5, 0, 1},
{3, 3, 3, 3, 3, 3, 3, 3},
{5, 4, 3, 2, 1, 0, 5, 4},
{1, 0, 4, 2, 5, 3, 0, 2},
};
// ----------------------------------------------------------
// Double precision run
// ----------------------------------------------------------
run_demo<double>(
"DOUBLE PRECISION",
f_double,
N, d, sweeps,
test_pts
);
// ----------------------------------------------------------
// Quad precision run
// ----------------------------------------------------------
run_demo<float128>(
"QUAD PRECISION (float128)",
f_quad,
N, d, sweeps,
test_pts
);
return 0;
}