/* ---------------------------------------------------------------------------- * 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 #include using boost::fusion::at_c; namespace gtsam { void RawQP::setName( boost::fusion::vector, std::vector, std::vector> 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, std::vector, std::vector, std::vector, double, std::vector> 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, std::vector, std::vector, double, std::vector, std::vector, std::vector, 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, std::vector, std::vector, std::vector, double, std::vector> 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, std::vector, std::vector, std::vector, double, std::vector, std::vector, std::vector, 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, char, std::vector, std::vector, std::vector> 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, std::vector, std::vector, std::vector, std::vector, std::vector, 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, std::vector, std::vector, std::vector, std::vector, std::vector> 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, std::vector, std::vector, std::vector, double, std::vector> 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 Gs; std::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 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 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 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; } }