| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							|  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  |  * @file testQPSolver.cpp | 
					
						
							|  |  |  |  * @brief Test simple QP solver for a linear inequality constraint | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |  * @date Apr 10, 2014 | 
					
						
							|  |  |  |  * @author Duy-Nguyen Ta | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam/base/Testable.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/FactorGraph-inst.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/linear/LinearCost.h>
 | 
					
						
							|  |  |  | #include <gtsam/linear/VectorValues.h>
 | 
					
						
							|  |  |  | #include <gtsam/linear/GaussianFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/linear/EqualityFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/linear/InequalityFactorGraph.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-25 08:40:55 +08:00
										 |  |  | #include <gtsam_unstable/linear/InfeasibleInitialValues.h>
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  | #include <boost/range/adaptor/map.hpp>
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 08:58:42 +08:00
										 |  |  | #include <gtsam_unstable/linear/LPSolver.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-25 09:08:14 +08:00
										 |  |  | #include <gtsam_unstable/linear/LPInitSolverMatlab.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-25 08:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | using namespace gtsam::symbol_shorthand; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * min -x1-x2 | 
					
						
							|  |  |  |  * s.t.   x1 + 2x2 <= 4 | 
					
						
							|  |  |  |  *       4x1 + 2x2 <= 12 | 
					
						
							|  |  |  |  *       -x1 +  x2 <= 1 | 
					
						
							|  |  |  |  *       x1, x2 >= 0 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | LP simpleLP1() { | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   LP lp; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   lp.cost = LinearCost(1, Vector2( -1., -1.)); // min -x1-x2 (max x1+x2)
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   lp.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( -1, 0), 0, 1)); // x1 >= 0
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   lp.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 0, -1), 0, 2)); //  x2 >= 0
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   lp.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 1, 2), 4, 3)); //  x1 + 2*x2 <= 4
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   lp.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 4, 2), 12, 4)); //  4x1 + 2x2 <= 12
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   lp.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( -1, 1), 1, 5)); //  -x1 + x2 <= 1
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   return lp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | TEST(LPInitSolverMatlab, initialization) { | 
					
						
							|  |  |  |   LP lp = simpleLP1(); | 
					
						
							|  |  |  |   LPSolver lpSolver(lp); | 
					
						
							|  |  |  |   LPInitSolverMatlab initSolver(lpSolver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GaussianFactorGraph::shared_ptr initOfInitGraph = initSolver.buildInitOfInitGraph(); | 
					
						
							|  |  |  |   VectorValues x0 = initOfInitGraph->optimize(); | 
					
						
							|  |  |  |   VectorValues expected_x0; | 
					
						
							|  |  |  |   expected_x0.insert(1, zero(2)); | 
					
						
							|  |  |  |   CHECK(assert_equal(expected_x0, x0, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   double y0 = initSolver.compute_y0(x0); | 
					
						
							|  |  |  |   double expected_y0 = 0.0; | 
					
						
							|  |  |  |   DOUBLES_EQUAL(expected_y0, y0, 1e-7); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Key yKey = 2; | 
					
						
							|  |  |  |   LP::shared_ptr initLP = initSolver.buildInitialLP(yKey); | 
					
						
							|  |  |  |   LP expectedInitLP; | 
					
						
							|  |  |  |   expectedInitLP.cost = LinearCost(yKey, ones(1)); | 
					
						
							|  |  |  |   expectedInitLP.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( -1, 0), 2, Vector::Constant(1, -1), 0, 1)); // -x1 - y <= 0
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   expectedInitLP.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 0, -1), 2, Vector::Constant(1, -1), 0, 2)); // -x2 - y <= 0
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   expectedInitLP.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 1, 2), 2, Vector::Constant(1, -1), 4, 3)); //  x1 + 2*x2 - y <= 4
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   expectedInitLP.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( 4, 2), 2, Vector::Constant(1, -1), 12, 4)); //  4x1 + 2x2 - y <= 12
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   expectedInitLP.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |       LinearInequality(1, Vector2( -1, 1), 2, Vector::Constant(1, -1), 1, 5)); //  -x1 + x2 - y <= 1
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   CHECK(assert_equal(expectedInitLP, *initLP, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   LPSolver lpSolveInit(*initLP); | 
					
						
							|  |  |  |   VectorValues xy0(x0); | 
					
						
							|  |  |  |   xy0.insert(yKey, Vector::Constant(1, y0)); | 
					
						
							|  |  |  |   VectorValues xyInit = lpSolveInit.optimize(xy0).first; | 
					
						
							|  |  |  |   VectorValues expected_init; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   expected_init.insert(1, Vector2( 1, 1)); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   expected_init.insert(2, Vector::Constant(1, -1)); | 
					
						
							|  |  |  |   CHECK(assert_equal(expected_init, xyInit, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VectorValues x = initSolver.solve(); | 
					
						
							|  |  |  |   CHECK(lp.isFeasible(x)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  |  * TEST gtsam solver with an over-constrained system | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |  *  x + y = 1 | 
					
						
							|  |  |  |  *  x - y = 5 | 
					
						
							|  |  |  |  *  x + 2y = 6 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, overConstrainedLinearSystem) { | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   GaussianFactorGraph graph; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   Matrix A1 = Vector3(1,1,1); | 
					
						
							|  |  |  |   Matrix A2 = Vector3(1,-1,2); | 
					
						
							|  |  |  |   Vector b = Vector3( 1, 5, 6); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   JacobianFactor factor(1, A1, 2, A2, b, noiseModel::Constrained::All(3)); | 
					
						
							|  |  |  |   graph.push_back(factor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VectorValues x = graph.optimize(); | 
					
						
							|  |  |  |   // This check confirms that gtsam linear constraint solver can't handle over-constrained system
 | 
					
						
							|  |  |  |   CHECK(factor.error(x) != 0.0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, overConstrainedLinearSystem2) { | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   GaussianFactorGraph graph; | 
					
						
							|  |  |  |   graph.push_back(JacobianFactor(1, ones(1, 1), 2, ones(1, 1), ones(1), noiseModel::Constrained::All(1))); | 
					
						
							|  |  |  |   graph.push_back(JacobianFactor(1, ones(1, 1), 2, -ones(1, 1), 5*ones(1), noiseModel::Constrained::All(1))); | 
					
						
							|  |  |  |   graph.push_back(JacobianFactor(1, ones(1, 1), 2, 2*ones(1, 1), 6*ones(1), noiseModel::Constrained::All(1))); | 
					
						
							|  |  |  |   VectorValues x = graph.optimize(); | 
					
						
							|  |  |  |   // This check confirms that gtsam linear constraint solver can't handle over-constrained system
 | 
					
						
							|  |  |  |   CHECK(graph.error(x) != 0.0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, simpleTest1) { | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   LP lp = simpleLP1(); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   LPSolver lpSolver(lp); | 
					
						
							|  |  |  |   VectorValues init; | 
					
						
							|  |  |  |   init.insert(1, zero(2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VectorValues x1 = lpSolver.solveWithCurrentWorkingSet(init, | 
					
						
							|  |  |  |       InequalityFactorGraph()); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  |   VectorValues expected_x1; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   expected_x1.insert(1, Vector2( 1, 1)); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  |   CHECK(assert_equal(expected_x1, x1, 1e-10)); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   VectorValues result, duals; | 
					
						
							|  |  |  |   boost::tie(result, duals) = lpSolver.optimize(init); | 
					
						
							|  |  |  |   VectorValues expectedResult; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   expectedResult.insert(1, Vector2(8./3., 2./3.)); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   CHECK(assert_equal(expectedResult, result, 1e-10)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  |  * TODO: More TEST cases: | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |  * - Infeasible | 
					
						
							|  |  |  |  * - Unbounded | 
					
						
							|  |  |  |  * - Underdetermined | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, LinearCost) { | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   LinearCost cost(1, Vector3( 2., 4., 6.)); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   VectorValues x; | 
					
						
							| 
									
										
										
										
											2016-01-25 09:18:10 +08:00
										 |  |  |   x.insert(1, Vector3( 1., 3., 5.)); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  |   double error = cost.error(x); | 
					
						
							|  |  |  |   double expectedError = 44.0; | 
					
						
							|  |  |  |   DOUBLES_EQUAL(expectedError, error, 1e-100); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { | 
					
						
							|  |  |  |   TestResult tr; | 
					
						
							|  |  |  |   return TestRegistry::runAllTests(tr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |