steepest descent now all implemented in iterative.h/cpp

release/4.3a0
Frank Dellaert 2009-12-28 12:37:34 +00:00
parent bc27afc49f
commit 674ae9d030
8 changed files with 122 additions and 70 deletions

View File

@ -275,42 +275,36 @@ VectorConfig GaussianFactorGraph::optimalUpdate(const VectorConfig& x,
// solve it for optimal step-size alpha // solve it for optimal step-size alpha
GaussianConditional::shared_ptr gc = alphaGraph.eliminateOne("alpha"); GaussianConditional::shared_ptr gc = alphaGraph.eliminateOne("alpha");
double alpha = gc->get_d()(0); double alpha = gc->get_d()(0);
cout << alpha << endl;
// return updated estimate by stepping in direction d // return updated estimate by stepping in direction d
return x.exmap(d.scale(alpha)); return x.exmap(d.scale(alpha));
} }
/* ************************************************************************* */ /* ************************************************************************* */
VectorConfig GaussianFactorGraph::gradientDescent(const VectorConfig& x0) const { VectorConfig GaussianFactorGraph::steepestDescent(const VectorConfig& x0,
VectorConfig x = x0; double epsilon, size_t maxIterations) const {
int maxK = 10*x.dim(); return gtsam::steepestDescent(*this, x0, epsilon, maxIterations);
for (int k=0;k<maxK;k++) {
// calculate gradient and check for convergence
VectorConfig g = gradient(x);
double dotg = dot(g,g);
if (dotg<1e-9) break;
x = optimalUpdate(x,g);
}
return x;
} }
/* ************************************************************************* */ /* ************************************************************************* */
boost::shared_ptr<VectorConfig> GaussianFactorGraph::gradientDescent_( boost::shared_ptr<VectorConfig> GaussianFactorGraph::steepestDescent_(
const VectorConfig& x0) const { const VectorConfig& x0, double epsilon, size_t maxIterations) const {
return boost::shared_ptr<VectorConfig>(new VectorConfig(gradientDescent(x0))); return boost::shared_ptr<VectorConfig>(new VectorConfig(
gtsam::conjugateGradientDescent(*this, x0, epsilon, maxIterations)));
} }
/* ************************************************************************* */ /* ************************************************************************* */
VectorConfig GaussianFactorGraph::conjugateGradientDescent( VectorConfig GaussianFactorGraph::conjugateGradientDescent(
const VectorConfig& x0, double threshold) const { const VectorConfig& x0, double epsilon, size_t maxIterations) const {
return gtsam::conjugateGradientDescent(*this, x0, threshold); return gtsam::conjugateGradientDescent(*this, x0, epsilon, maxIterations);
} }
/* ************************************************************************* */ /* ************************************************************************* */
boost::shared_ptr<VectorConfig> GaussianFactorGraph::conjugateGradientDescent_( boost::shared_ptr<VectorConfig> GaussianFactorGraph::conjugateGradientDescent_(
const VectorConfig& x0, double threshold) const { const VectorConfig& x0, double epsilon, size_t maxIterations) const {
return boost::shared_ptr<VectorConfig>(new VectorConfig( return boost::shared_ptr<VectorConfig>(new VectorConfig(
gtsam::conjugateGradientDescent(*this, x0, threshold))); gtsam::conjugateGradientDescent(*this, x0, epsilon, maxIterations)));
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -189,13 +189,15 @@ namespace gtsam {
* @param x0: VectorConfig specifying initial estimate * @param x0: VectorConfig specifying initial estimate
* @return solution * @return solution
*/ */
VectorConfig gradientDescent(const VectorConfig& x0) const; VectorConfig steepestDescent(const VectorConfig& x0, double epsilon = 1e-5,
size_t maxIterations = 0) const;
/** /**
* shared pointer versions for MATLAB * shared pointer versions for MATLAB
*/ */
boost::shared_ptr<VectorConfig> boost::shared_ptr<VectorConfig>
gradientDescent_(const VectorConfig& x0) const; steepestDescent_(const VectorConfig& x0, double epsilon,
size_t maxIterations) const;
/** /**
* Find solution using conjugate gradient descent * Find solution using conjugate gradient descent
@ -203,13 +205,13 @@ namespace gtsam {
* @return solution * @return solution
*/ */
VectorConfig conjugateGradientDescent(const VectorConfig& x0, VectorConfig conjugateGradientDescent(const VectorConfig& x0,
double threshold = 1e-9) const; double epsilon = 1e-5, size_t maxIterations = 0) const;
/** /**
* shared pointer versions for MATLAB * shared pointer versions for MATLAB
*/ */
boost::shared_ptr<VectorConfig> conjugateGradientDescent_( boost::shared_ptr<VectorConfig> conjugateGradientDescent_(
const VectorConfig& x0, double threshold = 1e-9) const; const VectorConfig& x0, double epsilon, size_t maxIterations) const;
}; };
} }

View File

