Lazily initialize the bounds arrays in ParameterBlock.
Problems that do not use bounds do not have to pay the
price of storing bounds constraints.
Also replace the raw pointer access to the upper and
lower bounds arrays with accessors which hides the
lazy initialization from the user.
Change-Id: I0325a35de9c29f853559f891e32e7c777686e537
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
index 6ae2c90..2bf6cd2 100644
--- a/internal/ceres/solver_impl.cc
+++ b/internal/ceres/solver_impl.cc
@@ -328,16 +328,16 @@
bool IsBoundsConstrained(const Program& program) {
const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
for (int i = 0; i < parameter_blocks.size(); ++i) {
- if (parameter_blocks[i]->IsConstant()) {
+ const ParameterBlock* parameter_block = parameter_blocks[i];
+ if (parameter_block->IsConstant()) {
continue;
}
-
- const double* lower_bounds = parameter_blocks[i]->lower_bounds();
- const double* upper_bounds = parameter_blocks[i]->upper_bounds();
- const int size = parameter_blocks[i]->Size();
+ const int size = parameter_block->Size();
for (int j = 0; j < size; ++j) {
- if (lower_bounds[j] > -std::numeric_limits<double>::max() ||
- upper_bounds[j] < std::numeric_limits<double>::max()) {
+ const double lower_bound = parameter_block->LowerBoundForParameter(j);
+ const double upper_bound = parameter_block->UpperBoundForParameter(j);
+ if (lower_bound > -std::numeric_limits<double>::max() ||
+ upper_bound < std::numeric_limits<double>::max()) {
return true;
}
}
@@ -353,24 +353,25 @@
const Program& program = problem->program();
const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
for (int i = 0; i < parameter_blocks.size(); ++i) {
- const double* array = parameter_blocks[i]->user_state();
- const double* lower_bounds = parameter_blocks[i]->lower_bounds();
- const double* upper_bounds = parameter_blocks[i]->upper_bounds();
- const int size = parameter_blocks[i]->Size();
- if (parameter_blocks[i]->IsConstant()) {
+ const ParameterBlock* parameter_block = parameter_blocks[i];
+ const double* parameters = parameter_block->user_state();
+ const int size = parameter_block->Size();
+ if (parameter_block->IsConstant()) {
// Constant parameter blocks must start in the feasible region
// to ultimately produce a feasible solution, since Ceres cannot
// change them.
for (int j = 0; j < size; ++j) {
- if (array[j] < lower_bounds[j] || array[j] > upper_bounds[j]) {
+ const double lower_bound = parameter_block->LowerBoundForParameter(j);
+ const double upper_bound = parameter_block->UpperBoundForParameter(j);
+ if (parameters[j] < lower_bound || parameters[j] > upper_bound) {
*message = StringPrintf(
"ParameterBlock: %p with size %d has at least one infeasible "
"value."
"\nFirst infeasible value is at index: %d."
"\nLower bound: %e, value: %e, upper bound: %e"
"\nParameter block values: ",
- array, size, j, lower_bounds[j], array[j], upper_bounds[j]);
- AppendArrayToString(size, array, message);
+ parameters, size, j, lower_bound, parameters[j], upper_bound);
+ AppendArrayToString(size, parameters, message);
return false;
}
}
@@ -379,15 +380,17 @@
// regions, otherwise there is no way to produce a feasible
// solution.
for (int j = 0; j < size; ++j) {
- if (lower_bounds[j] >= upper_bounds[j]) {
+ const double lower_bound = parameter_block->LowerBoundForParameter(j);
+ const double upper_bound = parameter_block->UpperBoundForParameter(j);
+ if (lower_bound >= upper_bound) {
*message = StringPrintf(
"ParameterBlock: %p with size %d has at least one infeasible "
"bound."
"\nFirst infeasible bound is at index: %d."
"\nLower bound: %e, upper bound: %e"
"\nParameter block values: ",
- array, size, j, lower_bounds[j], upper_bounds[j]);
- AppendArrayToString(size, array, message);
+ parameters, size, j, lower_bound, upper_bound);
+ AppendArrayToString(size, parameters, message);
return false;
}
}