| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QPSolver.cpp | 
					
						
							|  |  |  |  * @brief: | 
					
						
							|  |  |  |  * @date: Apr 15, 2014 | 
					
						
							|  |  |  |  * @author: thduynguyen | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-29 23:49:39 +08:00
										 |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | #include <gtsam/inference/FactorGraph-inst.h>
 | 
					
						
							| 
									
										
										
										
											2014-11-22 05:04:12 +08:00
										 |  |  | #include <gtsam_unstable/linear/QPSolver.h>
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  | #include <boost/range/adaptor/map.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							|  |  |  | QPSolver::QPSolver(const QP& qp) : qp_(qp) { | 
					
						
							|  |  |  |   baseGraph_ = qp_.cost; | 
					
						
							|  |  |  |   baseGraph_.push_back(qp_.equalities.begin(), qp_.equalities.end()); | 
					
						
							|  |  |  |   costVariableIndex_ = VariableIndex(qp_.cost); | 
					
						
							|  |  |  |   equalityVariableIndex_ = VariableIndex(qp_.equalities); | 
					
						
							|  |  |  |   inequalityVariableIndex_ = VariableIndex(qp_.inequalities); | 
					
						
							|  |  |  |   constrainedKeys_ = qp_.equalities.keys(); | 
					
						
							|  |  |  |   constrainedKeys_.merge(qp_.inequalities.keys()); | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | VectorValues QPSolver::solveWithCurrentWorkingSet( | 
					
						
							|  |  |  |     const LinearInequalityFactorGraph& workingSet) const { | 
					
						
							|  |  |  |   GaussianFactorGraph workingGraph = baseGraph_; | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   BOOST_FOREACH(const LinearInequality::shared_ptr& factor, workingSet) { | 
					
						
							|  |  |  |     if (factor->active()) | 
					
						
							|  |  |  |       workingGraph.push_back(factor); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |   return workingGraph.optimize(); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | JacobianFactor::shared_ptr QPSolver::createDualFactor(Key key, | 
					
						
							|  |  |  |     const LinearInequalityFactorGraph& workingSet, const VectorValues& delta) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Transpose the A matrix of constrained factors to have the jacobian of the dual key
 | 
					
						
							|  |  |  |   std::vector<std::pair<Key, Matrix> > Aterms = collectDualJacobians | 
					
						
							|  |  |  |       < LinearEquality > (key, qp_.equalities, equalityVariableIndex_); | 
					
						
							|  |  |  |   std::vector<std::pair<Key, Matrix> > AtermsInequalities = collectDualJacobians | 
					
						
							|  |  |  |       < LinearInequality > (key, workingSet, inequalityVariableIndex_); | 
					
						
							|  |  |  |   Aterms.insert(Aterms.end(), AtermsInequalities.begin(), | 
					
						
							|  |  |  |       AtermsInequalities.end()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Collect the gradients of unconstrained cost factors to the b vector
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   if (Aterms.size() > 0) { | 
					
						
							|  |  |  |     Vector b = zero(delta.at(key).size()); | 
					
						
							|  |  |  |     if (costVariableIndex_.find(key) != costVariableIndex_.end()) { | 
					
						
							|  |  |  |       BOOST_FOREACH(size_t factorIx, costVariableIndex_[key]) { | 
					
						
							|  |  |  |         GaussianFactor::shared_ptr factor = qp_.cost.at(factorIx); | 
					
						
							|  |  |  |         b += factor->gradient(key, delta); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     return boost::make_shared<JacobianFactor>(Aterms, b, noiseModel::Constrained::All(b.rows())); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   else { | 
					
						
							|  |  |  |     return boost::make_shared<JacobianFactor>(); | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | GaussianFactorGraph::shared_ptr QPSolver::buildDualGraph( | 
					
						
							|  |  |  |     const LinearInequalityFactorGraph& workingSet, const VectorValues& delta) const { | 
					
						
							|  |  |  |   GaussianFactorGraph::shared_ptr dualGraph(new GaussianFactorGraph()); | 
					
						
							|  |  |  |   BOOST_FOREACH(Key key, constrainedKeys_) { | 
					
						
							|  |  |  |     // Each constrained key becomes a factor in the dual graph
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     JacobianFactor::shared_ptr dualFactor = createDualFactor(key, workingSet, delta); | 
					
						
							|  |  |  |     if (!dualFactor->empty()) | 
					
						
							|  |  |  |       dualGraph->push_back(dualFactor); | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   return dualGraph; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  | int QPSolver::identifyLeavingConstraint( | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     const LinearInequalityFactorGraph& workingSet, | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     const VectorValues& lambdas) const { | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   int worstFactorIx = -1; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   // preset the maxLambda to 0.0: if lambda is <= 0.0, the constraint is either
 | 
					
						
							| 
									
										
										
										
											2014-11-27 18:01:45 +08:00
										 |  |  |   // inactive or a good inequality constraint, so we don't care!
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   double maxLambda = 0.0; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |   for (size_t factorIx = 0; factorIx < workingSet.size(); ++factorIx) { | 
					
						
							|  |  |  |     const LinearInequality::shared_ptr& factor = workingSet.at(factorIx); | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     if (factor->active()) { | 
					
						
							|  |  |  |       double lambda = lambdas.at(factor->dualKey())[0]; | 
					
						
							|  |  |  |       if (lambda > maxLambda) { | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |         worstFactorIx = factorIx; | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |         maxLambda = lambda; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   return worstFactorIx; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-11-27 18:01:45 +08:00
										 |  |  | /* We have to make sure the new solution with alpha satisfies all INACTIVE inequality constraints
 | 
					
						
							|  |  |  |  * If some inactive inequality constraints complain about the full step (alpha = 1), | 
					
						
							|  |  |  |  * we have to adjust alpha to stay within the inequality constraints' feasible regions. | 
					
						
							| 
									
										
										
										
											2014-05-02 02:41:55 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-11-27 18:01:45 +08:00
										 |  |  |  * For each inactive inequality j: | 
					
						
							|  |  |  |  *  - We already have: aj'*xk - bj <= 0, since xk satisfies all inequality constraints | 
					
						
							| 
									
										
										
										
											2014-05-02 02:41:55 +08:00
										 |  |  |  *  - We want: aj'*(xk + alpha*p) - bj <= 0 | 
					
						
							|  |  |  |  *  - If aj'*p <= 0, we have: aj'*(xk + alpha*p) <= aj'*xk <= bj, for all alpha>0 | 
					
						
							|  |  |  |  *  it's good! | 
					
						
							|  |  |  |  *  - We only care when aj'*p > 0. In this case, we need to choose alpha so that | 
					
						
							|  |  |  |  *  aj'*xk + alpha*aj'*p - bj <= 0  --> alpha <= (bj - aj'*xk) / (aj'*p) | 
					
						
							|  |  |  |  *  We want to step as far as possible, so we should choose alpha = (bj - aj'*xk) / (aj'*p) | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-11-27 18:01:45 +08:00
										 |  |  |  * We want the minimum of all those alphas among all inactive inequality. | 
					
						
							| 
									
										
										
										
											2014-05-02 02:41:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  | boost::tuple<double, int> QPSolver::computeStepSize( | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     const LinearInequalityFactorGraph& workingSet, const VectorValues& xk, | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     const VectorValues& p) const { | 
					
						
							| 
									
										
										
										
											2014-05-02 22:18:01 +08:00
										 |  |  |   static bool debug = false; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   double minAlpha = 1.0; | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |   int closestFactorIx = -1; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |   for(size_t factorIx = 0; factorIx<workingSet.size(); ++factorIx) { | 
					
						
							|  |  |  |     const LinearInequality::shared_ptr& factor = workingSet.at(factorIx); | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     double b = factor->getb()[0]; | 
					
						
							|  |  |  |     // only check inactive factors
 | 
					
						
							|  |  |  |     if (!factor->active()) { | 
					
						
							|  |  |  |       // Compute a'*p
 | 
					
						
							|  |  |  |       double aTp = factor->dotProductRow(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check if  a'*p >0. Don't care if it's not.
 | 
					
						
							|  |  |  |       if (aTp <= 0) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Compute a'*xk
 | 
					
						
							|  |  |  |       double aTx = factor->dotProductRow(xk); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // alpha = (b - a'*xk) / (a'*p)
 | 
					
						
							|  |  |  |       double alpha = (b - aTx) / aTp; | 
					
						
							|  |  |  |       if (debug) | 
					
						
							|  |  |  |         cout << "alpha: " << alpha << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // We want the minimum of all those max alphas
 | 
					
						
							|  |  |  |       if (alpha < minAlpha) { | 
					
						
							|  |  |  |         closestFactorIx = factorIx; | 
					
						
							|  |  |  |         minAlpha = alpha; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return boost::make_tuple(minAlpha, closestFactorIx); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | QPState QPSolver::iterate(const QPState& state) const { | 
					
						
							| 
									
										
										
										
											2014-05-02 22:18:01 +08:00
										 |  |  |   static bool debug = false; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Solve with the current working set
 | 
					
						
							|  |  |  |   VectorValues newValues = solveWithCurrentWorkingSet(state.workingSet); | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |   if (debug) | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     newValues.print("New solution:"); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // If we CAN'T move further
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |   if (newValues.equals(state.values, 1e-5)) { | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |     // Compute lambda from the dual graph
 | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     if (debug) | 
					
						
							|  |  |  |       cout << "Building dual graph..." << endl; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     GaussianFactorGraph::shared_ptr dualGraph = buildDualGraph(state.workingSet, newValues); | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     if (debug) | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |       dualGraph->print("Dual graph: "); | 
					
						
							|  |  |  |     VectorValues duals = dualGraph->optimize(); | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     if (debug) | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |       duals.print("Duals :"); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     int leavingFactor = identifyLeavingConstraint(state.workingSet, duals); | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     if (debug) | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |       cout << "leavingFactor: " << leavingFactor << endl; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If all inequality constraints are satisfied: We have the solution!!
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     if (leavingFactor < 0) { | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |       return QPState(newValues, duals, state.workingSet, true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       // Inactivate the leaving constraint
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |       LinearInequalityFactorGraph newWorkingSet = state.workingSet; | 
					
						
							|  |  |  |       newWorkingSet.at(leavingFactor)->inactivate(); | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |       return QPState(newValues, duals, newWorkingSet, false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |     // If we CAN make some progress
 | 
					
						
							| 
									
										
										
										
											2014-11-27 18:01:45 +08:00
										 |  |  |     // Adapt stepsize if some inactive constraints complain about this move
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |     double alpha; | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     int factorIx; | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     VectorValues p = newValues - state.values; | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     boost::tie(alpha, factorIx) = //
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |         computeStepSize(state.workingSet, state.values, p); | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  |     if (debug) | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |       cout << "alpha, factorIx: " << alpha << " " << factorIx << " " | 
					
						
							|  |  |  |            << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |     // also add to the working set the one that complains the most
 | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     LinearInequalityFactorGraph newWorkingSet = state.workingSet; | 
					
						
							|  |  |  |     if (factorIx >= 0) | 
					
						
							|  |  |  |       newWorkingSet.at(factorIx)->activate(); | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |     // step!
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     newValues = state.values + alpha * p; | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |     return QPState(newValues, state.duals, newWorkingSet, false); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							|  |  |  | LinearInequalityFactorGraph QPSolver::identifyActiveConstraints( | 
					
						
							|  |  |  |     const LinearInequalityFactorGraph& inequalities, | 
					
						
							|  |  |  |     const VectorValues& initialValues) const { | 
					
						
							|  |  |  |   LinearInequalityFactorGraph workingSet; | 
					
						
							|  |  |  |   BOOST_FOREACH(const LinearInequality::shared_ptr& factor, inequalities){ | 
					
						
							|  |  |  |     LinearInequality::shared_ptr workingFactor(new LinearInequality(*factor)); | 
					
						
							| 
									
										
										
										
											2014-12-13 01:03:00 +08:00
										 |  |  |     double error = workingFactor->error(initialValues); | 
					
						
							|  |  |  |     if (fabs(error)>1e-7){ | 
					
						
							|  |  |  |       workingFactor->inactivate(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       workingFactor->activate(); | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     workingSet.push_back(workingFactor); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return workingSet; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 17:47:45 +08:00
										 |  |  | //******************************************************************************
 | 
					
						
							| 
									
										
										
										
											2014-11-26 16:04:34 +08:00
										 |  |  | pair<VectorValues, VectorValues> QPSolver::optimize( | 
					
						
							| 
									
										
										
										
											2014-11-27 17:52:25 +08:00
										 |  |  |     const VectorValues& initialValues) const { | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 11:28:39 +08:00
										 |  |  |   // Initialize workingSet from the feasible initialValues
 | 
					
						
							| 
									
										
										
										
											2014-12-10 05:27:11 +08:00
										 |  |  |   LinearInequalityFactorGraph workingSet = | 
					
						
							|  |  |  |       identifyActiveConstraints(qp_.inequalities, initialValues); | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  |   QPState state(initialValues, VectorValues(), workingSet, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// main loop of the solver
 | 
					
						
							|  |  |  |   while (!state.converged) { | 
					
						
							|  |  |  |     state = iterate(state); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-09 19:13:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return make_pair(state.values, state.duals); | 
					
						
							| 
									
										
										
										
											2014-04-16 04:27:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } /* namespace gtsam */ |