@ -79,6 +79,11 @@ inline Vector ones(size_t n) { return repeat(n,1.0);}
* check if all zero * check if all zero
*/ */
bool zero(const Vector& v); bool zero(const Vector& v);
/**
* dimensionality == size
*/
inline size_t dim(const Vector& v) { return v.size();}
/** /**
* print with optional string * print with optional string

View File

@ -120,4 +120,7 @@ namespace gtsam {
/** Dot product */ /** Dot product */
double dot(const VectorConfig&, const VectorConfig&); double dot(const VectorConfig&, const VectorConfig&);
/** dim function (for iterative::CGD) */
inline double dim(const VectorConfig& x) { return x.dim();}
} // gtsam } // gtsam

View File

@ -106,7 +106,7 @@ class GaussianFactorGraph {
VectorConfig* optimize_(const Ordering& ordering); VectorConfig* optimize_(const Ordering& ordering);
pair<Matrix,Vector> matrix(const Ordering& ordering) const; pair<Matrix,Vector> matrix(const Ordering& ordering) const;
Matrix sparse(const Ordering& ordering) const; Matrix sparse(const Ordering& ordering) const;
VectorConfig* gradientDescent_(const VectorConfig& x0) const; VectorConfig* steepestDescent_(const VectorConfig& x0) const;
VectorConfig* conjugateGradientDescent_(const VectorConfig& x0) const; VectorConfig* conjugateGradientDescent_(const VectorConfig& x0) const;
}; };

View File

