272 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
| /* ----------------------------------------------------------------------------
 | |
| 
 | |
|  * 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
 | |
| 
 | |
|  * -------------------------------------------------------------------------- */
 | |
| 
 | |
| /**
 | |
|  * @file     RawQP.cpp
 | |
|  * @brief    
 | |
|  * @author   Ivan Dario Jimenez
 | |
|  * @date     3/5/16
 | |
|  */
 | |
| 
 | |
| #include <gtsam_unstable/linear/RawQP.h>
 | |
| #include <iostream>
 | |
| 
 | |
| using boost::fusion::at_c;
 | |
| 
 | |
| namespace gtsam {
 | |
| 
 | |
| void RawQP::setName(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>> const &name) {
 | |
|   name_ = std::string(at_c < 1 > (name).begin(), at_c < 1 > (name).end());
 | |
|   if (debug) {
 | |
|     std::cout << "Parsing file: " << name_ << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addColumn(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>, double,
 | |
|         std::vector<char>> const &vars) {
 | |
| 
 | |
|   std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string row_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end());
 | |
|   Matrix11 coefficient = at_c < 5 > (vars) * I_1x1;
 | |
| 
 | |
|   if (!varname_to_key.count(var_))
 | |
|     varname_to_key[var_] = Symbol('X', varNumber++);
 | |
|   if (row_ == obj_name) {
 | |
|     g[varname_to_key[var_]] = coefficient;
 | |
|     return;
 | |
|   }
 | |
|   (*row_to_constraint_v[row_])[row_][varname_to_key[var_]] = coefficient;
 | |
|   if (debug) {
 | |
|     std::cout << "Added Column for Var: " << var_ << " Row: " << row_
 | |
|         << " Coefficient: " << coefficient << std::endl;
 | |
|   }
 | |
| 
 | |
| }
 | |
| 
 | |
| void RawQP::addColumnDouble(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, double, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, double> const &vars) {
 | |
| 
 | |
|   std::string var_(at_c < 0 > (vars).begin(), at_c < 0 > (vars).end());
 | |
|   std::string row1_(at_c < 2 > (vars).begin(), at_c < 2 > (vars).end());
 | |
|   std::string row2_(at_c < 6 > (vars).begin(), at_c < 6 > (vars).end());
 | |
|   Matrix11 coefficient1 = at_c < 4 > (vars) * I_1x1;
 | |
|   Matrix11 coefficient2 = at_c < 8 > (vars) * I_1x1;
 | |
|   if (!varname_to_key.count(var_))
 | |
|     varname_to_key.insert( { var_, Symbol('X', varNumber++) });
 | |
|   if (row1_ == obj_name)
 | |
|     g[varname_to_key[var_]] = coefficient1;
 | |
|   else
 | |
|     (*row_to_constraint_v[row1_])[row1_][varname_to_key[var_]] = coefficient1;
 | |
|   if (row2_ == obj_name)
 | |
|     g[varname_to_key[var_]] = coefficient2;
 | |
|   else
 | |
|     (*row_to_constraint_v[row2_])[row2_][varname_to_key[var_]] = coefficient2;
 | |
| }
 | |
| 
 | |
| void RawQP::addRHS(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>, double,
 | |
|         std::vector<char>> const &vars) {
 | |
| 
 | |
|   std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string row_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end());
 | |
|   double coefficient = at_c < 5 > (vars);
 | |
|   if (row_ == obj_name)
 | |
|     f = -coefficient;
 | |
|   else
 | |
|     b[row_] = coefficient;
 | |
| 
 | |
|   if (debug) {
 | |
|     std::cout << "Added RHS for Var: " << var_ << " Row: " << row_
 | |
|         << " Coefficient: " << coefficient << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addRHSDouble(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>, double,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>, double> const &vars) {
 | |
| 
 | |
|   std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string row1_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end());
 | |
|   std::string row2_(at_c < 7 > (vars).begin(), at_c < 7 > (vars).end());
 | |
|   double coefficient1 = at_c < 5 > (vars);
 | |
|   double coefficient2 = at_c < 9 > (vars);
 | |
|   if (row1_ == obj_name)
 | |
|     f = -coefficient1;
 | |
|   else
 | |
|     b[row1_] = coefficient1;
 | |
| 
 | |
|   if (row2_ == obj_name)
 | |
|     f = -coefficient2;
 | |
|   else
 | |
|     b[row2_] = coefficient2;
 | |
| 
 | |
|   if (debug) {
 | |
|     std::cout << "Added RHS for Var: " << var_ << " Row: " << row1_
 | |
|         << " Coefficient: " << coefficient1 << std::endl;
 | |
|     std::cout << "                      " << "Row: " << row2_
 | |
|         << " Coefficient: " << coefficient2 << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addRow(
 | |
|     boost::fusion::vector<std::vector<char>, char, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>> const &vars) {
 | |
| 
 | |
|   std::string name_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end());
 | |
|   char type = at_c < 1 > (vars);
 | |
|   switch (type) {
 | |
|   case 'N':
 | |
|     obj_name = name_;
 | |
|     break;
 | |
|   case 'L':
 | |
|     row_to_constraint_v[name_] = &IL;
 | |
|     break;
 | |
|   case 'G':
 | |
|     row_to_constraint_v[name_] = &IG;
 | |
|     break;
 | |
|   case 'E':
 | |
|     row_to_constraint_v[name_] = &E;
 | |
|     break;
 | |
|   default:
 | |
|     std::cout << "invalid type: " << type << std::endl;
 | |
|     break;
 | |
|   }
 | |
|   if (debug) {
 | |
|     std::cout << "Added Row Type: " << type << " Name: " << name_ << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addBound(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, double> const &vars) {
 | |
| 
 | |
|   std::string type_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string var_(at_c < 5 > (vars).begin(), at_c < 5 > (vars).end());
 | |
|   double number = at_c < 7 > (vars);
 | |
|   if (type_.compare(std::string("UP")) == 0)
 | |
|     up[varname_to_key[var_]] = number;
 | |
|   else if (type_.compare(std::string("LO")) == 0)
 | |
|     lo[varname_to_key[var_]] = number;
 | |
|   else
 | |
|     std::cout << "Invalid Bound Type: " << type_ << std::endl;
 | |
| 
 | |
|   if (debug) {
 | |
|     std::cout << "Added Bound Type: " << type_ << " Var: " << var_
 | |
|         << " Amount: " << number << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addBoundFr(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>> const &vars) {
 | |
|   std::string type_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string var_(at_c < 5 > (vars).begin(), at_c < 5 > (vars).end());
 | |
|   Free.push_back(varname_to_key[var_]);
 | |
|   if (debug) {
 | |
|     std::cout << "Added Free Bound Type: " << type_ << " Var: " << var_
 | |
|         << " Amount: " << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RawQP::addQuadTerm(
 | |
|     boost::fusion::vector<std::vector<char>, std::vector<char>,
 | |
|         std::vector<char>, std::vector<char>, std::vector<char>, double,
 | |
|         std::vector<char>> const &vars) {
 | |
|   std::string var1_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end());
 | |
|   std::string var2_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end());
 | |
|   Matrix11 coefficient = at_c < 5 > (vars) * I_1x1;
 | |
| 
 | |
|   H[varname_to_key[var1_]][varname_to_key[var2_]] = coefficient;
 | |
|   H[varname_to_key[var2_]][varname_to_key[var1_]] = coefficient;
 | |
|   if (debug) {
 | |
|     std::cout << "Added QuadTerm for Var: " << var1_ << " Row: " << var2_
 | |
|         << " Coefficient: " << coefficient << std::endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| QP RawQP::makeQP() {
 | |
|   KeyVector keys;
 | |
|   std::vector<Matrix> Gs;
 | |
|   std::vector<Vector> gs;
 | |
|   for (auto kv : varname_to_key) {
 | |
|     keys.push_back(kv.second);
 | |
|   }
 | |
|   std::sort(keys.begin(), keys.end());
 | |
|   for (unsigned int i = 0; i < keys.size(); ++i) {
 | |
|     for (unsigned int j = i; j < keys.size(); ++j) {
 | |
|       Gs.push_back(H[keys[i]][keys[j]]);
 | |
|     }
 | |
|   }
 | |
|   for (Key key1 : keys) {
 | |
|     gs.push_back(-g[key1]);
 | |
|   }
 | |
|   int dual_key_num = keys.size() + 1;
 | |
|   QP madeQP;
 | |
|   auto obj = HessianFactor(keys, Gs, gs, f);
 | |
| 
 | |
|   madeQP.cost.push_back(obj);
 | |
| 
 | |
|   for (auto kv : E) {
 | |
|     std::map<Key, Matrix11> keyMatrixMap;
 | |
|     for (auto km : kv.second) {
 | |
|       keyMatrixMap.insert(km);
 | |
|     }
 | |
|     madeQP.equalities.push_back(
 | |
|         LinearEquality(keyMatrixMap, b[kv.first] * I_1x1, dual_key_num++));
 | |
|   }
 | |
| 
 | |
|   for (auto kv : IG) {
 | |
|     std::map<Key, Matrix11> keyMatrixMap;
 | |
|     for (auto km : kv.second) {
 | |
|       km.second = -km.second;
 | |
|       keyMatrixMap.insert(km);
 | |
|     }
 | |
|     madeQP.inequalities.push_back(
 | |
|         LinearInequality(keyMatrixMap, -b[kv.first], dual_key_num++));
 | |
|   }
 | |
| 
 | |
|   for (auto kv : IL) {
 | |
|     std::map<Key, Matrix11> keyMatrixMap;
 | |
|     for (auto km : kv.second) {
 | |
|       keyMatrixMap.insert(km);
 | |
|     }
 | |
|     madeQP.inequalities.push_back(
 | |
|         LinearInequality(keyMatrixMap, b[kv.first], dual_key_num++));
 | |
|   }
 | |
| 
 | |
|   for (Key k : keys) {
 | |
|     if (std::find(Free.begin(), Free.end(), k) != Free.end())
 | |
|       continue;
 | |
|     if (up.count(k) == 1)
 | |
|       madeQP.inequalities.push_back(
 | |
|           LinearInequality(k, I_1x1, up[k], dual_key_num++));
 | |
|     if (lo.count(k) == 1)
 | |
|       madeQP.inequalities.push_back(
 | |
|           LinearInequality(k, -I_1x1, lo[k], dual_key_num++));
 | |
|     else
 | |
|       madeQP.inequalities.push_back(
 | |
|           LinearInequality(k, -I_1x1, 0, dual_key_num++));
 | |
|   }
 | |
|   return madeQP;
 | |
| }
 | |
| }
 | |
| 
 |