// Ceres Solver - A fast non-linear least squares minimizer | |

// Copyright 2015 Google Inc. All rights reserved. | |

// http://ceres-solver.org/ | |

// | |

// Redistribution and use in source and binary forms, with or without | |

// modification, are permitted provided that the following conditions are met: | |

// | |

// * Redistributions of source code must retain the above copyright notice, | |

// this list of conditions and the following disclaimer. | |

// * Redistributions in binary form must reproduce the above copyright notice, | |

// this list of conditions and the following disclaimer in the documentation | |

// and/or other materials provided with the distribution. | |

// * Neither the name of Google Inc. nor the names of its contributors may be | |

// used to endorse or promote products derived from this software without | |

// specific prior written permission. | |

// | |

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |

// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |

// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |

// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |

// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |

// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |

// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |

// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |

// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |

// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |

// POSSIBILITY OF SUCH DAMAGE. | |

// | |

// Author: keir@google.com (Keir Mierle) | |

// | |

// A jacobian writer that writes to block sparse matrices. The "writer" name is | |

// misleading, since the Write() operation on the block jacobian writer does not | |

// write anything. Instead, the Prepare() method on the BlockEvaluatePreparers | |

// makes a jacobians array which has direct pointers into the block sparse | |

// jacobian. When the cost function is evaluated, the jacobian blocks get placed | |

// directly in their final location. | |

#ifndef CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ | |

#define CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ | |

#include <vector> | |

#include "ceres/evaluator.h" | |

#include "ceres/internal/port.h" | |

namespace ceres { | |

namespace internal { | |

class BlockEvaluatePreparer; | |

class Program; | |

class SparseMatrix; | |

// TODO(sameeragarwal): This class needs documemtation. | |

class BlockJacobianWriter { | |

public: | |

BlockJacobianWriter(const Evaluator::Options& options, | |

Program* program); | |

// JacobianWriter interface. | |

// Create evaluate prepareres that point directly into the final jacobian. | |

// This makes the final Write() a nop. | |

BlockEvaluatePreparer* CreateEvaluatePreparers(int num_threads); | |

SparseMatrix* CreateJacobian() const; | |

void Write(int /* residual_id */, | |

int /* residual_offset */, | |

double** /* jacobians */, | |

SparseMatrix* /* jacobian */) { | |

// This is a noop since the blocks were written directly into their final | |

// position by the outside evaluate call, thanks to the jacobians array | |

// prepared by the BlockEvaluatePreparers. | |

} | |

private: | |

Program* program_; | |

// Stores the position of each residual / parameter jacobian. | |

// | |

// The block sparse matrix that this writer writes to is stored as a set of | |

// contiguos dense blocks, one after each other; see BlockSparseMatrix. The | |

// "double* values_" member of the block sparse matrix contains all of these | |

// blocks. Given a pointer to the first element of a block and the size of | |

// that block, it's possible to write to it. | |

// | |

// In the case of a block sparse jacobian, the jacobian writer needs a way to | |

// find the offset in the values_ array of each residual/parameter jacobian | |

// block. | |

// | |

// That is the purpose of jacobian_layout_. | |

// | |

// In particular, jacobian_layout_[i][j] is the offset in the values_ array of | |

// the derivative of residual block i with respect to the parameter block at | |

// active argument position j. | |

// | |

// The active qualifier means that non-active parameters do not count. Care | |

// must be taken when indexing into jacobian_layout_ to account for this. | |

// Consider a single residual example: | |

// | |

// r(x, y, z) | |

// | |

// with r in R^3, x in R^4, y in R^2, and z in R^5. | |

// Take y as a constant (non-active) parameter. | |

// Take r as residual number 0. | |

// | |

// In this case, the active arguments are only (x, z), so the active argument | |

// position for x is 0, and the active argument position for z is 1. This is | |

// similar to thinking of r as taking only 2 parameters: | |

// | |

// r(x, z) | |

// | |

// There are only 2 jacobian blocks: dr/dx and dr/dz. jacobian_layout_ would | |

// have the following contents: | |

// | |

// jacobian_layout_[0] = { 0, 12 } | |

// | |

// which indicates that dr/dx is located at values_[0], and dr/dz is at | |

// values_[12]. See BlockEvaluatePreparer::Prepare()'s comments about 'j'. | |

std::vector<int*> jacobian_layout_; | |

// The pointers in jacobian_layout_ point directly into this vector. | |

std::vector<int> jacobian_layout_storage_; | |

}; | |

} // namespace internal | |

} // namespace ceres | |

#endif // CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ |