problem_impl.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2022 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: sameeragarwal@google.com (Sameer Agarwal)
  30. // mierle@gmail.com (Keir Mierle)
  31. #include "ceres/problem_impl.h"
  32. #include <algorithm>
  33. #include <cstddef>
  34. #include <cstdint>
  35. #include <iterator>
  36. #include <memory>
  37. #include <set>
  38. #include <string>
  39. #include <utility>
  40. #include <vector>
  41. #include "ceres/casts.h"
  42. #include "ceres/compressed_row_jacobian_writer.h"
  43. #include "ceres/compressed_row_sparse_matrix.h"
  44. #include "ceres/context_impl.h"
  45. #include "ceres/cost_function.h"
  46. #include "ceres/crs_matrix.h"
  47. #include "ceres/evaluation_callback.h"
  48. #include "ceres/evaluator.h"
  49. #include "ceres/internal/export.h"
  50. #include "ceres/internal/fixed_array.h"
  51. #include "ceres/loss_function.h"
  52. #include "ceres/manifold.h"
  53. #include "ceres/map_util.h"
  54. #include "ceres/parameter_block.h"
  55. #include "ceres/program.h"
  56. #include "ceres/program_evaluator.h"
  57. #include "ceres/residual_block.h"
  58. #include "ceres/scratch_evaluate_preparer.h"
  59. #include "ceres/stl_util.h"
  60. #include "ceres/stringprintf.h"
  61. #include "glog/logging.h"
  62. namespace ceres::internal {
  63. namespace {
  64. // Returns true if two regions of memory, a and b, with sizes size_a and size_b
  65. // respectively, overlap.
  66. bool RegionsAlias(const double* a, int size_a, const double* b, int size_b) {
  67. return (a < b) ? b < (a + size_a) : a < (b + size_b);
  68. }
  69. void CheckForNoAliasing(double* existing_block,
  70. int existing_block_size,
  71. double* new_block,
  72. int new_block_size) {
  73. CHECK(!RegionsAlias(
  74. existing_block, existing_block_size, new_block, new_block_size))
  75. << "Aliasing detected between existing parameter block at memory "
  76. << "location " << existing_block << " and has size "
  77. << existing_block_size << " with new parameter "
  78. << "block that has memory address " << new_block << " and would have "
  79. << "size " << new_block_size << ".";
  80. }
  81. template <typename KeyType>
  82. void DecrementValueOrDeleteKey(const KeyType key,
  83. std::map<KeyType, int>* container) {
  84. auto it = container->find(key);
  85. if (it->second == 1) {
  86. delete key;
  87. container->erase(it);
  88. } else {
  89. --it->second;
  90. }
  91. }
  92. template <typename ForwardIterator>
  93. void STLDeleteContainerPairFirstPointers(ForwardIterator begin,
  94. ForwardIterator end) {
  95. while (begin != end) {
  96. delete begin->first;
  97. ++begin;
  98. }
  99. }
  100. void InitializeContext(Context* context,
  101. ContextImpl** context_impl,
  102. bool* context_impl_owned) {
  103. if (context == nullptr) {
  104. *context_impl_owned = true;
  105. *context_impl = new ContextImpl;
  106. } else {
  107. *context_impl_owned = false;
  108. *context_impl = down_cast<ContextImpl*>(context);
  109. }
  110. }
  111. } // namespace
  112. ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values,
  113. int size) {
  114. CHECK(values != nullptr) << "Null pointer passed to AddParameterBlock "
  115. << "for a parameter with size " << size;
  116. // Ignore the request if there is a block for the given pointer already.
  117. auto it = parameter_block_map_.find(values);
  118. if (it != parameter_block_map_.end()) {
  119. if (!options_.disable_all_safety_checks) {
  120. int existing_size = it->second->Size();
  121. CHECK(size == existing_size)
  122. << "Tried adding a parameter block with the same double pointer, "
  123. << values << ", twice, but with different block sizes. Original "
  124. << "size was " << existing_size << " but new size is " << size;
  125. }
  126. return it->second;
  127. }
  128. if (!options_.disable_all_safety_checks) {
  129. // Before adding the parameter block, also check that it doesn't alias any
  130. // other parameter blocks.
  131. if (!parameter_block_map_.empty()) {
  132. auto lb = parameter_block_map_.lower_bound(values);
  133. // If lb is not the first block, check the previous block for aliasing.
  134. if (lb != parameter_block_map_.begin()) {
  135. auto previous = lb;
  136. --previous;
  137. CheckForNoAliasing(
  138. previous->first, previous->second->Size(), values, size);
  139. }
  140. // If lb is not off the end, check lb for aliasing.
  141. if (lb != parameter_block_map_.end()) {
  142. CheckForNoAliasing(lb->first, lb->second->Size(), values, size);
  143. }
  144. }
  145. }
  146. // Pass the index of the new parameter block as well to keep the index in
  147. // sync with the position of the parameter in the program's parameter vector.
  148. auto* new_parameter_block =
  149. new ParameterBlock(values, size, program_->parameter_blocks_.size());
  150. // For dynamic problems, add the list of dependent residual blocks, which is
  151. // empty to start.
  152. if (options_.enable_fast_removal) {
  153. new_parameter_block->EnableResidualBlockDependencies();
  154. }
  155. parameter_block_map_[values] = new_parameter_block;
  156. program_->parameter_blocks_.push_back(new_parameter_block);
  157. return new_parameter_block;
  158. }
  159. void ProblemImpl::InternalRemoveResidualBlock(ResidualBlock* residual_block) {
  160. CHECK(residual_block != nullptr);
  161. // Perform no check on the validity of residual_block, that is handled in
  162. // the public method: RemoveResidualBlock().
  163. // If needed, remove the parameter dependencies on this residual block.
  164. if (options_.enable_fast_removal) {
  165. const int num_parameter_blocks_for_residual =
  166. residual_block->NumParameterBlocks();
  167. for (int i = 0; i < num_parameter_blocks_for_residual; ++i) {
  168. residual_block->parameter_blocks()[i]->RemoveResidualBlock(
  169. residual_block);
  170. }
  171. auto it = residual_block_set_.find(residual_block);
  172. residual_block_set_.erase(it);
  173. }
  174. DeleteBlockInVector(program_->mutable_residual_blocks(), residual_block);
  175. }
  176. // Deletes the residual block in question, assuming there are no other
  177. // references to it inside the problem (e.g. by another parameter). Referenced
  178. // cost and loss functions are tucked away for future deletion, since it is not
  179. // possible to know whether other parts of the problem depend on them without
  180. // doing a full scan.
  181. void ProblemImpl::DeleteBlock(ResidualBlock* residual_block) {
  182. // The const casts here are legit, since ResidualBlock holds these
  183. // pointers as const pointers but we have ownership of them and
  184. // have the right to destroy them when the destructor is called.
  185. auto* cost_function =
  186. const_cast<CostFunction*>(residual_block->cost_function());
  187. if (options_.cost_function_ownership == TAKE_OWNERSHIP) {
  188. DecrementValueOrDeleteKey(cost_function, &cost_function_ref_count_);
  189. }
  190. auto* loss_function =
  191. const_cast<LossFunction*>(residual_block->loss_function());
  192. if (options_.loss_function_ownership == TAKE_OWNERSHIP &&
  193. loss_function != nullptr) {
  194. DecrementValueOrDeleteKey(loss_function, &loss_function_ref_count_);
  195. }
  196. delete residual_block;
  197. }
  198. // Deletes the parameter block in question, assuming there are no other
  199. // references to it inside the problem (e.g. by any residual blocks).
  200. void ProblemImpl::DeleteBlock(ParameterBlock* parameter_block) {
  201. parameter_block_map_.erase(parameter_block->mutable_user_state());
  202. delete parameter_block;
  203. }
  204. ProblemImpl::ProblemImpl()
  205. : options_(Problem::Options()), program_(new internal::Program) {
  206. InitializeContext(options_.context, &context_impl_, &context_impl_owned_);
  207. }
  208. ProblemImpl::ProblemImpl(const Problem::Options& options)
  209. : options_(options), program_(new internal::Program) {
  210. program_->evaluation_callback_ = options.evaluation_callback;
  211. InitializeContext(options_.context, &context_impl_, &context_impl_owned_);
  212. }
  213. ProblemImpl::~ProblemImpl() {
  214. STLDeleteContainerPointers(program_->residual_blocks_.begin(),
  215. program_->residual_blocks_.end());
  216. if (options_.cost_function_ownership == TAKE_OWNERSHIP) {
  217. STLDeleteContainerPairFirstPointers(cost_function_ref_count_.begin(),
  218. cost_function_ref_count_.end());
  219. }
  220. if (options_.loss_function_ownership == TAKE_OWNERSHIP) {
  221. STLDeleteContainerPairFirstPointers(loss_function_ref_count_.begin(),
  222. loss_function_ref_count_.end());
  223. }
  224. // Collect the unique parameterizations and delete the parameters.
  225. for (auto* parameter_block : program_->parameter_blocks_) {
  226. DeleteBlock(parameter_block);
  227. }
  228. // Delete the owned manifolds.
  229. STLDeleteUniqueContainerPointers(manifolds_to_delete_.begin(),
  230. manifolds_to_delete_.end());
  231. if (context_impl_owned_) {
  232. delete context_impl_;
  233. }
  234. }
  235. ResidualBlockId ProblemImpl::AddResidualBlock(
  236. CostFunction* cost_function,
  237. LossFunction* loss_function,
  238. double* const* const parameter_blocks,
  239. int num_parameter_blocks) {
  240. CHECK(cost_function != nullptr);
  241. CHECK_EQ(num_parameter_blocks, cost_function->parameter_block_sizes().size());
  242. // Check the sizes match.
  243. const std::vector<int32_t>& parameter_block_sizes =
  244. cost_function->parameter_block_sizes();
  245. if (!options_.disable_all_safety_checks) {
  246. CHECK_EQ(parameter_block_sizes.size(), num_parameter_blocks)
  247. << "Number of blocks input is different than the number of blocks "
  248. << "that the cost function expects.";
  249. // Check for duplicate parameter blocks.
  250. std::vector<double*> sorted_parameter_blocks(
  251. parameter_blocks, parameter_blocks + num_parameter_blocks);
  252. sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end());
  253. const bool has_duplicate_items =
  254. (std::adjacent_find(sorted_parameter_blocks.begin(),
  255. sorted_parameter_blocks.end()) !=
  256. sorted_parameter_blocks.end());
  257. if (has_duplicate_items) {
  258. std::string blocks;
  259. for (int i = 0; i < num_parameter_blocks; ++i) {
  260. blocks += StringPrintf(" %p ", parameter_blocks[i]);
  261. }
  262. LOG(FATAL) << "Duplicate parameter blocks in a residual parameter "
  263. << "are not allowed. Parameter block pointers: [" << blocks
  264. << "]";
  265. }
  266. }
  267. // Add parameter blocks and convert the double*'s to parameter blocks.
  268. std::vector<ParameterBlock*> parameter_block_ptrs(num_parameter_blocks);
  269. for (int i = 0; i < num_parameter_blocks; ++i) {
  270. parameter_block_ptrs[i] = InternalAddParameterBlock(
  271. parameter_blocks[i], parameter_block_sizes[i]);
  272. }
  273. if (!options_.disable_all_safety_checks) {
  274. // Check that the block sizes match the block sizes expected by the
  275. // cost_function.
  276. for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
  277. CHECK_EQ(cost_function->parameter_block_sizes()[i],
  278. parameter_block_ptrs[i]->Size())
  279. << "The cost function expects parameter block " << i << " of size "
  280. << cost_function->parameter_block_sizes()[i]
  281. << " but was given a block of size "
  282. << parameter_block_ptrs[i]->Size();
  283. }
  284. }
  285. auto* new_residual_block =
  286. new ResidualBlock(cost_function,
  287. loss_function,
  288. parameter_block_ptrs,
  289. program_->residual_blocks_.size());
  290. // Add dependencies on the residual to the parameter blocks.
  291. if (options_.enable_fast_removal) {
  292. for (int i = 0; i < num_parameter_blocks; ++i) {
  293. parameter_block_ptrs[i]->AddResidualBlock(new_residual_block);
  294. }
  295. }
  296. program_->residual_blocks_.push_back(new_residual_block);
  297. if (options_.enable_fast_removal) {
  298. residual_block_set_.insert(new_residual_block);
  299. }
  300. if (options_.cost_function_ownership == TAKE_OWNERSHIP) {
  301. // Increment the reference count, creating an entry in the table if
  302. // needed. Note: C++ maps guarantee that new entries have default
  303. // constructed values; this implies integers are zero initialized.
  304. ++cost_function_ref_count_[cost_function];
  305. }
  306. if (options_.loss_function_ownership == TAKE_OWNERSHIP &&
  307. loss_function != nullptr) {
  308. ++loss_function_ref_count_[loss_function];
  309. }
  310. return new_residual_block;
  311. }
  312. void ProblemImpl::AddParameterBlock(double* values, int size) {
  313. InternalAddParameterBlock(values, size);
  314. }
  315. void ProblemImpl::InternalSetManifold(double* /*values*/,
  316. ParameterBlock* parameter_block,
  317. Manifold* manifold) {
  318. if (manifold != nullptr && options_.manifold_ownership == TAKE_OWNERSHIP) {
  319. manifolds_to_delete_.push_back(manifold);
  320. }
  321. parameter_block->SetManifold(manifold);
  322. }
  323. void ProblemImpl::AddParameterBlock(double* values,
  324. int size,
  325. Manifold* manifold) {
  326. ParameterBlock* parameter_block = InternalAddParameterBlock(values, size);
  327. InternalSetManifold(values, parameter_block, manifold);
  328. }
  329. // Delete a block from a vector of blocks, maintaining the indexing invariant.
  330. // This is done in constant time by moving an element from the end of the
  331. // vector over the element to remove, then popping the last element. It
  332. // destroys the ordering in the interest of speed.
  333. template <typename Block>
  334. void ProblemImpl::DeleteBlockInVector(std::vector<Block*>* mutable_blocks,
  335. Block* block_to_remove) {
  336. CHECK_EQ((*mutable_blocks)[block_to_remove->index()], block_to_remove)
  337. << "You found a Ceres bug! \n"
  338. << "Block requested: " << block_to_remove->ToString() << "\n"
  339. << "Block present: "
  340. << (*mutable_blocks)[block_to_remove->index()]->ToString();
  341. // Prepare the to-be-moved block for the new, lower-in-index position by
  342. // setting the index to the blocks final location.
  343. Block* tmp = mutable_blocks->back();
  344. tmp->set_index(block_to_remove->index());
  345. // Overwrite the to-be-deleted residual block with the one at the end.
  346. (*mutable_blocks)[block_to_remove->index()] = tmp;
  347. DeleteBlock(block_to_remove);
  348. // The block is gone so shrink the vector of blocks accordingly.
  349. mutable_blocks->pop_back();
  350. }
  351. void ProblemImpl::RemoveResidualBlock(ResidualBlock* residual_block) {
  352. CHECK(residual_block != nullptr);
  353. // Verify that residual_block identifies a residual in the current problem.
  354. const std::string residual_not_found_message = StringPrintf(
  355. "Residual block to remove: %p not found. This usually means "
  356. "one of three things have happened:\n"
  357. " 1) residual_block is uninitialised and points to a random "
  358. "area in memory.\n"
  359. " 2) residual_block represented a residual that was added to"
  360. " the problem, but referred to a parameter block which has "
  361. "since been removed, which removes all residuals which "
  362. "depend on that parameter block, and was thus removed.\n"
  363. " 3) residual_block referred to a residual that has already "
  364. "been removed from the problem (by the user).",
  365. residual_block);
  366. if (options_.enable_fast_removal) {
  367. CHECK(residual_block_set_.find(residual_block) != residual_block_set_.end())
  368. << residual_not_found_message;
  369. } else {
  370. // Perform a full search over all current residuals.
  371. CHECK(std::find(program_->residual_blocks().begin(),
  372. program_->residual_blocks().end(),
  373. residual_block) != program_->residual_blocks().end())
  374. << residual_not_found_message;
  375. }
  376. InternalRemoveResidualBlock(residual_block);
  377. }
  378. void ProblemImpl::RemoveParameterBlock(const double* values) {
  379. ParameterBlock* parameter_block = FindWithDefault(
  380. parameter_block_map_, const_cast<double*>(values), nullptr);
  381. if (parameter_block == nullptr) {
  382. LOG(FATAL) << "Parameter block not found: " << values
  383. << ". You must add the parameter block to the problem before "
  384. << "it can be removed.";
  385. }
  386. if (options_.enable_fast_removal) {
  387. // Copy the dependent residuals from the parameter block because the set of
  388. // dependents will change after each call to RemoveResidualBlock().
  389. std::vector<ResidualBlock*> residual_blocks_to_remove(
  390. parameter_block->mutable_residual_blocks()->begin(),
  391. parameter_block->mutable_residual_blocks()->end());
  392. for (auto* residual_block : residual_blocks_to_remove) {
  393. InternalRemoveResidualBlock(residual_block);
  394. }
  395. } else {
  396. // Scan all the residual blocks to remove ones that depend on the parameter
  397. // block. Do the scan backwards since the vector changes while iterating.
  398. const int num_residual_blocks = NumResidualBlocks();
  399. for (int i = num_residual_blocks - 1; i >= 0; --i) {
  400. ResidualBlock* residual_block =
  401. (*(program_->mutable_residual_blocks()))[i];
  402. const int num_parameter_blocks = residual_block->NumParameterBlocks();
  403. for (int j = 0; j < num_parameter_blocks; ++j) {
  404. if (residual_block->parameter_blocks()[j] == parameter_block) {
  405. InternalRemoveResidualBlock(residual_block);
  406. // The parameter blocks are guaranteed unique.
  407. break;
  408. }
  409. }
  410. }
  411. }
  412. DeleteBlockInVector(program_->mutable_parameter_blocks(), parameter_block);
  413. }
  414. void ProblemImpl::SetParameterBlockConstant(const double* values) {
  415. ParameterBlock* parameter_block = FindWithDefault(
  416. parameter_block_map_, const_cast<double*>(values), nullptr);
  417. if (parameter_block == nullptr) {
  418. LOG(FATAL) << "Parameter block not found: " << values
  419. << ". You must add the parameter block to the problem before "
  420. << "it can be set constant.";
  421. }
  422. parameter_block->SetConstant();
  423. }
  424. bool ProblemImpl::IsParameterBlockConstant(const double* values) const {
  425. const ParameterBlock* parameter_block = FindWithDefault(
  426. parameter_block_map_, const_cast<double*>(values), nullptr);
  427. CHECK(parameter_block != nullptr)
  428. << "Parameter block not found: " << values << ". You must add the "
  429. << "parameter block to the problem before it can be queried.";
  430. return parameter_block->IsConstant();
  431. }
  432. void ProblemImpl::SetParameterBlockVariable(double* values) {
  433. ParameterBlock* parameter_block =
  434. FindWithDefault(parameter_block_map_, values, nullptr);
  435. if (parameter_block == nullptr) {
  436. LOG(FATAL) << "Parameter block not found: " << values
  437. << ". You must add the parameter block to the problem before "
  438. << "it can be set varying.";
  439. }
  440. parameter_block->SetVarying();
  441. }
  442. void ProblemImpl::SetManifold(double* values, Manifold* manifold) {
  443. ParameterBlock* parameter_block =
  444. FindWithDefault(parameter_block_map_, values, nullptr);
  445. if (parameter_block == nullptr) {
  446. LOG(FATAL) << "Parameter block not found: " << values
  447. << ". You must add the parameter block to the problem before "
  448. << "you can set its manifold.";
  449. }
  450. InternalSetManifold(values, parameter_block, manifold);
  451. }
  452. const Manifold* ProblemImpl::GetManifold(const double* values) const {
  453. ParameterBlock* parameter_block = FindWithDefault(
  454. parameter_block_map_, const_cast<double*>(values), nullptr);
  455. if (parameter_block == nullptr) {
  456. LOG(FATAL) << "Parameter block not found: " << values
  457. << ". You must add the parameter block to the problem before "
  458. << "you can get its manifold.";
  459. }
  460. return parameter_block->manifold();
  461. }
  462. bool ProblemImpl::HasManifold(const double* values) const {
  463. return GetManifold(values) != nullptr;
  464. }
  465. void ProblemImpl::SetParameterLowerBound(double* values,
  466. int index,
  467. double lower_bound) {
  468. ParameterBlock* parameter_block =
  469. FindWithDefault(parameter_block_map_, values, nullptr);
  470. if (parameter_block == nullptr) {
  471. LOG(FATAL) << "Parameter block not found: " << values
  472. << ". You must add the parameter block to the problem before "
  473. << "you can set a lower bound on one of its components.";
  474. }
  475. parameter_block->SetLowerBound(index, lower_bound);
  476. }
  477. void ProblemImpl::SetParameterUpperBound(double* values,
  478. int index,
  479. double upper_bound) {
  480. ParameterBlock* parameter_block =
  481. FindWithDefault(parameter_block_map_, values, nullptr);
  482. if (parameter_block == nullptr) {
  483. LOG(FATAL) << "Parameter block not found: " << values
  484. << ". You must add the parameter block to the problem before "
  485. << "you can set an upper bound on one of its components.";
  486. }
  487. parameter_block->SetUpperBound(index, upper_bound);
  488. }
  489. double ProblemImpl::GetParameterLowerBound(const double* values,
  490. int index) const {
  491. ParameterBlock* parameter_block = FindWithDefault(
  492. parameter_block_map_, const_cast<double*>(values), nullptr);
  493. if (parameter_block == nullptr) {
  494. LOG(FATAL) << "Parameter block not found: " << values
  495. << ". You must add the parameter block to the problem before "
  496. << "you can get the lower bound on one of its components.";
  497. }
  498. return parameter_block->LowerBound(index);
  499. }
  500. double ProblemImpl::GetParameterUpperBound(const double* values,
  501. int index) const {
  502. ParameterBlock* parameter_block = FindWithDefault(
  503. parameter_block_map_, const_cast<double*>(values), nullptr);
  504. if (parameter_block == nullptr) {
  505. LOG(FATAL) << "Parameter block not found: " << values
  506. << ". You must add the parameter block to the problem before "
  507. << "you can set an upper bound on one of its components.";
  508. }
  509. return parameter_block->UpperBound(index);
  510. }
  511. bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options,
  512. double* cost,
  513. std::vector<double>* residuals,
  514. std::vector<double>* gradient,
  515. CRSMatrix* jacobian) {
  516. if (cost == nullptr && residuals == nullptr && gradient == nullptr &&
  517. jacobian == nullptr) {
  518. return true;
  519. }
  520. // If the user supplied residual blocks, then use them, otherwise
  521. // take the residual blocks from the underlying program.
  522. Program program;
  523. *program.mutable_residual_blocks() =
  524. ((evaluate_options.residual_blocks.size() > 0)
  525. ? evaluate_options.residual_blocks
  526. : program_->residual_blocks());
  527. const std::vector<double*>& parameter_block_ptrs =
  528. evaluate_options.parameter_blocks;
  529. std::vector<ParameterBlock*> variable_parameter_blocks;
  530. std::vector<ParameterBlock*>& parameter_blocks =
  531. *program.mutable_parameter_blocks();
  532. if (parameter_block_ptrs.size() == 0) {
  533. // The user did not provide any parameter blocks, so default to
  534. // using all the parameter blocks in the order that they are in
  535. // the underlying program object.
  536. parameter_blocks = program_->parameter_blocks();
  537. } else {
  538. // The user supplied a vector of parameter blocks. Using this list
  539. // requires a number of steps.
  540. // 1. Convert double* into ParameterBlock*
  541. parameter_blocks.resize(parameter_block_ptrs.size());
  542. for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
  543. parameter_blocks[i] = FindWithDefault(
  544. parameter_block_map_, parameter_block_ptrs[i], nullptr);
  545. if (parameter_blocks[i] == nullptr) {
  546. LOG(FATAL) << "No known parameter block for "
  547. << "Problem::Evaluate::Options.parameter_blocks[" << i << "]"
  548. << " = " << parameter_block_ptrs[i];
  549. }
  550. }
  551. // 2. The user may have only supplied a subset of parameter
  552. // blocks, so identify the ones that are not supplied by the user
  553. // and are NOT constant. These parameter blocks are stored in
  554. // variable_parameter_blocks.
  555. //
  556. // To ensure that the parameter blocks are not included in the
  557. // columns of the jacobian, we need to make sure that they are
  558. // constant during evaluation and then make them variable again
  559. // after we are done.
  560. std::vector<ParameterBlock*> all_parameter_blocks(
  561. program_->parameter_blocks());
  562. std::vector<ParameterBlock*> included_parameter_blocks(
  563. program.parameter_blocks());
  564. std::vector<ParameterBlock*> excluded_parameter_blocks;
  565. sort(all_parameter_blocks.begin(), all_parameter_blocks.end());
  566. sort(included_parameter_blocks.begin(), included_parameter_blocks.end());
  567. set_difference(all_parameter_blocks.begin(),
  568. all_parameter_blocks.end(),
  569. included_parameter_blocks.begin(),
  570. included_parameter_blocks.end(),
  571. back_inserter(excluded_parameter_blocks));
  572. variable_parameter_blocks.reserve(excluded_parameter_blocks.size());
  573. for (auto* parameter_block : excluded_parameter_blocks) {
  574. if (!parameter_block->IsConstant()) {
  575. variable_parameter_blocks.push_back(parameter_block);
  576. parameter_block->SetConstant();
  577. }
  578. }
  579. }
  580. // Setup the Parameter indices and offsets before an evaluator can
  581. // be constructed and used.
  582. program.SetParameterOffsetsAndIndex();
  583. Evaluator::Options evaluator_options;
  584. // Even though using SPARSE_NORMAL_CHOLESKY requires SuiteSparse or
  585. // CXSparse, here it just being used for telling the evaluator to
  586. // use a SparseRowCompressedMatrix for the jacobian. This is because
  587. // the Evaluator decides the storage for the Jacobian based on the
  588. // type of linear solver being used.
  589. evaluator_options.linear_solver_type = SPARSE_NORMAL_CHOLESKY;
  590. evaluator_options.num_threads = evaluate_options.num_threads;
  591. // The main thread also does work so we only need to launch num_threads - 1.
  592. context_impl_->EnsureMinimumThreads(evaluator_options.num_threads - 1);
  593. evaluator_options.context = context_impl_;
  594. evaluator_options.evaluation_callback =
  595. program_->mutable_evaluation_callback();
  596. std::unique_ptr<Evaluator> evaluator(
  597. new ProgramEvaluator<ScratchEvaluatePreparer,
  598. CompressedRowJacobianWriter>(evaluator_options,
  599. &program));
  600. if (residuals != nullptr) {
  601. residuals->resize(evaluator->NumResiduals());
  602. }
  603. if (gradient != nullptr) {
  604. gradient->resize(evaluator->NumEffectiveParameters());
  605. }
  606. std::unique_ptr<CompressedRowSparseMatrix> tmp_jacobian;
  607. if (jacobian != nullptr) {
  608. tmp_jacobian.reset(down_cast<CompressedRowSparseMatrix*>(
  609. evaluator->CreateJacobian().release()));
  610. }
  611. // Point the state pointers to the user state pointers. This is
  612. // needed so that we can extract a parameter vector which is then
  613. // passed to Evaluator::Evaluate.
  614. program.SetParameterBlockStatePtrsToUserStatePtrs();
  615. // Copy the value of the parameter blocks into a vector, since the
  616. // Evaluate::Evaluate method needs its input as such. The previous
  617. // call to SetParameterBlockStatePtrsToUserStatePtrs ensures that
  618. // these values are the ones corresponding to the actual state of
  619. // the parameter blocks, rather than the temporary state pointer
  620. // used for evaluation.
  621. Vector parameters(program.NumParameters());
  622. program.ParameterBlocksToStateVector(parameters.data());
  623. double tmp_cost = 0;
  624. Evaluator::EvaluateOptions evaluator_evaluate_options;
  625. evaluator_evaluate_options.apply_loss_function =
  626. evaluate_options.apply_loss_function;
  627. bool status =
  628. evaluator->Evaluate(evaluator_evaluate_options,
  629. parameters.data(),
  630. &tmp_cost,
  631. residuals != nullptr ? &(*residuals)[0] : nullptr,
  632. gradient != nullptr ? &(*gradient)[0] : nullptr,
  633. tmp_jacobian.get());
  634. // Make the parameter blocks that were temporarily marked constant,
  635. // variable again.
  636. for (auto* parameter_block : variable_parameter_blocks) {
  637. parameter_block->SetVarying();
  638. }
  639. if (status) {
  640. if (cost != nullptr) {
  641. *cost = tmp_cost;
  642. }
  643. if (jacobian != nullptr) {
  644. tmp_jacobian->ToCRSMatrix(jacobian);
  645. }
  646. }
  647. program_->SetParameterBlockStatePtrsToUserStatePtrs();
  648. program_->SetParameterOffsetsAndIndex();
  649. return status;
  650. }
  651. bool ProblemImpl::EvaluateResidualBlock(ResidualBlock* residual_block,
  652. bool apply_loss_function,
  653. bool new_point,
  654. double* cost,
  655. double* residuals,
  656. double** jacobians) const {
  657. auto evaluation_callback = program_->mutable_evaluation_callback();
  658. if (evaluation_callback) {
  659. evaluation_callback->PrepareForEvaluation(jacobians != nullptr, new_point);
  660. }
  661. ParameterBlock* const* parameter_blocks = residual_block->parameter_blocks();
  662. const int num_parameter_blocks = residual_block->NumParameterBlocks();
  663. for (int i = 0; i < num_parameter_blocks; ++i) {
  664. ParameterBlock* parameter_block = parameter_blocks[i];
  665. if (parameter_block->IsConstant()) {
  666. if (jacobians != nullptr && jacobians[i] != nullptr) {
  667. LOG(ERROR) << "Jacobian requested for parameter block : " << i
  668. << ". But the parameter block is marked constant.";
  669. return false;
  670. }
  671. } else {
  672. CHECK(parameter_block->SetState(parameter_block->user_state()))
  673. << "Congratulations, you found a Ceres bug! Please report this error "
  674. << "to the developers.";
  675. }
  676. }
  677. double dummy_cost = 0.0;
  678. FixedArray<double, 32> scratch(
  679. residual_block->NumScratchDoublesForEvaluate());
  680. return residual_block->Evaluate(apply_loss_function,
  681. cost ? cost : &dummy_cost,
  682. residuals,
  683. jacobians,
  684. scratch.data());
  685. }
  686. int ProblemImpl::NumParameterBlocks() const {
  687. return program_->NumParameterBlocks();
  688. }
  689. int ProblemImpl::NumParameters() const { return program_->NumParameters(); }
  690. int ProblemImpl::NumResidualBlocks() const {
  691. return program_->NumResidualBlocks();
  692. }
  693. int ProblemImpl::NumResiduals() const { return program_->NumResiduals(); }
  694. int ProblemImpl::ParameterBlockSize(const double* values) const {
  695. ParameterBlock* parameter_block = FindWithDefault(
  696. parameter_block_map_, const_cast<double*>(values), nullptr);
  697. if (parameter_block == nullptr) {
  698. LOG(FATAL) << "Parameter block not found: " << values
  699. << ". You must add the parameter block to the problem before "
  700. << "you can get its size.";
  701. }
  702. return parameter_block->Size();
  703. }
  704. int ProblemImpl::ParameterBlockTangentSize(const double* values) const {
  705. ParameterBlock* parameter_block = FindWithDefault(
  706. parameter_block_map_, const_cast<double*>(values), nullptr);
  707. if (parameter_block == nullptr) {
  708. LOG(FATAL) << "Parameter block not found: " << values
  709. << ". You must add the parameter block to the problem before "
  710. << "you can get its tangent size.";
  711. }
  712. return parameter_block->TangentSize();
  713. }
  714. bool ProblemImpl::HasParameterBlock(const double* values) const {
  715. return (parameter_block_map_.find(const_cast<double*>(values)) !=
  716. parameter_block_map_.end());
  717. }
  718. void ProblemImpl::GetParameterBlocks(
  719. std::vector<double*>* parameter_blocks) const {
  720. CHECK(parameter_blocks != nullptr);
  721. parameter_blocks->resize(0);
  722. parameter_blocks->reserve(parameter_block_map_.size());
  723. for (const auto& entry : parameter_block_map_) {
  724. parameter_blocks->push_back(entry.first);
  725. }
  726. }
  727. void ProblemImpl::GetResidualBlocks(
  728. std::vector<ResidualBlockId>* residual_blocks) const {
  729. CHECK(residual_blocks != nullptr);
  730. *residual_blocks = program().residual_blocks();
  731. }
  732. void ProblemImpl::GetParameterBlocksForResidualBlock(
  733. const ResidualBlockId residual_block,
  734. std::vector<double*>* parameter_blocks) const {
  735. int num_parameter_blocks = residual_block->NumParameterBlocks();
  736. CHECK(parameter_blocks != nullptr);
  737. parameter_blocks->resize(num_parameter_blocks);
  738. for (int i = 0; i < num_parameter_blocks; ++i) {
  739. (*parameter_blocks)[i] =
  740. residual_block->parameter_blocks()[i]->mutable_user_state();
  741. }
  742. }
  743. const CostFunction* ProblemImpl::GetCostFunctionForResidualBlock(
  744. const ResidualBlockId residual_block) const {
  745. return residual_block->cost_function();
  746. }
  747. const LossFunction* ProblemImpl::GetLossFunctionForResidualBlock(
  748. const ResidualBlockId residual_block) const {
  749. return residual_block->loss_function();
  750. }
  751. void ProblemImpl::GetResidualBlocksForParameterBlock(
  752. const double* values, std::vector<ResidualBlockId>* residual_blocks) const {
  753. ParameterBlock* parameter_block = FindWithDefault(
  754. parameter_block_map_, const_cast<double*>(values), nullptr);
  755. if (parameter_block == nullptr) {
  756. LOG(FATAL) << "Parameter block not found: " << values
  757. << ". You must add the parameter block to the problem before "
  758. << "you can get the residual blocks that depend on it.";
  759. }
  760. if (options_.enable_fast_removal) {
  761. // In this case the residual blocks that depend on the parameter block are
  762. // stored in the parameter block already, so just copy them out.
  763. CHECK(residual_blocks != nullptr);
  764. residual_blocks->resize(parameter_block->mutable_residual_blocks()->size());
  765. std::copy(parameter_block->mutable_residual_blocks()->begin(),
  766. parameter_block->mutable_residual_blocks()->end(),
  767. residual_blocks->begin());
  768. return;
  769. }
  770. // Find residual blocks that depend on the parameter block.
  771. CHECK(residual_blocks != nullptr);
  772. residual_blocks->clear();
  773. const int num_residual_blocks = NumResidualBlocks();
  774. for (int i = 0; i < num_residual_blocks; ++i) {
  775. ResidualBlock* residual_block = (*(program_->mutable_residual_blocks()))[i];
  776. const int num_parameter_blocks = residual_block->NumParameterBlocks();
  777. for (int j = 0; j < num_parameter_blocks; ++j) {
  778. if (residual_block->parameter_blocks()[j] == parameter_block) {
  779. residual_blocks->push_back(residual_block);
  780. // The parameter blocks are guaranteed unique.
  781. break;
  782. }
  783. }
  784. }
  785. }
  786. } // namespace ceres::internal