logDetR method which leverages noise model for efficiency. Build logDeterminant and logNormalizationConstant on top of it.

release/4.3a0
Varun Agrawal 2024-09-20 04:35:29 -04:00
parent 1ab82f382c
commit 364b4b4a75
2 changed files with 48 additions and 17 deletions

View File

@ -239,21 +239,31 @@ void Gaussian::WhitenSystem(Matrix& A1, Matrix& A2, Matrix& A3, Vector& b) const
Matrix Gaussian::information() const { return R().transpose() * R(); } Matrix Gaussian::information() const { return R().transpose() * R(); }
/* *******************************************************************************/ /* *******************************************************************************/
double Gaussian::logNormalizationConstant() const { double Gaussian::logDetR() const {
double logDetR =
R().diagonal().unaryExpr([](double x) { return log(x); }).sum();
return logDetR;
}
/* *******************************************************************************/
double Gaussian::logDeterminant() const {
// Since noise models are Gaussian, we can get the logDeterminant easily // Since noise models are Gaussian, we can get the logDeterminant easily
// Sigma = (R'R)^{-1}, det(Sigma) = det((R'R)^{-1}) = det(R'R)^{-1} // Sigma = (R'R)^{-1}, det(Sigma) = det((R'R)^{-1}) = det(R'R)^{-1}
// log det(Sigma) = -log(det(R'R)) = -2*log(det(R)) // log det(Sigma) = -log(det(R'R)) = -2*log(det(R))
// Hence, log det(Sigma)) = -2.0 * logDeterminant() // Hence, log det(Sigma)) = -2.0 * logDetR()
// which gives log = -0.5*n*log(2*pi) - 0.5*(-2.0 * logDeterminant()) return -2.0 * logDetR();
// = -0.5*n*log(2*pi) + (0.5*2.0 * logDeterminant()) }
// = -0.5*n*log(2*pi) + logDeterminant()
double logDetR =
R().diagonal().unaryExpr([](double x) { return log(x); }).sum();
/* *******************************************************************************/
double Gaussian::logNormalizationConstant() const {
// log(det(Sigma)) = -2.0 * logDetR
// which gives log = -0.5*n*log(2*pi) - 0.5*(-2.0 * logDetR())
// = -0.5*n*log(2*pi) + (0.5*2.0 * logDetR())
// = -0.5*n*log(2*pi) + logDetR()
size_t n = dim(); size_t n = dim();
constexpr double log2pi = 1.8378770664093454835606594728112; constexpr double log2pi = 1.8378770664093454835606594728112;
// Get 1/log(\sqrt(|2pi Sigma|)) = -0.5*log(|2pi Sigma|) // Get 1/log(\sqrt(|2pi Sigma|)) = -0.5*log(|2pi Sigma|)
return -0.5 * n * log2pi + logDetR; return -0.5 * n * log2pi + logDetR();
} }
@ -333,6 +343,11 @@ void Diagonal::WhitenInPlace(Eigen::Block<Matrix> H) const {
H = invsigmas().asDiagonal() * H; H = invsigmas().asDiagonal() * H;
} }
/* *******************************************************************************/
double Diagonal::logDetR() const {
return invsigmas_.unaryExpr([](double x) { return log(x); }).sum();
}
/* ************************************************************************* */ /* ************************************************************************* */
// Constrained // Constrained
/* ************************************************************************* */ /* ************************************************************************* */
@ -661,6 +676,9 @@ void Isotropic::WhitenInPlace(Eigen::Block<Matrix> H) const {
H *= invsigma_; H *= invsigma_;
} }
/* *******************************************************************************/
double Isotropic::logDetR() const { return log(invsigma_) * dim(); }
/* ************************************************************************* */ /* ************************************************************************* */
// Unit // Unit
/* ************************************************************************* */ /* ************************************************************************* */
@ -673,6 +691,9 @@ double Unit::squaredMahalanobisDistance(const Vector& v) const {
return v.dot(v); return v.dot(v);
} }
/* *******************************************************************************/
double Unit::logDetR() const { return 0.0; }
/* ************************************************************************* */ /* ************************************************************************* */
// Robust // Robust
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -183,6 +183,8 @@ namespace gtsam {
return *sqrt_information_; return *sqrt_information_;
} }
/// Compute the log of |R|. Used for computing log(|Σ|)
virtual double logDetR() const;
public: public:
@ -266,15 +268,15 @@ namespace gtsam {
/// Compute covariance matrix /// Compute covariance matrix
virtual Matrix covariance() const; virtual Matrix covariance() const;
/// Compute the log of |Σ|
double logDeterminant() const;
/** /**
* @brief Helper method to compute the normalization constant * @brief Method to compute the normalization constant
* for a Gaussian noise model. * for a Gaussian noise model k = \sqrt(1/|2πΣ|).
* k = 1/log(\sqrt(|2πΣ|)) * We compute this in the log-space for numerical accuracy,
* thus returning log(k).
* *
* We compute this in the log-space for numerical accuracy.
*
* @param noise_model The Gaussian noise model
* whose normalization constant we wish to compute.
* @return double * @return double
*/ */
double logNormalizationConstant() const; double logNormalizationConstant() const;
@ -308,11 +310,12 @@ namespace gtsam {
*/ */
Vector sigmas_, invsigmas_, precisions_; Vector sigmas_, invsigmas_, precisions_;
protected:
/** constructor to allow for disabling initialization of invsigmas */ /** constructor to allow for disabling initialization of invsigmas */
Diagonal(const Vector& sigmas); Diagonal(const Vector& sigmas);
/// Compute the log of |R|. Used for computing log(|Σ|)
virtual double logDetR() const override;
public: public:
/** constructor - no initializations, for serialization */ /** constructor - no initializations, for serialization */
Diagonal(); Diagonal();
@ -545,6 +548,9 @@ namespace gtsam {
Isotropic(size_t dim, double sigma) : Isotropic(size_t dim, double sigma) :
Diagonal(Vector::Constant(dim, sigma)),sigma_(sigma),invsigma_(1.0/sigma) {} Diagonal(Vector::Constant(dim, sigma)),sigma_(sigma),invsigma_(1.0/sigma) {}
/// Compute the log of |R|. Used for computing log(|Σ|)
virtual double logDetR() const override;
public: public:
/* dummy constructor to allow for serialization */ /* dummy constructor to allow for serialization */
@ -608,6 +614,10 @@ namespace gtsam {
* Unit: i.i.d. unit-variance noise on all m dimensions. * Unit: i.i.d. unit-variance noise on all m dimensions.
*/ */
class GTSAM_EXPORT Unit : public Isotropic { class GTSAM_EXPORT Unit : public Isotropic {
protected:
/// Compute the log of |R|. Used for computing log(|Σ|)
virtual double logDetR() const override;
public: public:
typedef std::shared_ptr<Unit> shared_ptr; typedef std::shared_ptr<Unit> shared_ptr;