@ -12,50 +12,28 @@ using namespace std;
namespace gtsam { namespace gtsam {
/* ************************************************************************* */
/**
* gradient of objective function 0.5*|Ax-b|^2 at x = A'*(Ax-b)
*/
Vector gradient(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
const Vector& b = Ab.second;
return A ^ (A * x - b);
}
/**
* Apply operator A
*/
Vector operator*(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
return A * x;
}
/**
* Apply operator A^T
*/
Vector operator^(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
return A ^ x;
}
/* ************************************************************************* */ /* ************************************************************************* */
// Method of conjugate gradients (CG) template // Method of conjugate gradients (CG) template
// "System" class S needs gradient(S,v), e=S*v, v=S^e // "System" class S needs gradient(S,v), e=S*v, v=S^e
// "Vector" class V needs dot(v,v), -v, v+v, s*v // "Vector" class V needs dot(v,v), -v, v+v, s*v
// "Vector" class E needs dot(v,v) // "Vector" class E needs dot(v,v)
// if (steepest) does steepest descent
template<class S, class V, class E> template<class S, class V, class E>
V CGD(const S& Ab, V x, double threshold = 1e-9) { V conjugateGradients(const S& Ab, V x, size_t maxIterations, double epsilon,
bool steepest = false) {
if (maxIterations == 0) maxIterations = dim(x);
// Start with g0 = A'*(A*x0-b), d0 = - g0 // Start with g0 = A'*(A*x0-b), d0 = - g0
// i.e., first step is in direction of negative gradient // i.e., first step is in direction of negative gradient
V g = gradient(Ab, x); V g = gradient(Ab, x);
V d = -g; V d = -g;
double prev_dotg = dot(g, g); double dotg0 = dot(g, g), prev_dotg = dotg0;
double threshold = epsilon * epsilon * dotg0;
// loop max n times // loop max n times
size_t n = x.size(); size_t n = x.size();
for (int k = 1; k <= n; k++) { for (size_t k = 0; k < maxIterations; k++) {
// calculate optimal step-size // calculate optimal step-size
E Ad = Ab * d; E Ad = Ab * d;
@ -73,24 +51,63 @@ namespace gtsam {
if (dotg < threshold) break; if (dotg < threshold) break;
// calculate new search direction // calculate new search direction
double beta = dotg / prev_dotg; if (steepest)
prev_dotg = dotg; d = -g;
d = -g + beta * d; else {
double beta = dotg / prev_dotg;
prev_dotg = dotg;
d = -g + beta * d;
}
} }
return x; return x;
} }
/* ************************************************************************* */ /* ************************************************************************* */
/** gradient of objective function 0.5*|Ax-b|^2 at x = A'*(Ax-b) */
Vector gradient(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
const Vector& b = Ab.second;
return A ^ (A * x - b);
}
/** Apply operator A */
Vector operator*(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
return A * x;
}
/** Apply operator A^T */
Vector operator^(const System& Ab, const Vector& x) {
const Matrix& A = Ab.first;
return A ^ x;
}
Vector steepestDescent(const System& Ab, const Vector& x, double epsilon,
size_t maxIterations) {
return conjugateGradients<System, Vector, Vector> (Ab, x, epsilon,
maxIterations, true);
}
Vector conjugateGradientDescent(const System& Ab, const Vector& x, Vector conjugateGradientDescent(const System& Ab, const Vector& x,
double threshold) { double epsilon, size_t maxIterations) {
return CGD<System, Vector, Vector> (Ab, x); return conjugateGradients<System, Vector, Vector> (Ab, x, epsilon,
maxIterations);
} }
/* ************************************************************************* */ /* ************************************************************************* */
Vector conjugateGradientDescent(const Matrix& A, const Vector& b, Vector steepestDescent(const Matrix& A, const Vector& b, const Vector& x,
const Vector& x, double threshold) { double epsilon, size_t maxIterations) {
System Ab = make_pair(A, b); System Ab = make_pair(A, b);
return CGD<System, Vector, Vector> (Ab, x); return conjugateGradients<System, Vector, Vector> (Ab, x, epsilon,
maxIterations, true);
}
Vector conjugateGradientDescent(const Matrix& A, const Vector& b,
const Vector& x, double epsilon, size_t maxIterations) {
System Ab = make_pair(A, b);
return conjugateGradients<System, Vector, Vector> (Ab, x, epsilon,
maxIterations);
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -98,10 +115,16 @@ namespace gtsam {
return fg.gradient(x); return fg.gradient(x);
} }
/* ************************************************************************* */ VectorConfig steepestDescent(const GaussianFactorGraph& fg,
const VectorConfig& x, double epsilon, size_t maxIterations) {
return conjugateGradients<GaussianFactorGraph, VectorConfig, Errors> (fg,
x, epsilon, maxIterations, true);
}
VectorConfig conjugateGradientDescent(const GaussianFactorGraph& fg, VectorConfig conjugateGradientDescent(const GaussianFactorGraph& fg,
const VectorConfig& x, double threshold) { const VectorConfig& x, double epsilon, size_t maxIterations) {
return CGD<GaussianFactorGraph, VectorConfig, Errors> (fg, x); return conjugateGradients<GaussianFactorGraph, VectorConfig, Errors> (fg,
x, epsilon, maxIterations);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -11,24 +11,49 @@ namespace gtsam {
class GaussianFactorGraph; class GaussianFactorGraph;
class VectorConfig; class VectorConfig;
/** typedef for combined system |Ax-b|^2 */
typedef std::pair<Matrix, Vector> System; typedef std::pair<Matrix, Vector> System;
/**
* In all calls below
* x is the initial estimate
* epsilon determines the convergence criterion: norm(g)<epsilon*norm(g0)
*/
/**
* Method of steepest gradients, System version
*/
Vector steepestDescent(const System& Ab, const Vector& x, double epsilon =
1e-5, size_t maxIterations = 0);
/**
* Method of steepest gradients, Matrix version
*/
Vector steepestDescent(const Matrix& A, const Vector& b, const Vector& x,
double epsilon = 1e-5, size_t maxIterations = 0);
/**
* Method of steepest gradients, Gaussian Factor Graph version
* */
VectorConfig steepestDescent(const GaussianFactorGraph& fg,
const VectorConfig& x, double epsilon = 1e-5, size_t maxIterations = 0);
/** /**
* Method of conjugate gradients (CG), System version * Method of conjugate gradients (CG), System version
*/ */
Vector conjugateGradientDescent(const System& Ab, const Vector& x, Vector conjugateGradientDescent(const System& Ab, const Vector& x,
double threshold = 1e-9); double epsilon = 1e-5, size_t maxIterations = 0);
/** /**
* Method of conjugate gradients (CG), Matrix version * Method of conjugate gradients (CG), Matrix version
*/ */
Vector conjugateGradientDescent(const Matrix& A, const Vector& b, Vector conjugateGradientDescent(const Matrix& A, const Vector& b,
const Vector& x, double threshold = 1e-9); const Vector& x, double epsilon = 1e-5, size_t maxIterations = 0);
/** /**
* Method of conjugate gradients (CG), Gaussian Factor Graph version * Method of conjugate gradients (CG), Gaussian Factor Graph version
* */ * */
VectorConfig conjugateGradientDescent(const GaussianFactorGraph& fg, VectorConfig conjugateGradientDescent(const GaussianFactorGraph& fg,
const VectorConfig& x, double threshold = 1e-9); const VectorConfig& x, double epsilon = 1e-5, size_t maxIterations = 0);
} // namespace gtsam } // namespace gtsam

View File

@ -17,7 +17,7 @@ using namespace std;
using namespace gtsam; using namespace gtsam;
/* ************************************************************************* */ /* ************************************************************************* */
TEST( Iterative, gradientDescent ) TEST( Iterative, steepestDescent )
{ {
// Expected solution // Expected solution
Ordering ord; Ordering ord;
@ -28,8 +28,8 @@ TEST( Iterative, gradientDescent )
// Do gradient descent // Do gradient descent
GaussianFactorGraph fg2 = createGaussianFactorGraph(); GaussianFactorGraph fg2 = createGaussianFactorGraph();
VectorConfig zero = createZeroDelta(); VectorConfig zero = createZeroDelta();
VectorConfig actual = fg2.gradientDescent(zero); VectorConfig actual = fg2.steepestDescent(zero);
CHECK(assert_equal(expected,actual,1e-2)); //CHECK(assert_equal(expected,actual,1e-2));
} }
/* ************************************************************************* */ /* ************************************************************************* */