18 #define BOOST_SPIRIT_USE_PHOENIX_V3 1 27 #include <boost/fusion/include/vector.hpp> 28 #include <boost/fusion/sequence.hpp> 29 #include <boost/lambda/lambda.hpp> 30 #include <boost/phoenix/bind.hpp> 31 #include <boost/spirit/include/classic.hpp> 32 #include <boost/spirit/include/qi.hpp> 38 #include <unordered_map> 41 using boost::fusion::at_c;
45 namespace bf = boost::fusion;
46 namespace qi = boost::spirit::qi;
48 using Chars = std::vector<char>;
51 template <
size_t I,
class FusionVector>
53 const Chars &chars = at_c<I>(vars);
54 return string(chars.begin(), chars.end());
67 typedef std::unordered_map<std::string, coefficient_v>
constraint_v;
69 std::unordered_map<std::string, constraint_v *>
75 std::unordered_map<std::string, double>
78 std::unordered_map<std::string, double>
80 std::unordered_map<Key, Vector1>
g;
81 std::unordered_map<std::string, Key>
83 std::unordered_map<Key, std::unordered_map<Key, Matrix11>>
88 std::unordered_map<Key, double>
90 std::unordered_map<Key, double>
92 std::unordered_map<Key, double>
101 void setName(boost::fusion::vector<Chars, Chars, Chars>
const &
name) {
102 name_ = fromChars<1>(
name);
104 cout <<
"Parsing file: " << name_ << endl;
109 double,
Chars>
const &vars) {
110 string var_ = fromChars<1>(vars);
111 string row_ = fromChars<3>(vars);
112 Matrix11 coefficient = at_c<5>(vars) * I_1x1;
114 cout <<
"Added Column for Var: " << var_ <<
" Row: " << row_
115 <<
" Coefficient: " << coefficient << endl;
117 if (!varname_to_key.count(var_))
118 varname_to_key[var_] =
Symbol(
'X', numVariables++);
119 if (row_ == obj_name) {
120 g[varname_to_key[var_]] = coefficient;
123 (*row_to_constraint_v[row_])[row_][varname_to_key[var_]] = coefficient;
128 Chars,
double>
const &vars) {
129 string var_ = fromChars<0>(vars);
130 string row1_ = fromChars<2>(vars);
131 string row2_ = fromChars<6>(vars);
132 Matrix11 coefficient1 = at_c<4>(vars) * I_1x1;
133 Matrix11 coefficient2 = at_c<8>(vars) * I_1x1;
134 if (!varname_to_key.count(var_))
135 varname_to_key.insert({var_, Symbol(
'X', numVariables++)});
136 if (row1_ == obj_name)
137 g[varname_to_key[var_]] = coefficient1;
139 (*row_to_constraint_v[row1_])[row1_][varname_to_key[var_]] = coefficient1;
140 if (row2_ == obj_name)
141 g[varname_to_key[var_]] = coefficient2;
143 (*row_to_constraint_v[row2_])[row2_][varname_to_key[var_]] = coefficient2;
147 double,
Chars>
const &vars) {
148 string var_ = fromChars<1>(vars);
149 string row_ = fromChars<3>(vars);
150 double range = at_c<5>(vars);
151 ranges[row_] =
range;
153 cout <<
"SINGLE RANGE ADDED" << endl;
154 cout <<
"VAR:" << var_ <<
" ROW: " << row_ <<
" RANGE: " << range << endl;
160 string var_ = fromChars<1>(vars);
161 string row1_ = fromChars<3>(vars);
162 string row2_ = fromChars<7>(vars);
163 double range1 = at_c<5>(vars);
164 double range2 = at_c<9>(vars);
168 cout <<
"DOUBLE RANGE ADDED" << endl;
169 cout <<
"VAR: " << var_ <<
" ROW1: " << row1_ <<
" RANGE1: " << range1
170 <<
" ROW2: " << row2_ <<
" RANGE2: " << range2 << endl;
175 Chars>
const &vars) {
176 string var_ = fromChars<1>(vars);
177 string row_ = fromChars<3>(vars);
178 double coefficient = at_c<5>(vars);
179 if (row_ == obj_name) {
182 b[row_] = coefficient;
186 cout <<
"Added RHS for Var: " << var_ <<
" Row: " << row_
187 <<
" Coefficient: " << coefficient << endl;
194 string var_ = fromChars<1>(vars);
195 string row1_ = fromChars<3>(vars);
196 string row2_ = fromChars<7>(vars);
197 double coefficient1 = at_c<5>(vars);
198 double coefficient2 = at_c<9>(vars);
199 if (row1_ == obj_name) {
202 b[row1_] = coefficient1;
205 if (row2_ == obj_name) {
208 b[row2_] = coefficient2;
212 cout <<
"Added RHS for Var: " << var_ <<
" Row: " << row1_
213 <<
" Coefficient: " << coefficient1 << endl;
215 <<
"Row: " << row2_ <<
" Coefficient: " << coefficient2 << endl;
220 boost::fusion::vector<Chars, char, Chars, Chars, Chars>
const &vars) {
221 string name_ = fromChars<3>(vars);
222 char type = at_c<1>(vars);
228 row_to_constraint_v[name_] = &IL;
231 row_to_constraint_v[name_] = &IG;
234 row_to_constraint_v[name_] = &
E;
237 cout <<
"invalid type: " << type << endl;
241 cout <<
"Added Row Type: " << type <<
" Name: " << name_ << endl;
246 Chars,
double>
const &vars) {
247 string type_ = fromChars<1>(vars);
248 string var_ = fromChars<5>(vars);
249 double number = at_c<7>(vars);
250 if (type_.compare(
string(
"UP")) == 0)
251 up[varname_to_key[var_]] = number;
252 else if (type_.compare(
string(
"LO")) == 0)
253 lo[varname_to_key[var_]] = number;
254 else if (type_.compare(
string(
"FX")) == 0)
255 fx[varname_to_key[var_]] = number;
257 cout <<
"Invalid Bound Type: " << type_ << endl;
260 cout <<
"Added Bound Type: " << type_ <<
" Var: " << var_
261 <<
" Amount: " << number << endl;
267 string type_ = fromChars<1>(vars);
268 string var_ = fromChars<5>(vars);
269 free.push_back(varname_to_key[var_]);
271 cout <<
"Added Free Bound Type: " << type_ <<
" Var: " << var_
272 <<
" Amount: " << endl;
277 double,
Chars>
const &vars) {
278 string var1_ = fromChars<1>(vars);
279 string var2_ = fromChars<3>(vars);
280 Matrix11 coefficient = at_c<5>(vars) * I_1x1;
282 H[varname_to_key[var1_]][varname_to_key[var2_]] = coefficient;
283 H[varname_to_key[var2_]][varname_to_key[var1_]] = coefficient;
285 cout <<
"Added QuadTerm for Var: " << var1_ <<
" Row: " << var2_
286 <<
" Coefficient: " << coefficient << endl;
293 for (
auto kv : varname_to_key) {
294 keys.push_back(kv.second);
300 sort(keys.begin(), keys.end());
301 for (
size_t i = 0;
i < keys.size(); ++
i) {
302 for (
size_t j =
i;
j < keys.size(); ++
j) {
303 if (
H.count(keys[
i]) > 0 &&
H[keys[
i]].count(keys[
j]) > 0) {
304 Gs.emplace_back(
H[keys[i]][keys[j]]);
306 Gs.emplace_back(Z_1x1);
311 if (g.count(
key1) > 0) {
312 gs.emplace_back(-g[
key1]);
314 gs.emplace_back(Z_1x1);
324 size_t dual_key_num = keys.size() + 1;
326 map<Key, Matrix11> keyMatrixMapPos;
327 map<Key, Matrix11> keyMatrixMapNeg;
328 if (ranges.count(kv.first) == 1) {
329 for (
auto km : kv.second) {
330 keyMatrixMapPos.insert(km);
331 km.second = -km.second;
332 keyMatrixMapNeg.insert(km);
334 if (ranges[kv.first] > 0) {
338 keyMatrixMapPos,
b[kv.first] + ranges[kv.first], dual_key_num++));
339 }
else if (ranges[kv.first] < 0) {
343 keyMatrixMapNeg, ranges[kv.first] -
b[kv.first], dual_key_num++));
345 cerr <<
"ERROR: CANNOT ADD A RANGE OF ZERO" << endl;
350 map<Key, Matrix11> keyMatrixMap;
351 for (
auto km : kv.second) {
352 keyMatrixMap.insert(km);
359 map<Key, Matrix11> keyMatrixMapNeg;
360 map<Key, Matrix11> keyMatrixMapPos;
361 for (
auto km : kv.second) {
362 keyMatrixMapPos.insert(km);
363 km.second = -km.second;
364 keyMatrixMapNeg.insert(km);
368 if (ranges.count(kv.first) == 1) {
370 keyMatrixMapPos,
b[kv.first] + ranges[kv.first], dual_key_num++));
375 map<Key, Matrix11> keyMatrixMapPos;
376 map<Key, Matrix11> keyMatrixMapNeg;
377 for (
auto km : kv.second) {
378 keyMatrixMapPos.insert(km);
379 km.second = -km.second;
380 keyMatrixMapNeg.insert(km);
384 if (ranges.count(kv.first) == 1) {
386 keyMatrixMapNeg, ranges[kv.first] -
b[kv.first], dual_key_num++));
391 if (find(free.begin(), free.end(), k) != free.end())
continue;
392 if (
fx.count(k) == 1)
395 if (up.count(k) == 1)
398 if (lo.count(k) == 1)
409 typedef qi::grammar<boost::spirit::basic_istream_iterator<char>>
base_grammar;
414 std::function<void(bf::vector<Chars, Chars, Chars>
const &)> setName;
415 std::function<void(bf::vector<Chars, char, Chars, Chars, Chars>
const &)>
418 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>
const &)>
420 std::function<void(bf::vector<Chars, Chars, Chars, Chars, Chars,
double,
421 Chars, Chars, Chars,
double>)>
424 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>
const &)>
426 std::function<void(bf::vector<Chars, Chars, Chars, Chars, Chars,
double,
427 Chars, Chars, Chars,
double>)>
430 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>)>
432 std::function<void(bf::vector<Chars, Chars, Chars, Chars,
double, Chars,
433 Chars, Chars,
double>
const &)>
436 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>
const &)>
438 std::function<void(bf::vector<Chars, Chars, Chars, Chars, Chars, Chars,
439 Chars,
double>
const &)>
442 bf::vector<Chars, Chars, Chars, Chars, Chars, Chars, Chars>
const &)>
445 : base_grammar(start),
450 rhsDouble(
std::bind(&
QPSVisitor::addRHSDouble, rqp,
std::placeholders::_1)),
451 rangeSingle(
std::bind(&
QPSVisitor::addRangeSingle, rqp,
std::placeholders::_1)),
452 rangeDouble(
std::bind(&
QPSVisitor::addRangeDouble, rqp,
std::placeholders::_1)),
454 colDouble(
std::bind(&
QPSVisitor::addColumnDouble, rqp,
std::placeholders::_1)),
455 addQuadTerm(
std::bind(&
QPSVisitor::addQuadTerm, rqp,
std::placeholders::_1)),
457 addFreeBound(
std::bind(&
QPSVisitor::addFreeBound, rqp,
std::placeholders::_1)) {
458 using namespace boost::spirit;
459 using namespace boost::spirit::qi;
460 character = lexeme[alnum |
'_' |
'-' |
'.'];
461 title = lexeme[character >> *(blank | character)];
462 word = lexeme[+character];
463 name = lexeme[lit(
"NAME") >> *blank >> title >> +space][setName];
464 row = lexeme[*blank >> character >> +blank >> word >> *blank][addRow];
465 rhs_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ >>
468 lexeme[(*blank >> word >> +blank >> word >> +blank >> double_ >>
469 +blank >> word >> +blank >> double_)[rhsDouble] >>
471 range_single = lexeme[*blank >> word >> +blank >> word >> +blank >>
472 double_ >> *blank][rangeSingle];
474 lexeme[(*blank >> word >> +blank >> word >> +blank >> double_ >>
475 +blank >> word >> +blank >> double_)[rangeDouble] >>
477 col_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ >>
480 lexeme[*blank >> (word >> +blank >> word >> +blank >> double_ >>
481 +blank >> word >> +blank >> double_)[colDouble] >>
483 quad_l = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ >>
484 *blank][addQuadTerm];
485 bound = lexeme[(*blank >> word >> +blank >> word >> +blank >> word >>
486 +blank >> double_)[addBound] >>
488 bound_fr = lexeme[*blank >> word >> +blank >> word >> +blank >> word >>
489 *blank][addFreeBound];
490 rows = lexeme[lit(
"ROWS") >> *blank >> eol >> +(
row >> eol)];
491 rhs = lexeme[lit(
"RHS") >> *blank >> eol >>
492 +((rhs_double | rhs_single) >> eol)];
493 cols = lexeme[lit(
"COLUMNS") >> *blank >> eol >>
494 +((col_double | col_single) >> eol)];
495 quad = lexeme[lit(
"QUADOBJ") >> *blank >> eol >> +(quad_l >> eol)];
496 bounds = lexeme[lit(
"BOUNDS") >> +space >> *((
bound | bound_fr) >> eol)];
497 ranges = lexeme[lit(
"RANGES") >> +space >>
498 *((range_double | range_single) >> eol)];
499 end = lexeme[lit(
"ENDATA") >> *space];
501 lexeme[
name >>
rows >>
cols >> rhs >> -ranges >> bounds >> quad >>
end];
504 qi::rule<boost::spirit::basic_istream_iterator<char>, char()>
character;
505 qi::rule<boost::spirit::basic_istream_iterator<char>,
Chars()>
word, title;
506 qi::rule<boost::spirit::basic_istream_iterator<char>>
row,
end, col_single,
507 col_double, rhs_single, rhs_double, range_single, range_double, ranges,
511 QP QPSParser::Parse() {
513 std::fstream
stream(fileName_.c_str());
514 stream.unsetf(std::ios::skipws);
515 boost::spirit::basic_istream_iterator<char> begin(
stream);
516 boost::spirit::basic_istream_iterator<char>
last;
qi::rule< boost::spirit::basic_istream_iterator< char > > start
std::function< void(bf::vector< Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double > const &)> colDouble
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, Chars, Chars, double > const &)> addBound
void addFreeBound(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, Chars, Chars > const &vars)
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars >)> colSingle
void addRow(boost::fusion::vector< Chars, char, Chars, Chars, Chars > const &vars)
qi::grammar< boost::spirit::basic_istream_iterator< char > > base_grammar
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
void addBound(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, Chars, Chars, double > const &vars)
std::unordered_map< Key, Matrix11 > coefficient_v
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, Chars, Chars > const &)> addFreeBound
static double range2(const Camera &camera, const Camera2 &camera2)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate set rrange [*:*] noreverse nowriteback set trange [*:*] noreverse nowriteback set urange [*:*] noreverse nowriteback set vrange [*:*] noreverse nowriteback set xlabel matrix size set x2label set timefmt d m y n H
void addQuadTerm(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &vars)
static const symbolic::SymbolExpr< internal::symbolic_last_tag > last
void addRangeDouble(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double > const &vars)
static constexpr bool debug
Exception thrown if there is an error parsing a QPS file.
GaussianFactorGraph cost
Quadratic cost factors.
unsigned int numVariables
MPSGrammar(QPSVisitor *rqp)
const Symbol key1('v', 1)
static string fromChars(const FusionVector &vars)
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
void addRHSDouble(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double > const &vars)
std::unordered_map< std::string, double > b
std::unordered_map< std::string, double > ranges
std::unordered_map< Key, double > fx
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double >)> rangeDouble
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &)> rhsSingle
Factor graphs of a Quadratic Programming problem.
void addRHS(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &vars)
InequalityFactorGraph inequalities
linear inequality constraints: cI(x) <= 0
QPS parser implementation.
qi::rule< boost::spirit::basic_istream_iterator< char >, Chars()> word
void addColumnDouble(boost::fusion::vector< Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double > const &vars)
std::unordered_map< std::string, Key > varname_to_key
EqualityFactorGraph equalities
linear equality constraints: cE(x) = 0
Double_ range(const Point2_ &p, const Point2_ &q)
static double range1(const Camera &camera, const Pose3 &pose)
static EIGEN_DEPRECATED const end_t end
void addRangeSingle(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &vars)
std::vector< char > Chars
std::unordered_map< Key, std::unordered_map< Key, Matrix11 > > H
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &)> rangeSingle
A Gaussian factor using the canonical parameters (information form)
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &)> addQuadTerm
qi::rule< boost::spirit::basic_istream_iterator< char >, char()> character
Annotation for function names.
std::unordered_map< Key, double > lo
std::unordered_map< std::string, coefficient_v > constraint_v
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
void addColumn(boost::fusion::vector< Chars, Chars, Chars, Chars, Chars, double, Chars > const &vars)
def parse(input_path, output_path, quiet=False, generate_xml_flag=True)
std::unordered_map< Key, double > up
std::uint64_t Key
Integer nonlinear key type.
std::function< void(bf::vector< Chars, Chars, Chars, Chars, Chars, double, Chars, Chars, Chars, double >)> rhsDouble
std::unordered_map< Key, Vector1 > g
std::unordered_map< std::string, constraint_v * > row_to_constraint_v
std::vector< char > Chars
void setName(boost::fusion::vector< Chars, Chars, Chars > const &name)