blob: 6c886a1be388fb0c9de0ffbf3eeaa1372d9305ab [file] [log] [blame]
Keir Mierle8ebb0732012-04-30 23:09:08 -07001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3// http://code.google.com/p/ceres-solver/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: sameeragarwal@google.com (Sameer Agarwal)
30
31#include "ceres/linear_least_squares_problems.h"
32
Sameer Agarwal82f4b882012-05-06 21:05:28 -070033#include <cstdio>
Keir Mierle8ebb0732012-04-30 23:09:08 -070034#include <string>
35#include <vector>
Keir Mierle8ebb0732012-04-30 23:09:08 -070036#include "ceres/block_sparse_matrix.h"
37#include "ceres/block_structure.h"
Sameer Agarwal82f4b882012-05-06 21:05:28 -070038#include "ceres/casts.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070039#include "ceres/compressed_row_sparse_matrix.h"
40#include "ceres/file.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070041#include "ceres/internal/scoped_ptr.h"
Sameer Agarwal0beab862012-08-13 15:12:01 -070042#include "ceres/matrix_proto.h"
43#include "ceres/stringprintf.h"
44#include "ceres/triplet_sparse_matrix.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070045#include "ceres/types.h"
Sameer Agarwal0beab862012-08-13 15:12:01 -070046#include "glog/logging.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070047
48namespace ceres {
49namespace internal {
50
51LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) {
52 switch (id) {
53 case 0:
54 return LinearLeastSquaresProblem0();
55 case 1:
56 return LinearLeastSquaresProblem1();
57 case 2:
58 return LinearLeastSquaresProblem2();
59 case 3:
60 return LinearLeastSquaresProblem3();
61 default:
62 LOG(FATAL) << "Unknown problem id requested " << id;
63 }
Keir Mierleefe7ac62012-06-24 22:25:28 -070064 return NULL;
Keir Mierle8ebb0732012-04-30 23:09:08 -070065}
66
Sameer Agarwaldd2b17d2012-08-16 19:34:57 -070067#ifndef CERES_NO_PROTOCOL_BUFFERS
Keir Mierle8ebb0732012-04-30 23:09:08 -070068LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
69 const string& filename) {
70 LinearLeastSquaresProblemProto problem_proto;
71 {
72 string serialized_proto;
73 ReadFileToStringOrDie(filename, &serialized_proto);
74 CHECK(problem_proto.ParseFromString(serialized_proto));
75 }
76
77 LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
78 const SparseMatrixProto& A = problem_proto.a();
79
80 if (A.has_block_matrix()) {
81 problem->A.reset(new BlockSparseMatrix(A));
82 } else if (A.has_triplet_matrix()) {
83 problem->A.reset(new TripletSparseMatrix(A));
84 } else {
85 problem->A.reset(new CompressedRowSparseMatrix(A));
86 }
87
88 if (problem_proto.b_size() > 0) {
89 problem->b.reset(new double[problem_proto.b_size()]);
90 for (int i = 0; i < problem_proto.b_size(); ++i) {
91 problem->b[i] = problem_proto.b(i);
92 }
93 }
94
95 if (problem_proto.d_size() > 0) {
96 problem->D.reset(new double[problem_proto.d_size()]);
97 for (int i = 0; i < problem_proto.d_size(); ++i) {
98 problem->D[i] = problem_proto.d(i);
99 }
100 }
101
102 if (problem_proto.d_size() > 0) {
103 if (problem_proto.x_size() > 0) {
104 problem->x_D.reset(new double[problem_proto.x_size()]);
105 for (int i = 0; i < problem_proto.x_size(); ++i) {
106 problem->x_D[i] = problem_proto.x(i);
107 }
108 }
109 } else {
110 if (problem_proto.x_size() > 0) {
111 problem->x.reset(new double[problem_proto.x_size()]);
112 for (int i = 0; i < problem_proto.x_size(); ++i) {
113 problem->x[i] = problem_proto.x(i);
114 }
115 }
116 }
117
118 problem->num_eliminate_blocks = 0;
119 if (problem_proto.has_num_eliminate_blocks()) {
120 problem->num_eliminate_blocks = problem_proto.num_eliminate_blocks();
121 }
122
123 return problem;
124}
125#else
126LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile(
127 const string& filename) {
128 LOG(FATAL)
129 << "Loading a least squares problem from disk requires "
130 << "Ceres to be built with Protocol Buffers support.";
131 return NULL;
132}
Sameer Agarwaldd2b17d2012-08-16 19:34:57 -0700133#endif // CERES_NO_PROTOCOL_BUFFERS
Keir Mierle8ebb0732012-04-30 23:09:08 -0700134
135/*
136A = [1 2]
137 [3 4]
138 [6 -10]
139
140b = [ 8
141 18
142 -18]
143
144x = [2
145 3]
146
147D = [1
148 2]
149
150x_D = [1.78448275;
151 2.82327586;]
152 */
153LinearLeastSquaresProblem* LinearLeastSquaresProblem0() {
154 LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
155
156 TripletSparseMatrix* A = new TripletSparseMatrix(3, 2, 6);
157 problem->b.reset(new double[3]);
158 problem->D.reset(new double[2]);
159
160 problem->x.reset(new double[2]);
161 problem->x_D.reset(new double[2]);
162
163 int* Ai = A->mutable_rows();
164 int* Aj = A->mutable_cols();
165 double* Ax = A->mutable_values();
166
167 int counter = 0;
168 for (int i = 0; i < 3; ++i) {
169 for (int j = 0; j< 2; ++j) {
170 Ai[counter]=i;
171 Aj[counter]=j;
172 ++counter;
173 }
174 };
175
176 Ax[0] = 1.;
177 Ax[1] = 2.;
178 Ax[2] = 3.;
179 Ax[3] = 4.;
180 Ax[4] = 6;
181 Ax[5] = -10;
182 A->set_num_nonzeros(6);
183 problem->A.reset(A);
184
185 problem->b[0] = 8;
186 problem->b[1] = 18;
187 problem->b[2] = -18;
188
189 problem->x[0] = 2.0;
190 problem->x[1] = 3.0;
191
192 problem->D[0] = 1;
193 problem->D[1] = 2;
194
195 problem->x_D[0] = 1.78448275;
196 problem->x_D[1] = 2.82327586;
197 return problem;
198}
199
200
201/*
202 A = [1 0 | 2 0 0
203 3 0 | 0 4 0
204 0 5 | 0 0 6
205 0 7 | 8 0 0
206 0 9 | 1 0 0
207 0 0 | 1 1 1]
208
209 b = [0
210 1
211 2
212 3
213 4
214 5]
215
216 c = A'* b = [ 3
217 67
218 33
219 9
220 17]
221
222 A'A = [10 0 2 12 0
223 0 155 65 0 30
224 2 65 70 1 1
225 12 0 1 17 1
226 0 30 1 1 37]
227
228 S = [ 42.3419 -1.4000 -11.5806
229 -1.4000 2.6000 1.0000
230 11.5806 1.0000 31.1935]
231
232 r = [ 4.3032
233 5.4000
234 5.0323]
235
236 S\r = [ 0.2102
237 2.1367
238 0.1388]
239
240 A\b = [-2.3061
241 0.3172
242 0.2102
243 2.1367
244 0.1388]
245*/
246// The following two functions create a TripletSparseMatrix and a
247// BlockSparseMatrix version of this problem.
248
249// TripletSparseMatrix version.
250LinearLeastSquaresProblem* LinearLeastSquaresProblem1() {
251 int num_rows = 6;
252 int num_cols = 5;
253
254 LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
255 TripletSparseMatrix* A = new TripletSparseMatrix(num_rows,
256 num_cols,
257 num_rows * num_cols);
258 problem->b.reset(new double[num_rows]);
259 problem->D.reset(new double[num_cols]);
260 problem->num_eliminate_blocks = 2;
261
262 int* rows = A->mutable_rows();
263 int* cols = A->mutable_cols();
264 double* values = A->mutable_values();
265
266 int nnz = 0;
267
268 // Row 1
269 {
270 rows[nnz] = 0;
271 cols[nnz] = 0;
272 values[nnz++] = 1;
273
274 rows[nnz] = 0;
275 cols[nnz] = 2;
276 values[nnz++] = 2;
277 }
278
279 // Row 2
280 {
281 rows[nnz] = 1;
282 cols[nnz] = 0;
283 values[nnz++] = 3;
284
285 rows[nnz] = 1;
286 cols[nnz] = 3;
287 values[nnz++] = 4;
288 }
289
290 // Row 3
291 {
292 rows[nnz] = 2;
293 cols[nnz] = 1;
294 values[nnz++] = 5;
295
296 rows[nnz] = 2;
297 cols[nnz] = 4;
298 values[nnz++] = 6;
299 }
300
301 // Row 4
302 {
303 rows[nnz] = 3;
304 cols[nnz] = 1;
305 values[nnz++] = 7;
306
307 rows[nnz] = 3;
308 cols[nnz] = 2;
309 values[nnz++] = 8;
310 }
311
312 // Row 5
313 {
314 rows[nnz] = 4;
315 cols[nnz] = 1;
316 values[nnz++] = 9;
317
318 rows[nnz] = 4;
319 cols[nnz] = 2;
320 values[nnz++] = 1;
321 }
322
323 // Row 6
324 {
325 rows[nnz] = 5;
326 cols[nnz] = 2;
327 values[nnz++] = 1;
328
329 rows[nnz] = 5;
330 cols[nnz] = 3;
331 values[nnz++] = 1;
332
333 rows[nnz] = 5;
334 cols[nnz] = 4;
335 values[nnz++] = 1;
336 }
337
338 A->set_num_nonzeros(nnz);
339 CHECK(A->IsValid());
340
341 problem->A.reset(A);
342
343 for (int i = 0; i < num_cols; ++i) {
344 problem->D.get()[i] = 1;
345 }
346
347 for (int i = 0; i < num_rows; ++i) {
348 problem->b.get()[i] = i;
349 }
350
351 return problem;
352}
353
354// BlockSparseMatrix version
355LinearLeastSquaresProblem* LinearLeastSquaresProblem2() {
356 int num_rows = 6;
357 int num_cols = 5;
358
359 LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
360
361 problem->b.reset(new double[num_rows]);
362 problem->D.reset(new double[num_cols]);
363 problem->num_eliminate_blocks = 2;
364
365 CompressedRowBlockStructure* bs = new CompressedRowBlockStructure;
366 scoped_array<double> values(new double[num_rows * num_cols]);
367
368 for (int c = 0; c < num_cols; ++c) {
369 bs->cols.push_back(Block());
370 bs->cols.back().size = 1;
371 bs->cols.back().position = c;
372 }
373
374 int nnz = 0;
375
376 // Row 1
377 {
378 values[nnz++] = 1;
379 values[nnz++] = 2;
380
381 bs->rows.push_back(CompressedRow());
382 CompressedRow& row = bs->rows.back();
383 row.block.size = 1;
384 row.block.position = 0;
385 row.cells.push_back(Cell(0, 0));
386 row.cells.push_back(Cell(2, 1));
387 }
388
389 // Row 2
390 {
391 values[nnz++] = 3;
392 values[nnz++] = 4;
393
394 bs->rows.push_back(CompressedRow());
395 CompressedRow& row = bs->rows.back();
396 row.block.size = 1;
397 row.block.position = 1;
398 row.cells.push_back(Cell(0, 2));
399 row.cells.push_back(Cell(3, 3));
400 }
401
402 // Row 3
403 {
404 values[nnz++] = 5;
405 values[nnz++] = 6;
406
407 bs->rows.push_back(CompressedRow());
408 CompressedRow& row = bs->rows.back();
409 row.block.size = 1;
410 row.block.position = 2;
411 row.cells.push_back(Cell(1, 4));
412 row.cells.push_back(Cell(4, 5));
413 }
414
415 // Row 4
416 {
417 values[nnz++] = 7;
418 values[nnz++] = 8;
419
420 bs->rows.push_back(CompressedRow());
421 CompressedRow& row = bs->rows.back();
422 row.block.size = 1;
423 row.block.position = 3;
424 row.cells.push_back(Cell(1, 6));
425 row.cells.push_back(Cell(2, 7));
426 }
427
428 // Row 5
429 {
430 values[nnz++] = 9;
431 values[nnz++] = 1;
432
433 bs->rows.push_back(CompressedRow());
434 CompressedRow& row = bs->rows.back();
435 row.block.size = 1;
436 row.block.position = 4;
437 row.cells.push_back(Cell(1, 8));
438 row.cells.push_back(Cell(2, 9));
439 }
440
441 // Row 6
442 {
443 values[nnz++] = 1;
444 values[nnz++] = 1;
445 values[nnz++] = 1;
446
447 bs->rows.push_back(CompressedRow());
448 CompressedRow& row = bs->rows.back();
449 row.block.size = 1;
450 row.block.position = 5;
451 row.cells.push_back(Cell(2, 10));
452 row.cells.push_back(Cell(3, 11));
453 row.cells.push_back(Cell(4, 12));
454 }
455
456 BlockSparseMatrix* A = new BlockSparseMatrix(bs);
457 memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values()));
458
459 for (int i = 0; i < num_cols; ++i) {
460 problem->D.get()[i] = 1;
461 }
462
463 for (int i = 0; i < num_rows; ++i) {
464 problem->b.get()[i] = i;
465 }
466
467 problem->A.reset(A);
468
469 return problem;
470}
471
472
473/*
474 A = [1 0
475 3 0
476 0 5
477 0 7
478 0 9
479 0 0]
480
481 b = [0
482 1
483 2
484 3
485 4
486 5]
487*/
488// BlockSparseMatrix version
489LinearLeastSquaresProblem* LinearLeastSquaresProblem3() {
490 int num_rows = 5;
491 int num_cols = 2;
492
493 LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem;
494
495 problem->b.reset(new double[num_rows]);
496 problem->D.reset(new double[num_cols]);
497 problem->num_eliminate_blocks = 2;
498
499 CompressedRowBlockStructure* bs = new CompressedRowBlockStructure;
500 scoped_array<double> values(new double[num_rows * num_cols]);
501
502 for (int c = 0; c < num_cols; ++c) {
503 bs->cols.push_back(Block());
504 bs->cols.back().size = 1;
505 bs->cols.back().position = c;
506 }
507
508 int nnz = 0;
509
510 // Row 1
511 {
512 values[nnz++] = 1;
513 bs->rows.push_back(CompressedRow());
514 CompressedRow& row = bs->rows.back();
515 row.block.size = 1;
516 row.block.position = 0;
517 row.cells.push_back(Cell(0, 0));
518 }
519
520 // Row 2
521 {
522 values[nnz++] = 3;
523 bs->rows.push_back(CompressedRow());
524 CompressedRow& row = bs->rows.back();
525 row.block.size = 1;
526 row.block.position = 1;
527 row.cells.push_back(Cell(0, 1));
528 }
529
530 // Row 3
531 {
532 values[nnz++] = 5;
533 bs->rows.push_back(CompressedRow());
534 CompressedRow& row = bs->rows.back();
535 row.block.size = 1;
536 row.block.position = 2;
537 row.cells.push_back(Cell(1, 2));
538 }
539
540 // Row 4
541 {
542 values[nnz++] = 7;
543 bs->rows.push_back(CompressedRow());
544 CompressedRow& row = bs->rows.back();
545 row.block.size = 1;
546 row.block.position = 3;
547 row.cells.push_back(Cell(1, 3));
548 }
549
550 // Row 5
551 {
552 values[nnz++] = 9;
553 bs->rows.push_back(CompressedRow());
554 CompressedRow& row = bs->rows.back();
555 row.block.size = 1;
556 row.block.position = 4;
557 row.cells.push_back(Cell(1, 4));
558 }
559
560 BlockSparseMatrix* A = new BlockSparseMatrix(bs);
561 memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values()));
562
563 for (int i = 0; i < num_cols; ++i) {
564 problem->D.get()[i] = 1;
565 }
566
567 for (int i = 0; i < num_rows; ++i) {
568 problem->b.get()[i] = i;
569 }
570
571 problem->A.reset(A);
572
573 return problem;
574}
575
Sergey Sharybinb53c9662013-02-25 01:14:26 +0600576namespace {
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700577bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
578 int iteration,
579 const SparseMatrix* A,
580 const double* D,
581 const double* b,
582 const double* x,
583 int num_eliminate_blocks) {
584 CHECK_NOTNULL(A);
585 Matrix AA;
586 A->ToDenseMatrix(&AA);
587 LOG(INFO) << "A^T: \n" << AA.transpose();
588
589 if (D != NULL) {
590 LOG(INFO) << "A's appended diagonal:\n"
591 << ConstVectorRef(D, A->num_cols());
592 }
593
594 if (b != NULL) {
595 LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows());
596 }
597
598 if (x != NULL) {
599 LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols());
600 }
601 return true;
602};
603
Sameer Agarwaldd2b17d2012-08-16 19:34:57 -0700604#ifndef CERES_NO_PROTOCOL_BUFFERS
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700605bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
606 int iteration,
607 const SparseMatrix* A,
608 const double* D,
609 const double* b,
610 const double* x,
611 int num_eliminate_blocks) {
612 CHECK_NOTNULL(A);
613 LinearLeastSquaresProblemProto lsqp;
614 A->ToProto(lsqp.mutable_a());
615
616 if (D != NULL) {
617 for (int i = 0; i < A->num_cols(); ++i) {
618 lsqp.add_d(D[i]);
619 }
620 }
621
622 if (b != NULL) {
623 for (int i = 0; i < A->num_rows(); ++i) {
624 lsqp.add_b(b[i]);
625 }
626 }
627
628 if (x != NULL) {
629 for (int i = 0; i < A->num_cols(); ++i) {
630 lsqp.add_x(x[i]);
631 }
632 }
633
634 lsqp.set_num_eliminate_blocks(num_eliminate_blocks);
635 string format_string = JoinPath(directory,
636 "lm_iteration_%03d.lsqp");
637 string filename =
638 StringPrintf(format_string.c_str(), iteration);
639 LOG(INFO) << "Dumping least squares problem for iteration " << iteration
640 << " to disk. File: " << filename;
641 WriteStringToFileOrDie(lsqp.SerializeAsString(), filename);
642 return true;
643}
644#else
645bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
646 int iteration,
647 const SparseMatrix* A,
648 const double* D,
649 const double* b,
650 const double* x,
651 int num_eliminate_blocks) {
652 LOG(ERROR) << "Dumping least squares problems is only "
653 << "supported when Ceres is compiled with "
654 << "protocol buffer support.";
655 return false;
656}
657#endif
658
659void WriteArrayToFileOrDie(const string& filename,
660 const double* x,
661 const int size) {
662 CHECK_NOTNULL(x);
663 VLOG(2) << "Writing array to: " << filename;
664 FILE* fptr = fopen(filename.c_str(), "w");
665 CHECK_NOTNULL(fptr);
666 for (int i = 0; i < size; ++i) {
667 fprintf(fptr, "%17f\n", x[i]);
668 }
669 fclose(fptr);
670}
671
672bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
673 int iteration,
674 const SparseMatrix* A,
675 const double* D,
676 const double* b,
677 const double* x,
678 int num_eliminate_blocks) {
679 CHECK_NOTNULL(A);
680 string format_string = JoinPath(directory,
681 "lm_iteration_%03d");
682 string filename_prefix =
683 StringPrintf(format_string.c_str(), iteration);
684
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700685 LOG(INFO) << "writing to: " << filename_prefix << "*";
686
687 string matlab_script;
688 StringAppendF(&matlab_script,
Sameer Agarwal4a6cc1c2012-06-18 10:20:08 -0700689 "function lsqp = lm_iteration_%03d()\n", iteration);
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700690 StringAppendF(&matlab_script,
691 "lsqp.num_rows = %d;\n", A->num_rows());
692 StringAppendF(&matlab_script,
693 "lsqp.num_cols = %d;\n", A->num_cols());
694
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700695 {
696 string filename = filename_prefix + "_A.txt";
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700697 FILE* fptr = fopen(filename.c_str(), "w");
698 CHECK_NOTNULL(fptr);
699 A->ToTextFile(fptr);
700 fclose(fptr);
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700701 StringAppendF(&matlab_script,
702 "tmp = load('%s', '-ascii');\n", filename.c_str());
703 StringAppendF(
704 &matlab_script,
705 "lsqp.A = sparse(tmp(:, 1) + 1, tmp(:, 2) + 1, tmp(:, 3), %d, %d);\n",
706 A->num_rows(),
707 A->num_cols());
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700708 }
709
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700710
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700711 if (D != NULL) {
712 string filename = filename_prefix + "_D.txt";
713 WriteArrayToFileOrDie(filename, D, A->num_cols());
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700714 StringAppendF(&matlab_script,
715 "lsqp.D = load('%s', '-ascii');\n", filename.c_str());
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700716 }
717
718 if (b != NULL) {
719 string filename = filename_prefix + "_b.txt";
720 WriteArrayToFileOrDie(filename, b, A->num_rows());
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700721 StringAppendF(&matlab_script,
722 "lsqp.b = load('%s', '-ascii');\n", filename.c_str());
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700723 }
724
725 if (x != NULL) {
726 string filename = filename_prefix + "_x.txt";
727 WriteArrayToFileOrDie(filename, x, A->num_cols());
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700728 StringAppendF(&matlab_script,
729 "lsqp.x = load('%s', '-ascii');\n", filename.c_str());
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700730 }
731
Sameer Agarwal2d2c90a2012-05-11 14:12:25 -0700732 string matlab_filename = filename_prefix + ".m";
733 WriteStringToFileOrDie(matlab_script, matlab_filename);
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700734 return true;
735}
Sergey Sharybinb53c9662013-02-25 01:14:26 +0600736} // namespace
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700737
738bool DumpLinearLeastSquaresProblem(const string& directory,
Sameer Agarwal509f68c2013-02-20 01:39:03 -0800739 int iteration,
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700740 DumpFormatType dump_format_type,
741 const SparseMatrix* A,
742 const double* D,
743 const double* b,
744 const double* x,
745 int num_eliminate_blocks) {
746 switch (dump_format_type) {
Sameer Agarwal509f68c2013-02-20 01:39:03 -0800747 case CONSOLE:
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700748 return DumpLinearLeastSquaresProblemToConsole(directory,
749 iteration,
750 A, D, b, x,
751 num_eliminate_blocks);
Sameer Agarwal509f68c2013-02-20 01:39:03 -0800752 case PROTOBUF:
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700753 return DumpLinearLeastSquaresProblemToProtocolBuffer(
754 directory,
755 iteration,
756 A, D, b, x,
757 num_eliminate_blocks);
Sameer Agarwal509f68c2013-02-20 01:39:03 -0800758 case TEXTFILE:
Sameer Agarwal82f4b882012-05-06 21:05:28 -0700759 return DumpLinearLeastSquaresProblemToTextFile(directory,
760 iteration,
761 A, D, b, x,
762 num_eliminate_blocks);
763 default:
764 LOG(FATAL) << "Unknown DumpFormatType " << dump_format_type;
765 };
766
767 return true;
768}
769
Keir Mierle8ebb0732012-04-30 23:09:08 -0700770} // namespace internal
771} // namespace ceres