StateUpdatingCallback was being initialized with the wrong array. StateUpdatingCallback updates the user's parameter blocks in every iteration if the user so desires. The callback depends on having access to an array that the minimizer is using internally to do all the work. This is probably poor design. As a consequence of this design, it is easy to initialize the callback with the wrong array, which was the case here. It was being initialized with the array of initial parameters, which the minimizer does not touch, rather than the array final_parameters, which just happens to the one in which the Minimizer does all the work. Testing this change is a pain, because nothing is wrong with the Callback object, but rather the way it was being instantiated by SolverImpl, and the only way to test would be to test the whole Solve call.
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 834ec0d..2ec3dee 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -134,7 +134,7 @@ minimizer_options.callbacks.push_back(&logging_callback); } - StateUpdatingCallback updating_callback(program, initial_parameters); + StateUpdatingCallback updating_callback(program, final_parameters); if (options.update_state_every_iteration) { minimizer_options.callbacks.push_back(&updating_callback); }