Merge pull request #1660 from borglab/chebyshev-improvements

Chebyshev2 Improvements
release/4.3a0
Frank Dellaert 2023-12-05 22:20:08 -08:00 committed by GitHub
commit 36f773670a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 24 deletions

View File

@ -239,8 +239,8 @@ class Basis {
* i.e., one row of the Kronecker product of weights_ with the * i.e., one row of the Kronecker product of weights_ with the
* MxM identity matrix. See also VectorEvaluationFunctor. * MxM identity matrix. See also VectorEvaluationFunctor.
*/ */
void calculateJacobian(size_t N) { void calculateJacobian() {
H_.setZero(1, M_ * N); H_.setZero(1, M_ * EvaluationFunctor::weights_.size());
for (int j = 0; j < EvaluationFunctor::weights_.size(); j++) for (int j = 0; j < EvaluationFunctor::weights_.size(); j++)
H_(0, rowIndex_ + j * M_) = EvaluationFunctor::weights_(j); H_(0, rowIndex_ + j * M_) = EvaluationFunctor::weights_(j);
} }
@ -252,14 +252,14 @@ class Basis {
/// Construct with row index /// Construct with row index
VectorComponentFunctor(size_t M, size_t N, size_t i, double x) VectorComponentFunctor(size_t M, size_t N, size_t i, double x)
: EvaluationFunctor(N, x), M_(M), rowIndex_(i) { : EvaluationFunctor(N, x), M_(M), rowIndex_(i) {
calculateJacobian(N); calculateJacobian();
} }
/// Construct with row index and interval /// Construct with row index and interval
VectorComponentFunctor(size_t M, size_t N, size_t i, double x, double a, VectorComponentFunctor(size_t M, size_t N, size_t i, double x, double a,
double b) double b)
: EvaluationFunctor(N, x, a, b), M_(M), rowIndex_(i) { : EvaluationFunctor(N, x, a, b), M_(M), rowIndex_(i) {
calculateJacobian(N); calculateJacobian();
} }
/// Calculate component of component rowIndex_ of P /// Calculate component of component rowIndex_ of P
@ -460,8 +460,8 @@ class Basis {
* i.e., one row of the Kronecker product of weights_ with the * i.e., one row of the Kronecker product of weights_ with the
* MxM identity matrix. See also VectorDerivativeFunctor. * MxM identity matrix. See also VectorDerivativeFunctor.
*/ */
void calculateJacobian(size_t N) { void calculateJacobian() {
H_.setZero(1, M_ * N); H_.setZero(1, M_ * this->weights_.size());
for (int j = 0; j < this->weights_.size(); j++) for (int j = 0; j < this->weights_.size(); j++)
H_(0, rowIndex_ + j * M_) = this->weights_(j); H_(0, rowIndex_ + j * M_) = this->weights_(j);
} }
@ -473,14 +473,14 @@ class Basis {
/// Construct with row index /// Construct with row index
ComponentDerivativeFunctor(size_t M, size_t N, size_t i, double x) ComponentDerivativeFunctor(size_t M, size_t N, size_t i, double x)
: DerivativeFunctorBase(N, x), M_(M), rowIndex_(i) { : DerivativeFunctorBase(N, x), M_(M), rowIndex_(i) {
calculateJacobian(N); calculateJacobian();
} }
/// Construct with row index and interval /// Construct with row index and interval
ComponentDerivativeFunctor(size_t M, size_t N, size_t i, double x, double a, ComponentDerivativeFunctor(size_t M, size_t N, size_t i, double x, double a,
double b) double b)
: DerivativeFunctorBase(N, x, a, b), M_(M), rowIndex_(i) { : DerivativeFunctorBase(N, x, a, b), M_(M), rowIndex_(i) {
calculateJacobian(N); calculateJacobian();
} }
/// Calculate derivative of component rowIndex_ of F /// Calculate derivative of component rowIndex_ of F
double apply(const Matrix& P, double apply(const Matrix& P,

View File

@ -32,7 +32,7 @@ Weights Chebyshev2::CalculateWeights(size_t N, double x, double a, double b) {
const double dj = const double dj =
x - Point(N, j, a, b); // only thing that depends on [a,b] x - Point(N, j, a, b); // only thing that depends on [a,b]
if (std::abs(dj) < 1e-10) { if (std::abs(dj) < 1e-12) {
// exceptional case: x coincides with a Chebyshev point // exceptional case: x coincides with a Chebyshev point
weights.setZero(); weights.setZero();
weights(j) = 1; weights(j) = 1;
@ -73,7 +73,7 @@ Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
for (size_t j = 0; j < N; j++) { for (size_t j = 0; j < N; j++) {
const double dj = const double dj =
x - Point(N, j, a, b); // only thing that depends on [a,b] x - Point(N, j, a, b); // only thing that depends on [a,b]
if (std::abs(dj) < 1e-10) { if (std::abs(dj) < 1e-12) {
// exceptional case: x coincides with a Chebyshev point // exceptional case: x coincides with a Chebyshev point
weightDerivatives.setZero(); weightDerivatives.setZero();
// compute the jth row of the differentiation matrix for this point // compute the jth row of the differentiation matrix for this point

View File

@ -51,27 +51,30 @@ class GTSAM_EXPORT Chebyshev2 : public Basis<Chebyshev2> {
using Parameters = Eigen::Matrix<double, /*Nx1*/ -1, 1>; using Parameters = Eigen::Matrix<double, /*Nx1*/ -1, 1>;
using DiffMatrix = Eigen::Matrix<double, /*NxN*/ -1, -1>; using DiffMatrix = Eigen::Matrix<double, /*NxN*/ -1, -1>;
/// Specific Chebyshev point /**
static double Point(size_t N, int j) { * @brief Specific Chebyshev point, within [a,b] interval.
* Default interval is [-1, 1]
*
* @param N The degree of the polynomial
* @param j The index of the Chebyshev point
* @param a Lower bound of interval (default: -1)
* @param b Upper bound of interval (default: 1)
* @return double
*/
static double Point(size_t N, int j, double a = -1, double b = 1) {
assert(j >= 0 && size_t(j) < N); assert(j >= 0 && size_t(j) < N);
const double dtheta = M_PI / (N > 1 ? (N - 1) : 1); const double dtheta = M_PI / (N > 1 ? (N - 1) : 1);
// We add -PI so that we get values ordered from -1 to +1 // We add -PI so that we get values ordered from -1 to +1
// sin(- M_PI_2 + dtheta*j); also works // sin(-M_PI_2 + dtheta*j); also works
return cos(-M_PI + dtheta * j);
}
/// Specific Chebyshev point, within [a,b] interval
static double Point(size_t N, int j, double a, double b) {
assert(j >= 0 && size_t(j) < N);
const double dtheta = M_PI / (N - 1);
// We add -PI so that we get values ordered from -1 to +1
return a + (b - a) * (1. + cos(-M_PI + dtheta * j)) / 2; return a + (b - a) * (1. + cos(-M_PI + dtheta * j)) / 2;
} }
/// All Chebyshev points /// All Chebyshev points
static Vector Points(size_t N) { static Vector Points(size_t N) {
Vector points(N); Vector points(N);
for (size_t j = 0; j < N; j++) points(j) = Point(N, j); for (size_t j = 0; j < N; j++) {
points(j) = Point(N, j);
}
return points; return points;
} }

View File

@ -11,10 +11,9 @@ Author: Frank Dellaert & Gerry Chen (Python)
import unittest import unittest
import numpy as np import numpy as np
from gtsam.utils.test_case import GtsamTestCase
import gtsam import gtsam
from gtsam.utils.test_case import GtsamTestCase
from gtsam.symbol_shorthand import B
class TestBasis(GtsamTestCase): class TestBasis(GtsamTestCase):
@ -26,6 +25,7 @@ class TestBasis(GtsamTestCase):
Chebyshev bases, the line y=x is used to generate the data while for Fourier, 0.7*cos(x) is Chebyshev bases, the line y=x is used to generate the data while for Fourier, 0.7*cos(x) is
used. used.
""" """
def setUp(self): def setUp(self):
self.N = 2 self.N = 2
self.x = [0., 0.5, 0.75] self.x = [0., 0.5, 0.75]