14 #include "IncrementalSVDFastUpdate.h"
15 #include "utils/HDFDatabase.h"
24 IncrementalSVDFastUpdate::IncrementalSVDFastUpdate(
26 const std::string& basis_file_name) :
30 d_singular_value_tol(options.singular_value_tol)
32 CAROM_VERIFY(options.singular_value_tol >= 0);
39 if (options.restore_state && d_state_database) {
42 d_state_database->getInteger(
"Up_num_rows", num_rows);
44 d_state_database->getInteger(
"Up_num_cols", num_cols);
45 d_Up.reset(
new Matrix(num_rows, num_cols,
true));
46 d_state_database->getDoubleArray(
"Up",
51 d_state_database->close();
52 delete d_state_database;
59 IncrementalSVDFastUpdate::~IncrementalSVDFastUpdate()
67 if (d_save_state && (!isFirstSample())) {
70 d_state_database->create(d_state_file_name);
73 int num_rows = d_Up->numRows();
74 d_state_database->putInteger(
"Up_num_rows", num_rows);
75 int num_cols = d_Up->numColumns();
76 d_state_database->putInteger(
"Up_num_cols", num_cols);
77 d_state_database->putDoubleArray(
"Up",
84 IncrementalSVDFastUpdate::buildInitialSVD(
90 d_S.reset(
new Vector(1,
false));
91 Vector u_vec(u, d_dim,
true);
92 double norm_u = u_vec.norm();
93 d_S->item(0) = norm_u;
96 d_Up.reset(
new Matrix(1, 1,
false));
97 d_Up->item(0, 0) = 1.0;
100 d_U.reset(
new Matrix(d_dim, 1,
true));
101 for (
int i = 0; i < d_dim; ++i) {
102 d_U->item(i, 0) = u[i]/norm_u;
106 if (d_update_right_SV) {
107 d_W.reset(
new Matrix(1, 1,
false));
108 d_W->item(0, 0) = 1.0;
121 IncrementalSVDFastUpdate::computeBasis()
123 d_basis = d_U->mult(*d_Up);
124 if(d_update_right_SV)
126 d_basis_right.reset(
new Matrix(*d_W));
130 std::cout <<
"d_num_samples = " << d_num_samples <<
"\n";
131 std::cout <<
"d_num_rows_of_W = " << d_num_rows_of_W <<
"\n";
132 std::cout <<
"d_singular_value_tol = " << d_singular_value_tol <<
"\n";
133 std::cout <<
"smallest SV = " << d_S->item(d_num_samples-1) <<
"\n";
134 if (d_num_samples > 1) {
135 std::cout <<
"next smallest SV = " << d_S->item(d_num_samples-2) <<
"\n";
139 if ( (d_singular_value_tol != 0.0) &&
140 (d_S->item(d_num_samples-1) < d_singular_value_tol) &&
141 (d_num_samples != 1) ) {
143 if (d_rank == 0) std::cout <<
"removing a small singular value!\n";
145 Matrix* d_basis_new =
new Matrix(d_dim, d_num_samples-1,
146 d_basis->distributed());
147 for (
int row = 0; row < d_dim; ++row) {
148 for (
int col = 0; col < d_num_samples-1; ++col) {
149 d_basis_new->item(row, col) = d_basis->item(row,col);
152 d_basis.reset(d_basis_new);
154 if (d_update_right_SV)
156 Matrix* d_basis_right_new =
new Matrix(d_num_rows_of_W, d_num_samples-1,
157 d_basis_right->distributed());
158 for (
int row = 0; row < d_num_rows_of_W; ++row) {
159 for (
int col = 0; col < d_num_samples-1; ++col) {
160 d_basis_right_new->item(row, col) = d_basis_right->item(row,col);
163 d_basis_right.reset(d_basis_right_new);
169 if (fabs(checkOrthogonality(*d_basis)) >
170 std::numeric_limits<double>::epsilon()*
static_cast<double>(d_num_samples)) {
171 d_basis->orthogonalize();
173 if(d_update_right_SV)
175 if (fabs(checkOrthogonality(*d_basis_right)) >
176 std::numeric_limits<double>::epsilon()*d_num_samples) {
177 d_basis_right->orthogonalize();
184 IncrementalSVDFastUpdate::addLinearlyDependentSample(
187 const Matrix & sigma)
191 Matrix Amod(d_num_samples, d_num_samples,
false);
192 for (
int row = 0; row < d_num_samples; ++row) {
193 for (
int col = 0; col < d_num_samples; ++col) {
194 Amod.item(row, col) = A.item(row, col);
197 d_S->item(col) = sigma.item(row, col);
203 Matrix *Up_times_Amod =
new Matrix(d_Up->numRows(), Amod.numColumns(),
false);
204 d_Up->mult(Amod, *Up_times_Amod);
205 d_Up.reset(Up_times_Amod);
207 if (d_update_right_SV) {
213 Matrix *new_d_W =
new Matrix(d_num_rows_of_W+1, d_num_samples,
false);
214 for (
int row = 0; row < d_num_rows_of_W; ++row) {
215 for (
int col = 0; col < d_num_samples; ++col) {
216 double new_d_W_entry = 0.0;
217 for (
int entry = 0; entry < d_num_samples; ++entry) {
218 new_d_W_entry += d_W->item(row, entry)*W.item(entry, col);
220 new_d_W->item(row, col) = new_d_W_entry;
223 for (
int col = 0; col < d_num_samples; ++col) {
224 new_d_W->item(d_num_rows_of_W, col) = W.item(d_num_samples, col);
233 IncrementalSVDFastUpdate::addNewSample(
237 const Matrix & sigma)
240 Matrix* newU =
new Matrix(d_dim, d_num_samples+1,
true);
241 for (
int row = 0; row < d_dim; ++row) {
242 for (
int col = 0; col < d_num_samples; ++col) {
243 newU->item(row, col) = d_U->item(row, col);
245 newU->item(row, d_num_samples) = j.item(row);
249 if (d_update_right_SV) {
255 Matrix *new_d_W =
new Matrix(d_num_rows_of_W+1, d_num_samples+1,
false);
256 for (
int row = 0; row < d_num_rows_of_W; ++row) {
257 for (
int col = 0; col < d_num_samples+1; ++col) {
258 double new_d_W_entry = 0.0;
259 for (
int entry = 0; entry < d_num_samples; ++entry) {
260 new_d_W_entry += d_W->item(row, entry)*W.item(entry, col);
262 new_d_W->item(row, col) = new_d_W_entry;
265 for (
int col = 0; col < d_num_samples+1; ++col) {
266 new_d_W->item(d_num_rows_of_W, col) = W.item(d_num_samples, col);
276 Matrix* new_d_Up =
new Matrix(d_num_samples+1, d_num_samples+1,
false);
277 for (
int row = 0; row < d_num_samples; ++row) {
278 for (
int col = 0; col < d_num_samples+1; ++col) {
279 double new_d_Up_entry = 0.0;
280 for (
int entry = 0; entry < d_num_samples; ++entry) {
281 new_d_Up_entry += d_Up->item(row, entry)*A.item(entry, col);
283 new_d_Up->item(row, col) = new_d_Up_entry;
286 for (
int col = 0; col < d_num_samples+1; ++col) {
287 new_d_Up->item(d_num_samples, col) = A.item(d_num_samples, col);
289 d_Up.reset(new_d_Up);
292 int num_dim = std::min(sigma.numRows(), sigma.numColumns());
293 d_S.reset(
new Vector(num_dim,
false));
294 for (
int i = 0; i < num_dim; i++) {
295 d_S->item(i) = sigma.item(i,i);
304 if (d_num_samples > d_total_dim) {
305 max_U_dim = d_num_samples;
308 max_U_dim = d_total_dim;