Implemented linearization and equality for unary NonlinearConstraints. Current tests use a scalar example. Split out implementation into a separate implementation file.

release/4.3a0
Alex Cunningham 2009-11-20 03:04:49 +00:00
parent 4ca1dbf325
commit ee4a066275
5 changed files with 111 additions and 56 deletions

View File

@ -115,7 +115,7 @@ headers += NonlinearFactorGraph.h NonlinearFactorGraph-inl.h
headers += NonlinearOptimizer.h NonlinearOptimizer-inl.h
sources += NonlinearFactor.cpp
sources += NonlinearEquality.h
sources += NonlinearConstraint.h
sources += NonlinearConstraint.h NonlinearConstraint-inl.h
check_PROGRAMS += testNonlinearFactor testNonlinearFactorGraph testNonlinearOptimizer testNonlinearEquality testSQP testNonlinearConstraint
testNonlinearFactor_SOURCES = $(example) testNonlinearFactor.cpp
testNonlinearFactor_LDADD = libgtsam.la

View File

@ -0,0 +1,60 @@
/*
* @file NonlinearConstraint-inl.h
* @brief Implementation for NonlinearConstraints
* @author alexgc
*/
#pragma once
#include <iostream>
#include "NonlinearConstraint.h"
namespace gtsam {
/**
* Implementations of unary nonlinear constraints
*/
template <class Config>
void NonlinearConstraint1<Config>::print(const std::string& s) const {
std::cout << "NonlinearConstraint [" << s << "]:\n"
<< " Variable: " << key_ << "\n"
<< " p: " << this->p_ << "\n"
<< " lambda key: " << this->lagrange_key_ << std::endl;
}
template <class Config>
bool NonlinearConstraint1<Config>::equals(const Factor<Config>& f, double tol) const {
const NonlinearConstraint1<Config>* p = dynamic_cast<const NonlinearConstraint1<Config>*> (&f);
if (p == NULL) return false;
if (key_ != p->key_) return false;
if (this->lagrange_key_ != p->lagrange_key_) return false;
if (g_ != p->g_) return false;
if (gradG_ != p->gradG_) return false;
return this->p_ == p->p_;
}
template <class Config>
std::pair<GaussianFactor::shared_ptr, GaussianFactor::shared_ptr>
NonlinearConstraint1<Config>::linearize(const Config& config, const VectorConfig& lagrange) const {
// extract lagrange multiplier
Vector lambda = lagrange[this->lagrange_key_];
// find the error
Vector g = g_(config, key_);
// construct the gradient
Matrix grad = gradG_(config, key_);
// construct probabilistic factor
Matrix A1 = vector_scale(grad, lambda);
GaussianFactor::shared_ptr factor(new
GaussianFactor(key_, A1, this->lagrange_key_, eye(this->p_), zero(this->p_), 1.0));
// construct the constraint
GaussianFactor::shared_ptr constraint(new GaussianFactor("x", grad, g, 0.0));
return std::make_pair(factor, constraint);
}
}

View File

