program.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2023 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  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: keir@google.com (Keir Mierle)
  30. #include "ceres/program.h"
  31. #include <algorithm>
  32. #include <map>
  33. #include <memory>
  34. #include <string>
  35. #include <vector>
  36. #include "ceres/array_utils.h"
  37. #include "ceres/casts.h"
  38. #include "ceres/compressed_row_sparse_matrix.h"
  39. #include "ceres/cost_function.h"
  40. #include "ceres/evaluator.h"
  41. #include "ceres/internal/export.h"
  42. #include "ceres/loss_function.h"
  43. #include "ceres/manifold.h"
  44. #include "ceres/map_util.h"
  45. #include "ceres/parallel_for.h"
  46. #include "ceres/parameter_block.h"
  47. #include "ceres/problem.h"
  48. #include "ceres/residual_block.h"
  49. #include "ceres/stl_util.h"
  50. #include "ceres/triplet_sparse_matrix.h"
  51. namespace ceres::internal {
  52. const std::vector<ParameterBlock*>& Program::parameter_blocks() const {
  53. return parameter_blocks_;
  54. }
  55. const std::vector<ResidualBlock*>& Program::residual_blocks() const {
  56. return residual_blocks_;
  57. }
  58. std::vector<ParameterBlock*>* Program::mutable_parameter_blocks() {
  59. return &parameter_blocks_;
  60. }
  61. std::vector<ResidualBlock*>* Program::mutable_residual_blocks() {
  62. return &residual_blocks_;
  63. }
  64. EvaluationCallback* Program::mutable_evaluation_callback() {
  65. return evaluation_callback_;
  66. }
  67. bool Program::StateVectorToParameterBlocks(const double* state) {
  68. for (auto* parameter_block : parameter_blocks_) {
  69. if (!parameter_block->IsConstant() && !parameter_block->SetState(state)) {
  70. return false;
  71. }
  72. state += parameter_block->Size();
  73. }
  74. return true;
  75. }
  76. void Program::ParameterBlocksToStateVector(double* state) const {
  77. for (auto* parameter_block : parameter_blocks_) {
  78. parameter_block->GetState(state);
  79. state += parameter_block->Size();
  80. }
  81. }
  82. void Program::CopyParameterBlockStateToUserState() {
  83. for (auto* parameter_block : parameter_blocks_) {
  84. parameter_block->GetState(parameter_block->mutable_user_state());
  85. }
  86. }
  87. bool Program::SetParameterBlockStatePtrsToUserStatePtrs() {
  88. for (auto* parameter_block : parameter_blocks_) {
  89. if (!parameter_block->IsConstant() &&
  90. !parameter_block->SetState(parameter_block->user_state())) {
  91. return false;
  92. }
  93. }
  94. return true;
  95. }
  96. bool Program::Plus(const double* state,
  97. const double* delta,
  98. double* state_plus_delta,
  99. ContextImpl* context,
  100. int num_threads) const {
  101. std::atomic<bool> abort(false);
  102. auto* parameter_blocks = parameter_blocks_.data();
  103. ParallelFor(
  104. context,
  105. 0,
  106. parameter_blocks_.size(),
  107. num_threads,
  108. [&abort, state, delta, state_plus_delta, parameter_blocks](int block_id) {
  109. if (abort) {
  110. return;
  111. }
  112. auto parameter_block = parameter_blocks[block_id];
  113. auto block_state = state + parameter_block->state_offset();
  114. auto block_delta = delta + parameter_block->delta_offset();
  115. auto block_state_plus_delta =
  116. state_plus_delta + parameter_block->state_offset();
  117. if (!parameter_block->Plus(
  118. block_state, block_delta, block_state_plus_delta)) {
  119. abort = true;
  120. }
  121. });
  122. return abort == false;
  123. }
  124. void Program::SetParameterOffsetsAndIndex() {
  125. // Set positions for all parameters appearing as arguments to residuals to one
  126. // past the end of the parameter block array.
  127. for (auto* residual_block : residual_blocks_) {
  128. for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) {
  129. residual_block->parameter_blocks()[j]->set_index(-1);
  130. }
  131. }
  132. // For parameters that appear in the program, set their position and offset.
  133. int state_offset = 0;
  134. int delta_offset = 0;
  135. for (int i = 0; i < parameter_blocks_.size(); ++i) {
  136. parameter_blocks_[i]->set_index(i);
  137. parameter_blocks_[i]->set_state_offset(state_offset);
  138. parameter_blocks_[i]->set_delta_offset(delta_offset);
  139. state_offset += parameter_blocks_[i]->Size();
  140. delta_offset += parameter_blocks_[i]->TangentSize();
  141. }
  142. }
  143. bool Program::IsValid() const {
  144. for (int i = 0; i < residual_blocks_.size(); ++i) {
  145. const ResidualBlock* residual_block = residual_blocks_[i];
  146. if (residual_block->index() != i) {
  147. LOG(WARNING) << "Residual block: " << i
  148. << " has incorrect index: " << residual_block->index();
  149. return false;
  150. }
  151. }
  152. int state_offset = 0;
  153. int delta_offset = 0;
  154. for (int i = 0; i < parameter_blocks_.size(); ++i) {
  155. const ParameterBlock* parameter_block = parameter_blocks_[i];
  156. if (parameter_block->index() != i ||
  157. parameter_block->state_offset() != state_offset ||
  158. parameter_block->delta_offset() != delta_offset) {
  159. LOG(WARNING) << "Parameter block: " << i
  160. << "has incorrect indexing information: "
  161. << parameter_block->ToString();
  162. return false;
  163. }
  164. state_offset += parameter_blocks_[i]->Size();
  165. delta_offset += parameter_blocks_[i]->TangentSize();
  166. }
  167. return true;
  168. }
  169. bool Program::ParameterBlocksAreFinite(std::string* message) const {
  170. CHECK(message != nullptr);
  171. for (auto* parameter_block : parameter_blocks_) {
  172. const double* array = parameter_block->user_state();
  173. const int size = parameter_block->Size();
  174. const int invalid_index = FindInvalidValue(size, array);
  175. if (invalid_index != size) {
  176. *message = StringPrintf(
  177. "ParameterBlock: %p with size %d has at least one invalid value.\n"
  178. "First invalid value is at index: %d.\n"
  179. "Parameter block values: ",
  180. array,
  181. size,
  182. invalid_index);
  183. AppendArrayToString(size, array, message);
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. bool Program::IsBoundsConstrained() const {
  190. for (auto* parameter_block : parameter_blocks_) {
  191. if (parameter_block->IsConstant()) {
  192. continue;
  193. }
  194. const int size = parameter_block->Size();
  195. for (int j = 0; j < size; ++j) {
  196. const double lower_bound = parameter_block->LowerBoundForParameter(j);
  197. const double upper_bound = parameter_block->UpperBoundForParameter(j);
  198. if (lower_bound > -std::numeric_limits<double>::max() ||
  199. upper_bound < std::numeric_limits<double>::max()) {
  200. return true;
  201. }
  202. }
  203. }
  204. return false;
  205. }
  206. bool Program::IsFeasible(std::string* message) const {
  207. CHECK(message != nullptr);
  208. for (auto* parameter_block : parameter_blocks_) {
  209. const double* parameters = parameter_block->user_state();
  210. const int size = parameter_block->Size();
  211. if (parameter_block->IsConstant()) {
  212. // Constant parameter blocks must start in the feasible region
  213. // to ultimately produce a feasible solution, since Ceres cannot
  214. // change them.
  215. for (int j = 0; j < size; ++j) {
  216. const double lower_bound = parameter_block->LowerBoundForParameter(j);
  217. const double upper_bound = parameter_block->UpperBoundForParameter(j);
  218. if (parameters[j] < lower_bound || parameters[j] > upper_bound) {
  219. *message = StringPrintf(
  220. "ParameterBlock: %p with size %d has at least one infeasible "
  221. "value."
  222. "\nFirst infeasible value is at index: %d."
  223. "\nLower bound: %e, value: %e, upper bound: %e"
  224. "\nParameter block values: ",
  225. parameters,
  226. size,
  227. j,
  228. lower_bound,
  229. parameters[j],
  230. upper_bound);
  231. AppendArrayToString(size, parameters, message);
  232. return false;
  233. }
  234. }
  235. } else {
  236. // Variable parameter blocks must have non-empty feasible
  237. // regions, otherwise there is no way to produce a feasible
  238. // solution.
  239. for (int j = 0; j < size; ++j) {
  240. const double lower_bound = parameter_block->LowerBoundForParameter(j);
  241. const double upper_bound = parameter_block->UpperBoundForParameter(j);
  242. if (lower_bound >= upper_bound) {
  243. *message = StringPrintf(
  244. "ParameterBlock: %p with size %d has at least one infeasible "
  245. "bound."
  246. "\nFirst infeasible bound is at index: %d."
  247. "\nLower bound: %e, upper bound: %e"
  248. "\nParameter block values: ",
  249. parameters,
  250. size,
  251. j,
  252. lower_bound,
  253. upper_bound);
  254. AppendArrayToString(size, parameters, message);
  255. return false;
  256. }
  257. }
  258. }
  259. }
  260. return true;
  261. }
  262. std::unique_ptr<Program> Program::CreateReducedProgram(
  263. std::vector<double*>* removed_parameter_blocks,
  264. double* fixed_cost,
  265. std::string* error) const {
  266. CHECK(removed_parameter_blocks != nullptr);
  267. CHECK(fixed_cost != nullptr);
  268. CHECK(error != nullptr);
  269. std::unique_ptr<Program> reduced_program = std::make_unique<Program>(*this);
  270. if (!reduced_program->RemoveFixedBlocks(
  271. removed_parameter_blocks, fixed_cost, error)) {
  272. return nullptr;
  273. }
  274. reduced_program->SetParameterOffsetsAndIndex();
  275. return reduced_program;
  276. }
  277. bool Program::RemoveFixedBlocks(std::vector<double*>* removed_parameter_blocks,
  278. double* fixed_cost,
  279. std::string* error) {
  280. CHECK(removed_parameter_blocks != nullptr);
  281. CHECK(fixed_cost != nullptr);
  282. CHECK(error != nullptr);
  283. std::unique_ptr<double[]> residual_block_evaluate_scratch;
  284. residual_block_evaluate_scratch =
  285. std::make_unique<double[]>(MaxScratchDoublesNeededForEvaluate());
  286. *fixed_cost = 0.0;
  287. bool need_to_call_prepare_for_evaluation = evaluation_callback_ != nullptr;
  288. // Mark all the parameters as unused. Abuse the index member of the
  289. // parameter blocks for the marking.
  290. for (auto* parameter_block : parameter_blocks_) {
  291. parameter_block->set_index(-1);
  292. }
  293. // Filter out residual that have all-constant parameters, and mark
  294. // all the parameter blocks that appear in residuals.
  295. int num_active_residual_blocks = 0;
  296. for (int i = 0; i < residual_blocks_.size(); ++i) {
  297. ResidualBlock* residual_block = residual_blocks_[i];
  298. int num_parameter_blocks = residual_block->NumParameterBlocks();
  299. // Determine if the residual block is fixed, and also mark varying
  300. // parameters that appear in the residual block.
  301. bool all_constant = true;
  302. for (int k = 0; k < num_parameter_blocks; k++) {
  303. ParameterBlock* parameter_block = residual_block->parameter_blocks()[k];
  304. if (!parameter_block->IsConstant()) {
  305. all_constant = false;
  306. parameter_block->set_index(1);
  307. }
  308. }
  309. if (!all_constant) {
  310. residual_blocks_[num_active_residual_blocks++] = residual_block;
  311. continue;
  312. }
  313. // This is an exceedingly rare case, where the user has residual
  314. // blocks which are effectively constant but they are also
  315. // performance sensitive enough to add an EvaluationCallback.
  316. //
  317. // In this case before we evaluate the cost of the constant
  318. // residual blocks, we must call
  319. // EvaluationCallback::PrepareForEvaluation(). Because this call
  320. // can be costly, we only call this if we actually encounter a
  321. // residual block with all constant parameter blocks.
  322. //
  323. // It is worth nothing that there is a minor inefficiency here,
  324. // that the iteration 0 of TrustRegionMinimizer will also cause
  325. // PrepareForEvaluation to be called on the same point, but with
  326. // evaluate_jacobians = true. We could try and optimize this here,
  327. // but given the rarity of this case, the additional complexity
  328. // and long range dependency is not worth it.
  329. if (need_to_call_prepare_for_evaluation) {
  330. constexpr bool kNewPoint = true;
  331. constexpr bool kDoNotEvaluateJacobians = false;
  332. evaluation_callback_->PrepareForEvaluation(kDoNotEvaluateJacobians,
  333. kNewPoint);
  334. need_to_call_prepare_for_evaluation = false;
  335. }
  336. // The residual is constant and will be removed, so its cost is
  337. // added to the variable fixed_cost.
  338. double cost = 0.0;
  339. if (!residual_block->Evaluate(true,
  340. &cost,
  341. nullptr,
  342. nullptr,
  343. residual_block_evaluate_scratch.get())) {
  344. *error = StringPrintf(
  345. "Evaluation of the residual %d failed during "
  346. "removal of fixed residual blocks.",
  347. i);
  348. return false;
  349. }
  350. *fixed_cost += cost;
  351. }
  352. residual_blocks_.resize(num_active_residual_blocks);
  353. // Filter out unused or fixed parameter blocks.
  354. int num_active_parameter_blocks = 0;
  355. removed_parameter_blocks->clear();
  356. for (auto* parameter_block : parameter_blocks_) {
  357. if (parameter_block->index() == -1) {
  358. removed_parameter_blocks->push_back(
  359. parameter_block->mutable_user_state());
  360. } else {
  361. parameter_blocks_[num_active_parameter_blocks++] = parameter_block;
  362. }
  363. }
  364. parameter_blocks_.resize(num_active_parameter_blocks);
  365. if (!(((NumResidualBlocks() == 0) && (NumParameterBlocks() == 0)) ||
  366. ((NumResidualBlocks() != 0) && (NumParameterBlocks() != 0)))) {
  367. *error = "Congratulations, you found a bug in Ceres. Please report it.";
  368. return false;
  369. }
  370. return true;
  371. }
  372. bool Program::IsParameterBlockSetIndependent(
  373. const std::set<double*>& independent_set) const {
  374. // Loop over each residual block and ensure that no two parameter
  375. // blocks in the same residual block are part of
  376. // parameter_block_ptrs as that would violate the assumption that it
  377. // is an independent set in the Hessian matrix.
  378. for (const ResidualBlock* residual_block : residual_blocks_) {
  379. ParameterBlock* const* parameter_blocks =
  380. residual_block->parameter_blocks();
  381. const int num_parameter_blocks = residual_block->NumParameterBlocks();
  382. int count = 0;
  383. for (int i = 0; i < num_parameter_blocks; ++i) {
  384. count += independent_set.count(parameter_blocks[i]->mutable_user_state());
  385. }
  386. if (count > 1) {
  387. return false;
  388. }
  389. }
  390. return true;
  391. }
  392. std::unique_ptr<TripletSparseMatrix>
  393. Program::CreateJacobianBlockSparsityTranspose(int start_residual_block) const {
  394. // Matrix to store the block sparsity structure of the Jacobian.
  395. const int num_rows = NumParameterBlocks();
  396. const int num_cols = NumResidualBlocks() - start_residual_block;
  397. std::unique_ptr<TripletSparseMatrix> tsm(
  398. new TripletSparseMatrix(num_rows, num_cols, 10 * num_cols));
  399. int num_nonzeros = 0;
  400. int* rows = tsm->mutable_rows();
  401. int* cols = tsm->mutable_cols();
  402. double* values = tsm->mutable_values();
  403. for (int c = start_residual_block; c < residual_blocks_.size(); ++c) {
  404. const ResidualBlock* residual_block = residual_blocks_[c];
  405. const int num_parameter_blocks = residual_block->NumParameterBlocks();
  406. ParameterBlock* const* parameter_blocks =
  407. residual_block->parameter_blocks();
  408. for (int j = 0; j < num_parameter_blocks; ++j) {
  409. if (parameter_blocks[j]->IsConstant()) {
  410. continue;
  411. }
  412. // Re-size the matrix if needed.
  413. if (num_nonzeros >= tsm->max_num_nonzeros()) {
  414. tsm->set_num_nonzeros(num_nonzeros);
  415. tsm->Reserve(2 * num_nonzeros);
  416. rows = tsm->mutable_rows();
  417. cols = tsm->mutable_cols();
  418. values = tsm->mutable_values();
  419. }
  420. const int r = parameter_blocks[j]->index();
  421. rows[num_nonzeros] = r;
  422. cols[num_nonzeros] = c - start_residual_block;
  423. values[num_nonzeros] = 1.0;
  424. ++num_nonzeros;
  425. }
  426. }
  427. tsm->set_num_nonzeros(num_nonzeros);
  428. return tsm;
  429. }
  430. int Program::NumResidualBlocks() const { return residual_blocks_.size(); }
  431. int Program::NumParameterBlocks() const { return parameter_blocks_.size(); }
  432. int Program::NumResiduals() const {
  433. int num_residuals = 0;
  434. for (auto* residual_block : residual_blocks_) {
  435. num_residuals += residual_block->NumResiduals();
  436. }
  437. return num_residuals;
  438. }
  439. int Program::NumParameters() const {
  440. int num_parameters = 0;
  441. for (auto* parameter_block : parameter_blocks_) {
  442. num_parameters += parameter_block->Size();
  443. }
  444. return num_parameters;
  445. }
  446. int Program::NumEffectiveParameters() const {
  447. int num_parameters = 0;
  448. for (auto* parameter_block : parameter_blocks_) {
  449. num_parameters += parameter_block->TangentSize();
  450. }
  451. return num_parameters;
  452. }
  453. // TODO(sameeragarwal): The following methods should just be updated
  454. // incrementally and the values cached, rather than the linear
  455. // complexity we have right now on every call.
  456. int Program::MaxScratchDoublesNeededForEvaluate() const {
  457. // Compute the scratch space needed for evaluate.
  458. int max_scratch_bytes_for_evaluate = 0;
  459. for (auto* residual_block : residual_blocks_) {
  460. max_scratch_bytes_for_evaluate =
  461. std::max(max_scratch_bytes_for_evaluate,
  462. residual_block->NumScratchDoublesForEvaluate());
  463. }
  464. return max_scratch_bytes_for_evaluate;
  465. }
  466. int Program::MaxDerivativesPerResidualBlock() const {
  467. int max_derivatives = 0;
  468. for (auto* residual_block : residual_blocks_) {
  469. int derivatives = 0;
  470. int num_parameters = residual_block->NumParameterBlocks();
  471. for (int j = 0; j < num_parameters; ++j) {
  472. derivatives += residual_block->NumResiduals() *
  473. residual_block->parameter_blocks()[j]->TangentSize();
  474. }
  475. max_derivatives = std::max(max_derivatives, derivatives);
  476. }
  477. return max_derivatives;
  478. }
  479. int Program::MaxParametersPerResidualBlock() const {
  480. int max_parameters = 0;
  481. for (auto* residual_block : residual_blocks_) {
  482. max_parameters =
  483. std::max(max_parameters, residual_block->NumParameterBlocks());
  484. }
  485. return max_parameters;
  486. }
  487. int Program::MaxResidualsPerResidualBlock() const {
  488. int max_residuals = 0;
  489. for (auto* residual_block : residual_blocks_) {
  490. max_residuals = std::max(max_residuals, residual_block->NumResiduals());
  491. }
  492. return max_residuals;
  493. }
  494. std::string Program::ToString() const {
  495. std::string ret = "Program dump\n";
  496. ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks());
  497. ret += StringPrintf("Number of parameters: %d\n", NumParameters());
  498. ret += "Parameters:\n";
  499. for (int i = 0; i < parameter_blocks_.size(); ++i) {
  500. ret +=
  501. StringPrintf("%d: %s\n", i, parameter_blocks_[i]->ToString().c_str());
  502. }
  503. return ret;
  504. }
  505. } // namespace ceres::internal