31 #define msg(level, M) (level <= verbose_level) ? (cout << M) : (cout << "")
42 use_user_scaling =
false;
43 use_automated_scaling =
true;
44 new_iteration_callback = 0;
45 state_change_callback = 0;
47 set_state_size(state_size);
53 if (state_size<=0)
return;
55 this->state_size = state_size;
56 state =
new flt_t[state_size];
57 new_state =
new flt_t[state_size];
58 best_state =
new flt_t[state_size];
59 scales =
new flt_t[state_size];
60 for(
int i = 0; i < state_size; i++)
64 void ls_minimizer2::alloc_matrices(
int maximum_scalar_measure_number)
67 assert(maximum_scalar_measure_number>0);
69 if (J && real_J_size>=maximum_scalar_measure_number) {
70 step_solver->resize(state_size, maximum_scalar_measure_number);
75 step_solver =
new ls_step_solver(state_size, maximum_scalar_measure_number);
76 real_J_size = maximum_scalar_measure_number;
77 J = cvCreateMat(maximum_scalar_measure_number, state_size, CV_64F);
78 newJ = cvCreateMat(maximum_scalar_measure_number, state_size, CV_64F);
79 eps = cvCreateMat(maximum_scalar_measure_number, 1, CV_64F);
80 eps_previous = cvCreateMat(maximum_scalar_measure_number, 1, CV_64F);
82 JtJ = cvCreateMat(state_size, state_size, CV_64F);
83 Jteps = cvCreateMat(state_size, 1, CV_64F);
84 ds = cvCreateMat(state_size, 1, CV_64F);
85 Jds = cvCreateMat(maximum_scalar_measure_number, 1, CV_64F);
88 aug_JtJ = cvCreateMat(state_size, state_size, CV_64F);
91 dl_delta_sd = cvCreateMat(state_size, 1, CV_64F);
92 dl_delta_gn = cvCreateMat(state_size, 1, CV_64F);
93 dl_delta_dl = cvCreateMat(state_size, 1, CV_64F);
94 dl_delta_diff = cvCreateMat(state_size, 1, CV_64F);
95 JtJdelta = cvCreateMat(state_size, 1, CV_64F);
96 JJteps = cvCreateMat(maximum_scalar_measure_number, 1, CV_64F);
99 ct_delta_gn = cvCreateMat(state_size, 1, CV_64F);
100 ct_delta_sd = cvCreateMat(state_size, 1, CV_64F);
108 void ls_minimizer2::free_all()
115 delete[] ground_truth_state;
120 void ls_minimizer2::free_matrices()
122 if (step_solver)
delete step_solver;
130 cvReleaseMat(&eps_previous);
133 cvReleaseMat(&Jteps);
137 cvReleaseMat(&aug_JtJ);
138 cvReleaseMat(&dl_delta_sd);
139 cvReleaseMat(&dl_delta_gn);
140 cvReleaseMat(&dl_delta_dl);
141 cvReleaseMat(&dl_delta_diff);
142 cvReleaseMat(&JtJdelta);
143 cvReleaseMat(&JJteps);
145 cvReleaseMat(&ct_delta_gn);
146 cvReleaseMat(&ct_delta_sd);
151 assert((
unsigned)slot_index< 10);
152 user_data[slot_index] = ptr;
159 for(
int i = 0; i < state_size; i++)
160 norm += scales[i] * scales[i];
163 for(
int i = 0; i < state_size; i++)
164 this->scales[i] = scales[i] / (state_size * norm);
166 use_user_scaling =
true;
169 void ls_minimizer2::set_default_values(
void)
171 set_verbose_level(0);
173 default_squared_c = numeric_limits<flt_t>::max();
175 lm_set_initial_lambda(0);
176 lm_set_max_iterations(50);
177 lm_set_max_failures_in_a_row(10);
178 lm_set_tol_cos(1e-5);
180 ct_set_max_iterations(50);
181 set_line_search_parameters(1e-3, 5, 1.2);
183 inside_julien_method =
false;
193 lm_max_iterations = it;
198 lm_max_failures_in_a_row = f;
208 lm_initial_lambda = l;
213 ct_lambda0 = lambda0;
214 ct_k_rough = k_rough;
222 if(ground_truth_state)
delete[] ground_truth_state;
223 ground_truth_state =
new flt_t[state_size];
224 for(
int i = 0; i < state_size; i++)
225 ground_truth_state[i] = state[i];
230 new_iteration_callback = callback;
235 state_change_callback = callback;
239 erase_observations(0);
244 assert(b<0 || (a<=b));
245 if (a >= (
signed)observations.size())
return;
246 observation_vector::iterator first = observations.begin()+a;
247 observation_vector::iterator last = (b<0 ? observations.end() : observations.begin()+b);
248 for (observation_vector::iterator it = first; it != last; ++it)
250 if ((*it)->delete_me)
delete *it;
251 else if ((*it)->array_delete_me)
delete[] *it;
253 observations.erase(first,last);
254 assert(a == (
signed)observations.size());
259 default_squared_c = c * c;
264 assert(!(to_delete && to_array_delete));
271 observations.push_back(obs);
314 int n = get_nb_measures();
316 for (
int i=0; i<n; i++) {
317 flt_t d = computed_b[i] - b[i];
329 for (observation_vector::iterator it = observations.begin();
330 it != observations.end(); ++it)
341 if (ground_truth_state==0)
return;
344 compute_residual(state,
true);
345 cout <<
"GROUND TRUTH: ";
346 compute_residual(ground_truth_state,
true);
348 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
353 int correct_inlier_number = 0, correct_outlier_number = 0;
359 int observation_number = 0;
360 for (observation_vector::iterator it = observations.begin();
361 it != observations.end(); ++it)
368 correct_inlier_number++;
370 correct_outlier_number++;
373 ++observation_number;
378 cout << (100.0 * correct_inlier_number) / gt_inliers <<
"% inliers and ";
379 cout << (100.0 * correct_outlier_number) / (observation_number - gt_inliers) <<
"% outliers correctly found.";
383 ls_minimizer2::flt_t ls_minimizer2::build_eps(flt_t * state, flt_t current_best_residual,
bool outliers_in_residual)
388 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
393 for (observation_vector::iterator it = observations.begin();
394 it != observations.end(); ++it)
397 o->eval_func(state, b, newJ->data.db + im_n*state_size, user_data);
399 flt_t res = o->residual(b);
402 int n = o->get_nb_measures();
403 if (res < o->squared_c)
408 for(
int j = 0; j < n*state_size; j++)
409 (newJ->data.db + im_n * state_size)[j] *= o->
sqrt_weight;
411 for (
int i=0; i<n; ++i)
412 eps->data.db[im_n+i] = o->
sqrt_weight * (o->b[i] - b[i]);
414 residual += o->
weight * res;
420 if (outliers_in_residual)
424 if (residual > current_best_residual) {
427 return numeric_limits<flt_t>::max();
436 ls_minimizer2::flt_t ls_minimizer2::build_eps_return_inlier_residual(flt_t * state, flt_t current_best_residual)
438 return build_eps(state, current_best_residual,
false);
445 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
449 for (observation_vector::iterator it = observations.begin();
450 it != observations.end(); ++it)
454 obs->eval_func(state, b, 0, user_data);
455 residual += obs->
weight * obs->residual(b);
456 if (residual > current_best_residual)
return numeric_limits<flt_t>::max();
463 bool ls_minimizer2::build_J(flt_t * state)
468 for (observation_vector::iterator it = observations.begin();
469 it != observations.end(); ++it)
473 int n = obs->get_nb_measures();
474 assert(im_n+n <= real_J_size);
475 obs->eval_func(state, b, J->data.db + im_n*state_size, user_data);
476 if (obs->
weight != 1.)
for(
int j = 0; j < n*state_size; j++)
477 (J->data.db + im_n * state_size)[j] *= obs->
sqrt_weight;
490 for(
int i = 0; i < state_size; i++)
491 cout << state[i] <<
" " << flush;
493 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
495 flt_t result = residual(state);
497 cout <<
" -> " << result << endl;
502 void ls_minimizer2::show_state(
int vl, flt_t * state, flt_t r)
504 for(
int i = 0; i < state_size; i++) {
506 if (i < state_size - 1)
509 msg(vl,
" --> " << setprecision(20) << r << setprecision(6) << endl);
512 bool ls_minimizer2::build_J_and_stuff(flt_t * state)
522 msg(0,
"**: No inliers found" << endl);
527 cvGEMM(J, eps, 1, 0, 1, Jteps, CV_GEMM_A_T);
528 cvMulTransposed(J, JtJ, 1);
533 void ls_minimizer2::set_current_c_s(flt_t k)
537 if (inside_julien_method)
return;
538 for (observation_vector::iterator it = observations.begin();
539 it != observations.end(); ++it)
547 for (observation_vector::iterator it = observations.begin();
548 it != observations.end(); ++it)
551 flt_t c = exp(k * log(o->
c_max) + (1. - k) * log(o->
c_min));
561 if (observations.size()==0)
return 0;
563 for (observation_vector::iterator it = observations.begin();
564 it != observations.end(); ++it)
566 n += (*it)->get_nb_measures();
569 msg(2,nobs <<
" obs, " << n <<
" measures"<<endl);
581 msg(1,
"LM: Beginning optimization using Levenberg-Marquardt:" << endl);
583 alloc_matrices(count_measures());
585 assert(step_solver!=0);
586 set_new_state(initial_state);
587 assert(step_solver!=0);
589 double *state =
new flt_t[state_size];
590 memcpy(state, initial_state, state_size*
sizeof(
flt_t));
594 flt_t lambda = lm_initial_lambda, rho = 0., cosinus = 0.;
595 int iter_nb = 0, failures_in_a_row = 0;
597 flt_t r_previous = build_eps(state), r=0.;
599 eps_previous->rows = eps->rows; cvCopy(eps, eps_previous);
600 build_J_and_stuff(state);
601 cvCopy(JtJ, aug_JtJ);
603 msg(1,
"LM: "); show_state(1, state, r_previous);
605 while(iter_nb < lm_max_iterations)
608 msg(2,
"LM: iteration # " << iter_nb <<
" --------------------------------------------" << endl);
611 for(
int i = 0; i < state_size; i++)
612 if (use_user_scaling)
613 aug_JtJ->data.db[i * state_size + i] = JtJ->data.db[i * state_size + i] + lambda * scales[i];
614 else if (use_automated_scaling)
615 aug_JtJ->data.db[i * state_size + i] = JtJ->data.db[i * state_size + i] +
616 lambda * (1 + JtJ->data.db[i * state_size + i] * JtJ->data.db[i * state_size + i]);
618 aug_JtJ->data.db[i * state_size + i] = JtJ->data.db[i * state_size + i] + lambda;
620 assert(aug_JtJ->cols == state_size && state_size == aug_JtJ->rows);
622 if (!step_solver->qr_solve(aug_JtJ, Jteps, ds)) {
627 assert(aug_JtJ->cols == state_size && state_size == aug_JtJ->rows);
630 for(
int i = 0; i < state_size; i++) {
631 new_state[i] = state[i];
632 state[i] = state[i] + ds->data.db[i];
635 set_new_state(state);
636 r = build_eps(state);
637 rho = r_previous - r;
639 rho /= lambda * cvDotProduct(ds, ds) + cvDotProduct(ds, Jteps);
642 cvMatMul(J, ds, Jds);
643 cosinus = cvDotProduct(eps_previous, Jds) / (sqrt(r_previous) * sqrt(cvDotProduct(Jds, Jds)));
644 msg(2,
"LM: cosinus = " << cosinus << endl);
645 if (cosinus < lm_tol_cos) {
649 eps_previous->rows = eps->rows; cvCopy(eps, eps_previous);
651 build_J_and_stuff(state);
652 cvCopy(JtJ, aug_JtJ);
654 lambda = lambda / 10;
656 failures_in_a_row = 0;
657 msg(2,
"LM: iteration succeeded: new lambda = " << lambda << endl);
658 msg(2,
"LM: "); show_state(2, state, r);
659 if (verbose_level >= 3) { compare_outliers_with_ground_truth(); compare_state_with_ground_truth(); }
662 memcpy(state, new_state, state_size*
sizeof(
flt_t));
664 if (failures_in_a_row > lm_max_failures_in_a_row) {
668 if (lambda == 0) lambda = 1e-3;
else lambda *= 10;
670 msg(2,
"LM: iteration failed --> " << r <<
" new lambda = " << lambda << endl);
675 if (iter_nb >= lm_max_iterations)
679 case 2:
msg(1,
"LM: " << failures_in_a_row <<
" failures in a row." << endl);
break;
680 case 3:
msg(1,
"LM: Termination criterion satisfied: cosinus = " << cosinus <<
" < " << lm_tol_cos << endl);
682 case 4:
msg(1,
"LM: Too many iterations." << endl);
break;
683 case -1:
msg(1,
"LM: qr_solve failed\n");
break;
685 msg(1,
"LM: unkown termination reason" << endl);
689 for(
int i = 0; i < state_size; i++)
692 if (i < state_size - 1)
695 msg(1,
" --> " << r << endl);
696 msg(1,
"LM: End of minimization." << endl);
698 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
704 void ls_minimizer2::set_new_state(
const flt_t *new_state)
706 if (memcmp(new_state, state,
sizeof(flt_t)*state_size)==0)
return;
707 for(
int i = 0; i < state_size; i++) state[i] = new_state[i];
708 if (state_change_callback) state_change_callback(state, user_data);
711 ls_minimizer2::flt_t ls_minimizer2::dl_update_Delta(flt_t rho, flt_t Delta, flt_t rho_min, flt_t rho_max)
713 if (rho < rho_min)
return Delta / 2;
714 if (rho > rho_max)
return Delta * 2;
720 msg(1,
"DL: Beginning optimization using Dog Leg algorithm:" << endl);
722 alloc_matrices(count_measures());
724 set_new_state(initial_state);
728 flt_t Delta = 10000., rho = 0., cosinus = 0.;
729 flt_t dl_delta_gn_computed =
false;
730 int iter_nb = 0, failures_in_a_row = 0;
733 flt_t r_previous = build_eps(state), r = 0.;
734 eps_previous->rows = eps->rows; cvCopy(eps, eps_previous);
735 build_J_and_stuff(state);
737 msg(1,
"DL: "); show_state(1, state, r_previous);
739 while(iter_nb < lm_max_iterations)
742 msg(2,
"DL: iteration # " << iter_nb <<
" --------------------------------------------" << endl);
744 JJteps->rows = J->rows;
745 cvMatMul(J, Jteps, JJteps);
746 cvScale(Jteps, dl_delta_sd, cvDotProduct(Jteps, Jteps) / cvDotProduct(JJteps, JJteps));
748 dl_delta_gn_computed =
false;
751 msg(2,
"DL: Delta = " << Delta << endl);
752 if (cvDotProduct(dl_delta_sd, dl_delta_sd) > Delta * Delta)
754 cvScale(dl_delta_sd, dl_delta_dl, Delta / cvDotProduct(dl_delta_sd, dl_delta_sd));
755 msg(2,
"DL: Trying truncated steepest descent step" << endl);
758 if (!dl_delta_gn_computed) {
759 step_solver->qr_solve(JtJ, Jteps, dl_delta_gn);
761 dl_delta_gn_computed =
true;
763 if (cvDotProduct(dl_delta_gn, dl_delta_gn) <= Delta * Delta)
765 cvCopy(dl_delta_gn, dl_delta_dl);
767 msg(2,
"DL: Trying gauss-newton step" << endl);
770 cvSub(dl_delta_gn, dl_delta_sd, dl_delta_diff);
771 flt_t beta1, beta2, beta;
772 solve_deg2(cvDotProduct(dl_delta_diff, dl_delta_diff),
773 2 * cvDotProduct(dl_delta_sd, dl_delta_diff),
774 cvDotProduct(dl_delta_sd, dl_delta_sd) - Delta * Delta,
776 beta = (beta1 > 0) ? beta1 : beta2;
777 cvScaleAdd(dl_delta_diff, cvScalar(beta), dl_delta_sd, dl_delta_dl);
779 msg(2,
"DL: Trying truncated gauss-newton step" << endl);
782 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + dl_delta_dl->data.db[i];
784 r = build_eps(new_state);
785 cvMatMul(JtJ, dl_delta_dl, JtJdelta);
786 flt_t L_delta = 2 * ( 0.5 * r_previous - cvDotProduct(Jteps, dl_delta_dl) + 0.5 * cvDotProduct(dl_delta_dl, JtJdelta));
787 rho = (r_previous - r) / (r_previous - L_delta);
789 set_new_state(new_state);
791 cvMatMul(J, dl_delta_dl, Jds);
792 cosinus = cvDotProduct(eps_previous, Jds) / (sqrt(r_previous) * sqrt(cvDotProduct(Jds, Jds)));
793 msg(2,
"DL: cosinus = " << cosinus << endl);
794 if (cosinus < dl_tol_cos) {
798 eps_previous->rows = eps->rows; cvCopy(eps, eps_previous);
800 build_J_and_stuff(state);
802 failures_in_a_row = 0;
803 msg(2,
"DL: "); show_state(2, state, r);
804 if (verbose_level >= 3) { compare_outliers_with_ground_truth(); compare_state_with_ground_truth(); }
807 msg(2,
"DL: -> failure." << endl);
810 if (failures_in_a_row > lm_max_failures_in_a_row) {
815 Delta = dl_update_Delta(rho, Delta, 0.25, 0.75);
819 if (iter_nb >= lm_max_iterations)
822 if (reason == 2)
msg(1,
"DL: " << failures_in_a_row <<
" failures in a row." << endl);
823 if (reason == 3)
msg(1,
"DL: Termination criterion satisfied: cosinus = " << cosinus <<
" < " << lm_tol_cos << endl);
824 if (reason == 4)
msg(1,
"DL: Too many iterations." << endl);
827 for(
int i = 0; i < state_size; i++)
830 if (i < state_size - 1)
833 msg(1,
" --> " << r << endl);
834 msg(1,
"DL: End of minimization." << endl);
836 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
841 bool ls_minimizer2::line_search(CvMat * dir,
842 flt_t lambda_min, flt_t lambda_max,
843 flt_t residual0, flt_t & new_residual, flt_t & new_lambda)
845 lambda_min = lambda_max = 0.;
847 alloc_matrices(count_measures());
849 static flt_t lambda = ct_lambda0;
850 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + lambda * dir->data.db[i];
851 flt_t residual_lambda = inlier_residual(new_state, residual0);
852 flt_t old_residual = residual_lambda;
854 while(residual_lambda > residual0)
856 msg(2,
" LS: rough search lambda = " << lambda << endl);
857 lambda /= ct_k_rough;
858 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + lambda * dir->data.db[i];
859 old_residual = residual_lambda;
860 residual_lambda = inlier_residual(new_state, residual0);
863 while(residual_lambda < residual0)
865 msg(2,
" LS: rough search lambda = " << lambda << endl);
866 residual0 = residual_lambda;
867 lambda *= ct_k_rough;
868 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + lambda * dir->data.db[i];
869 old_residual = residual_lambda;
870 residual_lambda = inlier_residual(new_state, old_residual);
872 lambda /= ct_k_rough;
873 residual_lambda = old_residual;
874 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + lambda * dir->data.db[i];
877 while(residual_lambda < new_residual)
879 msg(2,
" LS: fine search lambda = " << lambda << endl);
880 new_residual = residual_lambda;
881 memcpy(best_state, new_state, state_size *
sizeof(flt_t));
886 for(
int i = 0; i < state_size; i++) new_state[i] = state[i] + lambda * dir->data.db[i];
887 residual_lambda = build_eps(new_state, new_residual);
900 msg(1,
"CT: Beginning optimization using Cat Tail algorithm:" << endl);
902 alloc_matrices(count_measures());
907 memcpy(state, initial_state, state_size *
sizeof(
flt_t));
916 if (verbose_level >= 3) {
msg(3,
"CT: "); compare_state_with_ground_truth(); }
918 r = build_eps_return_inlier_residual(state);
920 build_J_and_stuff(state);
922 msg(2,
"CT " << nb_inliers <<
" inliers." << endl);
925 flt_t best_lambda, gain = 0.;
927 step_solver->qr_solve(J, eps, ct_delta_gn);
928 for(
int i = 0; i < state_size; i++) best_state[i] = state[i] + ct_delta_gn->data.db[i];
929 flt_t r_gn = inlier_residual(best_state, best_r);
937 for(
int i = 0; i < state_size; i++) ct_delta_sd->data.db[i] = Jteps->data.db[i] / JtJ->data.db[i * state_size + i];
938 if (line_search(ct_delta_sd, 0.0001, 1, r, best_r, best_lambda))
949 else if (method == 1)
950 msg(2,
"CT: Taking the gauss-newton step." << endl);
951 else if (method == 2)
952 msg(2,
"CT: Taking the corrected linear model step (lambda = " << best_lambda <<
")." << endl);
955 cerr <<
"bug in ls_minimizer2::minimize_using_cattail_from" << endl;
959 msg(2,
"CT: Gain = " << gain <<
" --> residual = " << best_r << endl);
960 memcpy(state, best_state, state_size *
sizeof(
flt_t));
965 }
while(iter_nb < ct_max_iterations);
969 if (reason == 2)
msg(2,
"CT: no improvement found." << endl);
970 if (reason == 4)
msg(2,
"CT: Too many iterations (" << ct_max_iterations <<
")." << endl);
973 for(
int i = 0; i < state_size; i++)
976 if (i < state_size - 1)
979 msg(1,
" --> " << r << endl);
980 msg(1,
"CT: End of minimization." << endl);
982 if (new_iteration_callback != 0) new_iteration_callback(state, user_data);
987 bool ls_minimizer2::pick_random_indices(
int *idx,
int n,
int max_index)
990 if ( n > max_index )
return false;
992 for (
int i=0; i<n; i++) {
993 idx[i] =
rand()%max_index;
995 for (
int j=0; j<i; j++)
996 if (idx[i]==idx[j]) {
1004 static inline unsigned mymin(
unsigned a,
unsigned b) {
1005 return (a>b? b : a);
1010 int min_number_of_inliers,
int max_number_of_iterations)
1012 alloc_matrices(count_measures());
1018 flt_t best_residual = numeric_limits<flt_t>::max();
1019 int *idx =
new int[nb_samples];
1021 for(
int iter = 0; iter < max_number_of_iterations; iter++)
1023 if (!pick_random_indices(idx, nb_samples,
mymin(iter + nb_samples, observations.size())))
1025 cerr <<
"PR: not enough observations." << endl;
1029 for (
int i=0; i<nb_samples; i++) {
1031 observation_vector::iterator it=observations.begin();
1032 for (
int j=0; j<idx[i]; ++i) ++it;
1037 if (f(new_state, o, nb_samples, user_data))
1039 set_new_state(new_state);
1040 flt_t new_residual = build_eps(state, best_residual);
1041 if (new_residual < best_residual)
1043 best_residual = new_residual;
1044 memcpy(best_state, state, state_size *
sizeof(
flt_t));
1046 for (observation_vector::iterator it = observations.begin();
1047 it != observations.end(); ++it)
1049 if (!(*it)->outlier)
1052 if (nb_inliers > min_number_of_inliers)
1061 memcpy(state, best_state, state_size *
sizeof(
flt_t));
1062 return best_residual;
1067 alloc_matrices(count_measures());
1068 inside_julien_method =
true;
1069 ct_set_max_iterations(nb_iterations_per_step);
1071 memcpy(state, initial_state, state_size *
sizeof(
flt_t));
1073 for(
int i = 0; i < nb_steps; i++)
1076 msg(2,
"-----------------------------------------------------------------" << endl);
1077 msg(2,
" STEP # " << i <<
" / " << nb_steps << endl);
1078 msg(2,
"-----------------------------------------------------------------" << endl);
1079 set_current_c_s(1. -
flt_t(i) / (nb_steps - 1));
1080 minimize_using_cattail_from(state);
1083 ct_set_max_iterations(50);
1084 minimize_using_cattail_from(state);
1086 inside_julien_method =
false;
1093 alloc_matrices(count_measures());
1094 flt_t b0[MAX_B_SIZE];
1095 flt_t b[MAX_B_SIZE];
1099 for (observation_vector::iterator it = observations.begin();
1100 it != observations.end(); ++it)
1102 cout <<
"OBS #" << obsnb++ << endl;
1107 set_new_state(state0);
1110 for(
int j = 0; j < state_size; j++)
1112 for(
int k = 0; k < state_size; k++)
1113 new_state[k] = state0[k];
1114 new_state[j] += state_step;
1116 set_new_state(new_state);
1119 for (
int i=0; i<n; i++) {
1120 flt_t analytic = J[i*state_size + j];
1121 flt_t numeric = (b[i] - b0[i])/state_step;
1123 cout <<
" (df" << i <<
"/ds" << j <<
") = "
1124 << analytic <<
" = " << numeric << endl;
1136 add_observation(o,
true,
false);
1143 add_observation(o,
true,
false);
1150 add_observation(o,
true,
false);
1157 add_observation(o,
true,
false);