@ -8,6 +8,7 @@
#pragma once
#include <map>
#include <iostream>
#include "NonlinearFactor.h"
namespace gtsam {
@ -81,7 +82,7 @@ public:
* A unary constraint with arbitrary cost and gradient functions
*/
template <class Config>
class NonlinearConstraint1 : NonlinearConstraint<Config> {
class NonlinearConstraint1 : public NonlinearConstraint<Config> {
private:
/** calculates the constraint function of the current config
@ -122,21 +123,17 @@ public:
const std::string& lagrange_key="") :
NonlinearConstraint<Config>(lagrange_key, dim_constraint),
g_(g), gradG_(gradG), key_(key) {
// set a good lagrange key here - should do something smart to find a unique one
// set a good lagrange key here
// TODO:should do something smart to find a unique one
if (lagrange_key == "")
this->lagrange_key_ = "L_" + key;
}
/** Print */
void print(const std::string& s = "") const {
//FIXME: dummy implementation
}
void print(const std::string& s = "") const;
/** Check if two factors are equal */
bool equals(const Factor<Config>& f, double tol=1e-9) const {
//FIXME: dummy implementation
return false;
}
bool equals(const Factor<Config>& f, double tol=1e-9) const;
/** error function - returns the result of the constraint function */
inline Vector error_vector(const Config& c) const {
@ -151,13 +148,7 @@ public:
* @return a pair GaussianFactor (probabilistic) and GaussianFactor (constraint)
*/
std::pair<GaussianFactor::shared_ptr, GaussianFactor::shared_ptr>
linearize(const Config& config, const VectorConfig& lagrange) const {
//FIXME: dummy implementation
GaussianFactor::shared_ptr factor(new GaussianFactor);
GaussianFactor::shared_ptr constraint(new GaussianFactor);
return std::make_pair(factor, constraint);
}
linearize(const Config& config, const VectorConfig& lagrange) const;
};

View File

@ -7,14 +7,12 @@
#include <CppUnitLite/TestHarness.h>
#include <VectorConfig.h>
#include <NonlinearConstraint.h>
#include <NonlinearConstraint-inl.h>
using namespace gtsam;
// define some functions to use
// these examples use scalar variables and a single constraint
/* ************************************************************************* */
// unary functions
// unary functions with scalar variables
/* ************************************************************************* */
namespace test1 {
/** p = 1, gradG(x) = 2x */
@ -31,7 +29,7 @@ Vector g_func(const VectorConfig& config, const std::string& key) {
} // \namespace test1
/* ************************************************************************* */
TEST( NonlinearConstraint, unary_construction ) {
TEST( NonlinearConstraint, unary_scalar_construction ) {
// construct a constraint on x
// the lagrange multipliers will be expected on L_x1
// and there is only one multiplier
@ -48,40 +46,46 @@ TEST( NonlinearConstraint, unary_construction ) {
CHECK(assert_equal(actual, expected, 1e-5));
}
///* ************************************************************************* */
//TEST( NonlinearConstraint, unary_linearize ) {
// // constuct a constraint
// Vector lambda = Vector_(1, 1.0);
// NonlinearConstraint1<VectorConfig> c1("x", *grad_g1, *g1_func, lambda);
//
// // get a configuration to use for linearization
// VectorConfig config;
// config.insert("x", Vector_(1, 1.0));
//
// // determine the gradient of the function
// Matrix
//
//}
/* ************************************************************************* */
TEST( NonlinearConstraint, unary_scalar_linearize ) {
// construct a constraint on x
// the lagrange multipliers will be expected on L_x1
// and there is only one multiplier
size_t p = 1;
NonlinearConstraint1<VectorConfig> c1("x", *test1::grad_g, *test1::g_func, p, "L_x1");
///* ************************************************************************* */
//// binary functions
//Matrix grad1_g2(const VectorConfig& config) {
// return eye(1);
//}
//
//Matrix grad2_g2(const VectorConfig& config) {
// return eye(1);
//}
//
//Vector g2_func(const VectorConfig& config) {
// return zero(1);
//}
//
///* ************************************************************************* */
//TEST( NonlinearConstraint, binary_construction ) {
// Vector lambda = Vector_(1, 1.0);
// NonlinearConstraint2<VectorConfig> c1("x", *grad1_g2, "y", *grad2_g2, *g2_func, lambda);
//}
// get a configuration to use for linearization
VectorConfig realconfig;
realconfig.insert("x", Vector_(1, 1.0));
// get a configuration of Lagrange multipliers
VectorConfig lagrangeConfig;
lagrangeConfig.insert("L_x1", Vector_(1, 3.0));
// linearize the system
GaussianFactor::shared_ptr actFactor, actConstraint;
boost::tie(actFactor, actConstraint) = c1.linearize(realconfig, lagrangeConfig);
// verify
GaussianFactor expFactor("x", Matrix_(1,1, 6.0), "L_x1", eye(1), zero(1), 1.0);
GaussianFactor expConstraint("x", Matrix_(1,1, 2.0), Vector_(1,-4.0), 0.0);
CHECK(assert_equal(*actFactor, expFactor));
CHECK(assert_equal(*actConstraint, expConstraint));
}
/* ************************************************************************* */
TEST( NonlinearConstraint, unary_scalar_equal ) {
NonlinearConstraint1<VectorConfig>
c1("x", *test1::grad_g, *test1::g_func, 1, "L_x1"),
c2("x", *test1::grad_g, *test1::g_func, 1, "L_x1"),
c3("x", *test1::grad_g, *test1::g_func, 2, "L_x1"),
c4("y", *test1::grad_g, *test1::g_func, 1, "L_x1");
CHECK(assert_equal(c1, c2));
CHECK(assert_equal(c2, c1));
CHECK(!c1.equals(c3));
CHECK(!c1.equals(c4));
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }

View File

@ -192,7 +192,7 @@ TEST (SQP, problem1_sqp ) {
* to zero
* lam*gradG*dx + dlam + lam
* formulated in matrix form as:
* [lam*gradG eye(1)] [dx; dlam] = lam
* [lam*gradG eye(1)] [dx; dlam] = zero
*/
GaussianFactor::shared_ptr f2(
new GaussianFactor("x", lam*sub(gradG, 0,1, 0,1), // scaled gradG(:,1)