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;
42 using namespace std::placeholders;
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);
301 for (
size_t i = 0;
i <
keys.size(); ++
i) {
302 for (
size_t j =
i;
j <
keys.size(); ++
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 &)>
424 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>
const &)>
430 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>)>
436 bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>
const &)>
439 Chars,
double>
const &)>
442 bf::vector<Chars, Chars, Chars, Chars, Chars, Chars, Chars>
const &)>
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;