| 
									
										
										
										
											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/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-05-07 00:23:41 +08:00
										 |  |  | #include <gtsam_unstable/linear/LPInitSolver.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-25 09:08:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | using namespace gtsam::symbol_shorthand; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | static const Vector kOne = Vector::Ones(1), kZero = Vector::Zero(1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											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-02-16 02:53:22 +08:00
										 |  |  |   lp.cost = LinearCost(1, Vector2(-1., -1.)); // min -x1-x2 (max x1+x2)
 | 
					
						
							|  |  |  |   lp.inequalities.push_back(LinearInequality(1, Vector2(-1, 0), 0, 1)); // x1 >= 0
 | 
					
						
							|  |  |  |   lp.inequalities.push_back(LinearInequality(1, Vector2(0, -1), 0, 2)); //  x2 >= 0
 | 
					
						
							|  |  |  |   lp.inequalities.push_back(LinearInequality(1, Vector2(1, 2), 4, 3)); //  x1 + 2*x2 <= 4
 | 
					
						
							|  |  |  |   lp.inequalities.push_back(LinearInequality(1, Vector2(4, 2), 12, 4)); //  4x1 + 2x2 <= 12
 | 
					
						
							|  |  |  |   lp.inequalities.push_back(LinearInequality(1, Vector2(-1, 1), 1, 5)); //  -x1 + x2 <= 1
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   return lp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							| 
									
										
										
										
											2016-04-26 07:00:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | TEST(LPInitSolver, infinite_loop_single_var) { | 
					
						
							| 
									
										
										
										
											2016-04-26 07:00:22 +08:00
										 |  |  |   LP initchecker; | 
					
						
							|  |  |  |   initchecker.cost = LinearCost(1,Vector3(0,0,1)); //min alpha
 | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   initchecker.inequalities.push_back(LinearInequality(1, Vector3(-2,-1,-1),-2,1));//-2x-y-alpha <= -2
 | 
					
						
							| 
									
										
										
										
											2016-04-26 07:00:22 +08:00
										 |  |  |   initchecker.inequalities.push_back(LinearInequality(1, Vector3(-1,2,-1), 6, 2));// -x+2y-alpha <= 6
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(1, Vector3(-1,0,-1), 0,3));// -x - alpha <= 0
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(1, Vector3(1,0,-1), 20, 4));//x - alpha <= 20
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(1, Vector3(0,-1,-1),0, 5));// -y - alpha <= 0
 | 
					
						
							|  |  |  |   LPSolver solver(initchecker); | 
					
						
							|  |  |  |   VectorValues starter; | 
					
						
							|  |  |  |   starter.insert(1,Vector3(0,0,2)); | 
					
						
							|  |  |  |   VectorValues results, duals; | 
					
						
							|  |  |  |   boost::tie(results, duals) = solver.optimize(starter); | 
					
						
							|  |  |  |   VectorValues expected; | 
					
						
							|  |  |  |   expected.insert(1, Vector3(13.5, 6.5, -6.5)); | 
					
						
							|  |  |  |   CHECK(assert_equal(results, expected, 1e-7)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | TEST(LPInitSolver, infinite_loop_multi_var) { | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   LP initchecker; | 
					
						
							|  |  |  |   Key X = symbol('X', 1); | 
					
						
							|  |  |  |   Key Y = symbol('Y', 1); | 
					
						
							|  |  |  |   Key Z = symbol('Z', 1); | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |   initchecker.cost = LinearCost(Z, kOne); //min alpha
 | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   initchecker.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |       LinearInequality(X, -2.0 * kOne, Y, -1.0 * kOne, Z, -1.0 * kOne, -2, 1));//-2x-y-alpha <= -2
 | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   initchecker.inequalities.push_back( | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |       LinearInequality(X, -1.0 * kOne, Y, 2.0 * kOne, Z, -1.0 * kOne, 6, 2));// -x+2y-alpha <= 6
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(X, -1.0 * kOne, Z, -1.0 * kOne, 0, 3));// -x - alpha <= 0
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(X, 1.0 * kOne, Z, -1.0 * kOne, 20, 4));//x - alpha <= 20
 | 
					
						
							|  |  |  |   initchecker.inequalities.push_back(LinearInequality(Y, -1.0 * kOne, Z, -1.0 * kOne, 0, 5));// -y - alpha <= 0
 | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   LPSolver solver(initchecker); | 
					
						
							|  |  |  |   VectorValues starter; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |   starter.insert(X, kZero); | 
					
						
							|  |  |  |   starter.insert(Y, kZero); | 
					
						
							| 
									
										
										
										
											2016-06-14 08:35:17 +08:00
										 |  |  |   starter.insert(Z, Vector::Constant(1, 2.0)); | 
					
						
							| 
									
										
										
										
											2016-05-03 07:54:58 +08:00
										 |  |  |   VectorValues results, duals; | 
					
						
							|  |  |  |   boost::tie(results, duals) = solver.optimize(starter); | 
					
						
							|  |  |  |   VectorValues expected; | 
					
						
							|  |  |  |   expected.insert(X, Vector::Constant(1, 13.5)); | 
					
						
							|  |  |  |   expected.insert(Y, Vector::Constant(1, 6.5)); | 
					
						
							|  |  |  |   expected.insert(Z, Vector::Constant(1, -6.5)); | 
					
						
							|  |  |  |   CHECK(assert_equal(results, expected, 1e-7)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | TEST(LPInitSolver, initialization) { | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   LP lp = simpleLP1(); | 
					
						
							| 
									
										
										
										
											2016-06-16 18:49:19 +08:00
										 |  |  |   LPInitSolver initSolver(lp); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   GaussianFactorGraph::shared_ptr initOfInitGraph = initSolver.buildInitOfInitGraph(); | 
					
						
							|  |  |  |   VectorValues x0 = initOfInitGraph->optimize(); | 
					
						
							|  |  |  |   VectorValues expected_x0; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |   expected_x0.insert(1, Vector::Zero(2)); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  |   expectedInitLP.cost = LinearCost(yKey, kOne); | 
					
						
							| 
									
										
										
										
											2015-05-15 20:47:57 +08:00
										 |  |  |   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-02-16 02:53:22 +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-02-16 02:53:22 +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-02-16 02:53:22 +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-02-16 02:53:22 +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-05-07 00:40:08 +08:00
										 |  |  |   expected_init.insert(1, Vector::Ones(2)); | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | GaussianFactorGraph graph; | 
					
						
							|  |  |  | Matrix A1 = Vector3(1,1,1); | 
					
						
							|  |  |  | Matrix A2 = Vector3(1,-1,2); | 
					
						
							|  |  |  | Vector b = Vector3( 1, 5, 6); | 
					
						
							|  |  |  | 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:47:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, overConstrainedLinearSystem2) { | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | GaussianFactorGraph graph; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | graph.push_back(JacobianFactor(1, I_1x1, 2, I_1x1, kOne, noiseModel::Constrained::All(1))); | 
					
						
							|  |  |  | graph.push_back(JacobianFactor(1, I_1x1, 2, -I_1x1, 5*kOne, noiseModel::Constrained::All(1))); | 
					
						
							|  |  |  | graph.push_back(JacobianFactor(1, I_1x1, 2, 2*I_1x1, 6*kOne, noiseModel::Constrained::All(1))); | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | 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:47:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-15 20:57:43 +08:00
										 |  |  | TEST(LPSolver, simpleTest1) { | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | LP lp = simpleLP1(); | 
					
						
							|  |  |  | LPSolver lpSolver(lp); | 
					
						
							|  |  |  | VectorValues init; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:23:41 +08:00
										 |  |  | init.insert(1, Vector::Zero(2)); | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | VectorValues x1 = lpSolver.solveWithCurrentWorkingSet(init, | 
					
						
							|  |  |  |     InequalityFactorGraph()); | 
					
						
							|  |  |  | VectorValues expected_x1; | 
					
						
							| 
									
										
										
										
											2016-05-07 00:40:08 +08:00
										 |  |  | expected_x1.insert(1, Vector::Ones(2)); | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | CHECK(assert_equal(expected_x1, x1, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VectorValues result, duals; | 
					
						
							|  |  |  | boost::tie(result, duals) = lpSolver.optimize(init); | 
					
						
							|  |  |  | VectorValues expectedResult; | 
					
						
							|  |  |  | expectedResult.insert(1, Vector2(8./3., 2./3.)); | 
					
						
							|  |  |  | CHECK(assert_equal(expectedResult, result, 1e-10)); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 23:45:55 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST(LPSolver, testWithoutInitialValues) { | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | LP lp = simpleLP1(); | 
					
						
							|  |  |  | LPSolver lpSolver(lp); | 
					
						
							|  |  |  | VectorValues result,duals, expectedResult; | 
					
						
							|  |  |  | expectedResult.insert(1, Vector2(8./3., 2./3.)); | 
					
						
							|  |  |  | boost::tie(result, duals) = lpSolver.optimize(); | 
					
						
							|  |  |  | CHECK(assert_equal(expectedResult, result)); | 
					
						
							| 
									
										
										
										
											2016-02-09 23:45:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-02-16 02:53:22 +08:00
										 |  |  | LinearCost cost(1, Vector3( 2., 4., 6.)); | 
					
						
							|  |  |  | VectorValues x; | 
					
						
							|  |  |  | x.insert(1, Vector3( 1., 3., 5.)); | 
					
						
							|  |  |  | double error = cost.error(x); | 
					
						
							|  |  |  | double expectedError = 44.0; | 
					
						
							|  |  |  | DOUBLES_EQUAL(expectedError, error, 1e-100); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { | 
					
						
							| 
									
										
										
										
											2016-02-16 02:53:22 +08:00
										 |  |  | TestResult tr; | 
					
						
							|  |  |  | return TestRegistry::runAllTests(tr); | 
					
						
							| 
									
										
										
										
											2015-03-25 20:19:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |