| 
									
										
										
										
											2009-11-29 02:35:36 +08:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  |  * @file testNonlinearConstraint.cpp | 
					
						
							|  |  |  |  * @brief Tests for nonlinear constraints handled via SQP | 
					
						
							|  |  |  |  * @author Alex Cunningham | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | #include <list>
 | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | #include <boost/bind.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define GTSAM_MAGIC_KEY
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | #include <VectorConfig.h>
 | 
					
						
							|  |  |  | #include <NonlinearConstraint.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | #include <NonlinearConstraint-inl.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-29 03:18:02 +08:00
										 |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | using namespace gtsam; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | using namespace boost::assign; | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | // unary functions with scalar variables
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | namespace test1 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	/** p = 1, g(x) = x^2-5 = 0 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Vector g(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Vector_(1, x * x - 5); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** p = 1, jacobianG(x) = 2x */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, 2 * x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | } // \namespace test1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | TEST( NonlinearConstraint1, unary_scalar_construction ) { | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 	// construct a constraint on x
 | 
					
						
							|  |  |  | 	// the lagrange multipliers will be expected on L_x1
 | 
					
						
							|  |  |  | 	// and there is only one multiplier
 | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys;	keys += "x"; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> c1(boost::bind(test1::g, _1, keys), | 
					
						
							|  |  |  | 										  "x", boost::bind(test1::G, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 										  p, "L1"); | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration to use for finding the error
 | 
					
						
							|  |  |  | 	VectorConfig config; | 
					
						
							|  |  |  | 	config.insert("x", Vector_(1, 1.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// calculate the error
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | 	Vector actual = c1.unwhitenedError(config); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	Vector expected = Vector_(1, -4.0); | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 	CHECK(assert_equal(actual, expected, 1e-5)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | TEST( NonlinearConstraint1, unary_scalar_linearize ) { | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys;	keys += "x"; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> c1(boost::bind(test1::g, _1, keys), | 
					
						
							|  |  |  | 										  "x", boost::bind(test1::G, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 										  p, "L1"); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration to use for linearization
 | 
					
						
							|  |  |  | 	VectorConfig realconfig; | 
					
						
							|  |  |  | 	realconfig.insert("x", Vector_(1, 1.0)); | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 	// get a configuration of Lagrange multipliers
 | 
					
						
							|  |  |  | 	VectorConfig lagrangeConfig; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	lagrangeConfig.insert("L1", Vector_(1, 3.0)); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// linearize the system
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor::shared_ptr actualFactor, actualConstraint; | 
					
						
							|  |  |  | 	boost::tie(actualFactor, actualConstraint) = c1.linearize(realconfig, lagrangeConfig); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// verify
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	GaussianFactor expectedFactor("x", Matrix_(1,1, 6.0), "L1", eye(1), zero(1), 1.0); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor expectedConstraint("x", Matrix_(1,1, 2.0), Vector_(1, 4.0), 0.0); | 
					
						
							|  |  |  | 	CHECK(assert_equal(*actualFactor, expectedFactor)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(*actualConstraint, expectedConstraint)); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | TEST( NonlinearConstraint1, unary_scalar_equal ) { | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys1, keys2; keys1 += "x"; keys2 += "y"; | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 		c1(boost::bind(test1::g, _1, keys1), "x", boost::bind(test1::G, _1, keys1), 1, "L_x1", true), | 
					
						
							|  |  |  | 		c2(boost::bind(test1::g, _1, keys1), "x", boost::bind(test1::G, _1, keys1), 1, "L_x1"), | 
					
						
							|  |  |  | 		c3(boost::bind(test1::g, _1, keys1), "x", boost::bind(test1::G, _1, keys1), 2, "L_x1"), | 
					
						
							|  |  |  | 		c4(boost::bind(test1::g, _1, keys2), "y", boost::bind(test1::G, _1, keys2), 1, "L_x1"); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:04:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	CHECK(assert_equal(c1, c2)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(c2, c1)); | 
					
						
							|  |  |  | 	CHECK(!c1.equals(c3)); | 
					
						
							|  |  |  | 	CHECK(!c1.equals(c4)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // binary functions with scalar variables
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | namespace test2 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	/** p = 1, g(x) = x^2-5 -y = 0 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Vector g(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		double y = config[keys.back()](0); | 
					
						
							|  |  |  | 		return Vector_(1, x * x - 5.0 - y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** jacobian for x, jacobianG(x,y) in x: 2x*/ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G1(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, 2.0 * x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** jacobian for y, jacobianG(x,y) in y: -1 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G2(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.back()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, -1.0); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // \namespace test2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint2, binary_scalar_construction ) { | 
					
						
							|  |  |  | 	// construct a constraint on x and y
 | 
					
						
							|  |  |  | 	// the lagrange multipliers will be expected on L_xy
 | 
					
						
							|  |  |  | 	// and there is only one multiplier
 | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x", "y"; | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 	NonlinearConstraint2<VectorConfig> c1( | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 			boost::bind(test2::g, _1, keys), | 
					
						
							|  |  |  | 			"x", boost::bind(test2::G1, _1, keys), | 
					
						
							|  |  |  | 			"y", boost::bind(test2::G1, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			p, "L12"); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration to use for finding the error
 | 
					
						
							|  |  |  | 	VectorConfig config; | 
					
						
							|  |  |  | 	config.insert("x", Vector_(1, 1.0)); | 
					
						
							|  |  |  | 	config.insert("y", Vector_(1, 2.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// calculate the error
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | 	Vector actual = c1.unwhitenedError(config); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 	Vector expected = Vector_(1.0, -6.0); | 
					
						
							|  |  |  | 	CHECK(assert_equal(actual, expected, 1e-5)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint2, binary_scalar_linearize ) { | 
					
						
							|  |  |  | 	// create a constraint
 | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x", "y"; | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 	NonlinearConstraint2<VectorConfig> c1( | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 			boost::bind(test2::g, _1, keys), | 
					
						
							|  |  |  | 			"x", boost::bind(test2::G1, _1, keys), | 
					
						
							|  |  |  | 			"y", boost::bind(test2::G2, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			p, "L12"); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration to use for finding the error
 | 
					
						
							|  |  |  | 	VectorConfig realconfig; | 
					
						
							|  |  |  | 	realconfig.insert("x", Vector_(1, 1.0)); | 
					
						
							|  |  |  | 	realconfig.insert("y", Vector_(1, 2.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration of Lagrange multipliers
 | 
					
						
							|  |  |  | 	VectorConfig lagrangeConfig; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	lagrangeConfig.insert("L12", Vector_(1, 3.0)); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// linearize the system
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor::shared_ptr actualFactor, actualConstraint; | 
					
						
							|  |  |  | 	boost::tie(actualFactor, actualConstraint) = c1.linearize(realconfig, lagrangeConfig); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// verify
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor expectedFactor("x", Matrix_(1,1, 6.0), | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 							 "y", Matrix_(1,1, -3.0), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 							 "L12", eye(1), zero(1), 1.0); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor expectedConstraint("x", Matrix_(1,1, 2.0), | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 								 "y", Matrix_(1,1, -1.0), | 
					
						
							| 
									
										
										
										
											2009-11-29 05:00:09 +08:00
										 |  |  | 								 Vector_(1, 6.0), 0.0); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	CHECK(assert_equal(*actualFactor, expectedFactor)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(*actualConstraint, expectedConstraint)); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint2, binary_scalar_equal ) { | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys1, keys2, keys3; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	keys1 += "x", "y"; keys2 += "y", "x"; keys3 += "x", "z"; | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 	NonlinearConstraint2<VectorConfig> | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 		c1(boost::bind(test2::g, _1, keys1), "x", boost::bind(test2::G1, _1, keys1), "y", boost::bind(test2::G2, _1, keys1), 1, "L_xy"), | 
					
						
							|  |  |  | 		c2(boost::bind(test2::g, _1, keys1), "x", boost::bind(test2::G1, _1, keys1), "y", boost::bind(test2::G2, _1, keys1), 1, "L_xy"), | 
					
						
							|  |  |  | 		c3(boost::bind(test2::g, _1, keys2), "y", boost::bind(test2::G1, _1, keys2), "x", boost::bind(test2::G2, _1, keys2), 1, "L_xy"), | 
					
						
							|  |  |  | 		c4(boost::bind(test2::g, _1, keys3), "x", boost::bind(test2::G1, _1, keys3), "z", boost::bind(test2::G2, _1, keys3), 3, "L_xy"); | 
					
						
							| 
									
										
										
										
											2009-11-20 11:50:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	CHECK(assert_equal(c1, c2)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(c2, c1)); | 
					
						
							|  |  |  | 	CHECK(!c1.equals(c3)); | 
					
						
							|  |  |  | 	CHECK(!c1.equals(c4)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // Inequality tests
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | namespace inequality1 { | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	/** p = 1, g(x) x^2 - 5 > 0 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Vector g(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		double g = x * x - 5; | 
					
						
							|  |  |  | 		return Vector_(1, g); // return the actual cost
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** p = 1, jacobianG(x) = 2*x */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G(const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, 2 * x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // \namespace inequality1
 | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint1, unary_inequality ) { | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x"; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> c1(boost::bind(inequality1::g, _1, keys), | 
					
						
							|  |  |  | 										  "x", boost::bind(inequality1::G, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 										   p, "L1", | 
					
						
							| 
									
										
										
										
											2009-11-29 02:35:36 +08:00
										 |  |  | 										  false); // inequality constraint
 | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get configurations to use for evaluation
 | 
					
						
							|  |  |  | 	VectorConfig config1, config2; | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	config1.insert("x", Vector_(1, 10.0)); // should be inactive
 | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 	config2.insert("x", Vector_(1, 1.0)); // should have nonzero error
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check error
 | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	CHECK(!c1.active(config1)); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | 	Vector actualError2 = c1.unwhitenedError(config2); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9))); | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	CHECK(c1.active(config2)); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint1, unary_inequality_linearize ) { | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x"; | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> c1(boost::bind(inequality1::g, _1, keys), | 
					
						
							|  |  |  | 										  "x", boost::bind(inequality1::G, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 										   p, "L1", | 
					
						
							| 
									
										
										
										
											2009-11-29 02:35:36 +08:00
										 |  |  | 										  false); // inequality constraint
 | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get configurations to use for linearization
 | 
					
						
							|  |  |  | 	VectorConfig config1, config2; | 
					
						
							|  |  |  | 	config1.insert("x", Vector_(1, 10.0)); // should have zero error
 | 
					
						
							|  |  |  | 	config2.insert("x", Vector_(1, 1.0)); // should have nonzero error
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration of Lagrange multipliers
 | 
					
						
							|  |  |  | 	VectorConfig lagrangeConfig; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	lagrangeConfig.insert("L1", Vector_(1, 3.0)); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// linearize for inactive constraint
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor::shared_ptr actualFactor1, actualConstraint1; | 
					
						
							|  |  |  | 	boost::tie(actualFactor1, actualConstraint1) = c1.linearize(config1, lagrangeConfig); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 	// check if the factor is active
 | 
					
						
							| 
									
										
										
										
											2009-11-29 02:35:36 +08:00
										 |  |  | 	CHECK(!c1.active(config1)); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// linearize for active constraint
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor::shared_ptr actualFactor2, actualConstraint2; | 
					
						
							|  |  |  | 	boost::tie(actualFactor2, actualConstraint2) = c1.linearize(config2, lagrangeConfig); | 
					
						
							| 
									
										
										
										
											2009-11-29 02:35:36 +08:00
										 |  |  | 	CHECK(c1.active(config2)); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// verify
 | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	GaussianFactor expectedFactor("x", Matrix_(1,1, 6.0), "L1", eye(1), zero(1), 1.0); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	GaussianFactor expectedConstraint("x", Matrix_(1,1, 2.0), Vector_(1, 4.0), 0.0); | 
					
						
							|  |  |  | 	CHECK(assert_equal(*actualFactor2, expectedFactor)); | 
					
						
							|  |  |  | 	CHECK(assert_equal(*actualConstraint2, expectedConstraint)); | 
					
						
							| 
									
										
										
										
											2009-11-28 02:42:01 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // Binding arbitrary functions
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | namespace binding1 { | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	/** p = 1, g(x) x^2 - r > 0 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Vector g(double r, const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		double g = x * x - r; | 
					
						
							|  |  |  | 		return Vector_(1, g); // return the actual cost
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** p = 1, jacobianG(x) = 2*x */ | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	Matrix G(double coeff, const VectorConfig& config, | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, coeff * x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // \namespace binding1
 | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint1, unary_binding ) { | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							|  |  |  | 	double coeff = 2; | 
					
						
							|  |  |  | 	double radius = 5; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x"; | 
					
						
							| 
									
										
										
										
											2009-12-18 09:40:29 +08:00
										 |  |  | 	NonlinearConstraint1<VectorConfig> c1( | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 										  boost::bind(binding1::g, radius, _1, keys), | 
					
						
							|  |  |  | 										  "x", boost::bind(binding1::G, coeff, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 										  p, "L1", | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 										  false); // inequality constraint
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// get configurations to use for evaluation
 | 
					
						
							|  |  |  | 	VectorConfig config1, config2; | 
					
						
							|  |  |  | 	config1.insert("x", Vector_(1, 10.0)); // should have zero error
 | 
					
						
							|  |  |  | 	config2.insert("x", Vector_(1, 1.0)); // should have nonzero error
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check error
 | 
					
						
							|  |  |  | 	CHECK(!c1.active(config1)); | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | 	Vector actualError2 = c1.unwhitenedError(config2); | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9))); | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	CHECK(c1.active(config2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | namespace binding2 { | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 	/** p = 1, g(x) = x^2-5 -y = 0 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Vector g(double r, const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		double y = config[keys.back()](0); | 
					
						
							|  |  |  | 		return Vector_(1, x * x - r - y); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** jacobian for x, jacobianG(x,y) in x: 2x*/ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G1(double c, const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.front()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, c * x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-18 11:05:47 +08:00
										 |  |  | 	/** jacobian for y, jacobianG(x,y) in y: -1 */ | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	Matrix G2(double c, const VectorConfig& config, const list<Symbol>& keys) { | 
					
						
							| 
									
										
										
										
											2009-12-15 13:34:49 +08:00
										 |  |  | 		double x = config[keys.back()](0); | 
					
						
							|  |  |  | 		return Matrix_(1, 1, -1.0 * c); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // \namespace binding2
 | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( NonlinearConstraint2, binary_binding ) { | 
					
						
							|  |  |  | 	// construct a constraint on x and y
 | 
					
						
							|  |  |  | 	// the lagrange multipliers will be expected on L_xy
 | 
					
						
							|  |  |  | 	// and there is only one multiplier
 | 
					
						
							|  |  |  | 	size_t p = 1; | 
					
						
							|  |  |  | 	double a = 2.0; | 
					
						
							|  |  |  | 	double b = 1.0; | 
					
						
							|  |  |  | 	double r = 5.0; | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 	list<Symbol> keys; keys += "x", "y"; | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	NonlinearConstraint2<VectorConfig> c1( | 
					
						
							| 
									
										
										
										
											2009-12-18 10:39:02 +08:00
										 |  |  | 			boost::bind(binding2::g, r, _1, keys), | 
					
						
							|  |  |  | 			"x", boost::bind(binding2::G1, a, _1, keys), | 
					
						
							|  |  |  | 			"y", boost::bind(binding2::G2, b, _1, keys), | 
					
						
							| 
									
										
										
										
											2010-01-18 03:34:57 +08:00
										 |  |  | 			p, "L1"); | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get a configuration to use for finding the error
 | 
					
						
							|  |  |  | 	VectorConfig config; | 
					
						
							|  |  |  | 	config.insert("x", Vector_(1, 1.0)); | 
					
						
							|  |  |  | 	config.insert("y", Vector_(1, 2.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// calculate the error
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:38:53 +08:00
										 |  |  | 	Vector actual = c1.unwhitenedError(config); | 
					
						
							| 
									
										
										
										
											2009-12-02 03:45:47 +08:00
										 |  |  | 	Vector expected = Vector_(1.0, -6.0); | 
					
						
							|  |  |  | 	CHECK(assert_equal(actual, expected, 1e-5)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-20 00:50:18 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { TestResult tr; return TestRegistry::runAllTests(tr); } | 
					
						
							|  |  |  | /* ************************************************************************* */ |