LPInitSolver.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* ----------------------------------------------------------------------------
  2. * GTSAM Copyright 2010, Georgia Tech Research Corporation,
  3. * Atlanta, Georgia 30332-0415
  4. * All Rights Reserved
  5. * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
  6. * See LICENSE for the license information
  7. * -------------------------------------------------------------------------- */
  8. /**
  9. * @file LPInitSolver.h
  10. * @brief This finds a feasible solution for an LP problem
  11. * @author Duy Nguyen Ta
  12. * @author Ivan Dario Jimenez
  13. * @date 6/16/16
  14. */
  15. #include <gtsam_unstable/linear/LPInitSolver.h>
  16. #include <gtsam_unstable/linear/LPSolver.h>
  17. #include <gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h>
  18. namespace gtsam {
  19. /******************************************************************************/
  20. VectorValues LPInitSolver::solve() const {
  21. // Build the graph to solve for the initial value of the initial problem
  22. GaussianFactorGraph::shared_ptr initOfInitGraph = buildInitOfInitGraph();
  23. VectorValues x0 = initOfInitGraph->optimize();
  24. double y0 = compute_y0(x0);
  25. Key yKey = maxKey(lp_) + 1; // the unique key for y0
  26. VectorValues xy0(x0);
  27. xy0.insert(yKey, Vector::Constant(1, y0));
  28. // Formulate and solve the initial LP
  29. LP::shared_ptr initLP = buildInitialLP(yKey);
  30. // solve the initialLP
  31. LPSolver lpSolveInit(*initLP);
  32. VectorValues xyInit = lpSolveInit.optimize(xy0).first;
  33. double yOpt = xyInit.at(yKey)[0];
  34. xyInit.erase(yKey);
  35. if (yOpt > 0)
  36. throw InfeasibleOrUnboundedProblem();
  37. else
  38. return xyInit;
  39. }
  40. /******************************************************************************/
  41. LP::shared_ptr LPInitSolver::buildInitialLP(Key yKey) const {
  42. LP::shared_ptr initLP(new LP());
  43. initLP->cost = LinearCost(yKey, I_1x1); // min y
  44. initLP->equalities = lp_.equalities; // st. Ax = b
  45. initLP->inequalities =
  46. addSlackVariableToInequalities(yKey,
  47. lp_.inequalities); // Cx-y <= d
  48. return initLP;
  49. }
  50. /******************************************************************************/
  51. GaussianFactorGraph::shared_ptr LPInitSolver::buildInitOfInitGraph() const {
  52. // first add equality constraints Ax = b
  53. GaussianFactorGraph::shared_ptr initGraph(
  54. new GaussianFactorGraph(lp_.equalities));
  55. // create factor ||x||^2 and add to the graph
  56. const KeyDimMap& constrainedKeyDim = lp_.constrainedKeyDimMap();
  57. for (Key key : constrainedKeyDim | boost::adaptors::map_keys) {
  58. size_t dim = constrainedKeyDim.at(key);
  59. initGraph->push_back(
  60. JacobianFactor(key, Matrix::Identity(dim, dim), Vector::Zero(dim)));
  61. }
  62. return initGraph;
  63. }
  64. /******************************************************************************/
  65. double LPInitSolver::compute_y0(const VectorValues& x0) const {
  66. double y0 = -std::numeric_limits<double>::infinity();
  67. for (const auto& factor : lp_.inequalities) {
  68. double error = factor->error(x0);
  69. if (error > y0) y0 = error;
  70. }
  71. return y0;
  72. }
  73. /******************************************************************************/
  74. std::vector<std::pair<Key, Matrix> > LPInitSolver::collectTerms(
  75. const LinearInequality& factor) const {
  76. std::vector<std::pair<Key, Matrix> > terms;
  77. for (Factor::const_iterator it = factor.begin(); it != factor.end(); it++) {
  78. terms.push_back(make_pair(*it, factor.getA(it)));
  79. }
  80. return terms;
  81. }
  82. /******************************************************************************/
  83. InequalityFactorGraph LPInitSolver::addSlackVariableToInequalities(
  84. Key yKey, const InequalityFactorGraph& inequalities) const {
  85. InequalityFactorGraph slackInequalities;
  86. for (const auto& factor : lp_.inequalities) {
  87. std::vector<std::pair<Key, Matrix> > terms = collectTerms(*factor); // Cx
  88. terms.push_back(make_pair(yKey, Matrix::Constant(1, 1, -1.0))); // -y
  89. double d = factor->getb()[0];
  90. slackInequalities.push_back(LinearInequality(terms, d, factor->dualKey()));
  91. }
  92. return slackInequalities;
  93. }
  94. }