[TEST] Now includes a test with QPS ranges

[FEATURE] Parser Reads but doesn't handle ranges in QPS files.
release/4.3a0
= 2016-06-28 20:53:59 -04:00
parent ab045edf07
commit b467e944cf
4 changed files with 57 additions and 5 deletions

View File

@ -43,6 +43,12 @@ struct QPSParser::MPSGrammar: base_grammar {
void(
bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars, Chars,
Chars, double>)> rhsDouble;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars> const &)> rangeSingle;
boost::function<
void(
bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars, Chars,
Chars, double>)> rangeDouble;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>)> colSingle;
boost::function<
@ -61,7 +67,9 @@ struct QPSParser::MPSGrammar: base_grammar {
boost::bind(&RawQP::setName, rqp, ::_1)), addRow(
boost::bind(&RawQP::addRow, rqp, ::_1)), rhsSingle(
boost::bind(&RawQP::addRHS, rqp, ::_1)), rhsDouble(
boost::bind(&RawQP::addRHSDouble, rqp, ::_1)), colSingle(
boost::bind(&RawQP::addRHSDouble, rqp, ::_1)), rangeSingle(
boost::bind(&RawQP::addRangeSingle, rqp, ::_1)), rangeDouble(
boost::bind(&RawQP::addRangeDouble, rqp, ::_1)), colSingle(
boost::bind(&RawQP::addColumn, rqp, ::_1)), colDouble(
boost::bind(&RawQP::addColumnDouble, rqp, ::_1)), addQuadTerm(
boost::bind(&RawQP::addQuadTerm, rqp, ::_1)), addBound(
@ -78,6 +86,10 @@ struct QPSParser::MPSGrammar: base_grammar {
>> *blank][rhsSingle];
rhs_double = lexeme[(*blank >> word >> +blank >> word >> +blank >> double_
>> +blank >> word >> +blank >> double_)[rhsDouble] >> *blank];
range_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][rangeSingle];
range_double = lexeme[(*blank >> word >> +blank >> word >> +blank >> double_
>> +blank >> word >> +blank >> double_)[rangeDouble] >> *blank];
col_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][colSingle];
col_double = lexeme[*blank
@ -96,7 +108,8 @@ struct QPSParser::MPSGrammar: base_grammar {
>> +((col_double | col_single) >> eol)];
quad = lexeme[lit("QUADOBJ") >> *blank >> eol >> +(quad_l >> eol)];
bounds = lexeme[lit("BOUNDS") >> +space >> +((bound | bound_fr) >> eol)];
ranges = lexeme[lit("RANGES") >> +space];
ranges = lexeme[lit("RANGES") >> +space
>> *((range_double | range_single) >> eol)];
end = lexeme[lit("ENDATA") >> *space];
start = lexeme[name >> rows >> cols >> rhs >> -ranges >> bounds >> quad
>> end];
@ -105,8 +118,8 @@ struct QPSParser::MPSGrammar: base_grammar {
qi::rule<boost::spirit::basic_istream_iterator<char>, char()> character;
qi::rule<boost::spirit::basic_istream_iterator<char>, Chars()> word, title;
qi::rule<boost::spirit::basic_istream_iterator<char> > row, end, col_single,
col_double, rhs_single, rhs_double, ranges, bound, bound_fr, bounds, quad,
quad_l, rows, cols, rhs, name, start;
col_double, rhs_single, rhs_double, range_single, range_double, ranges,
bound, bound_fr, bounds, quad, quad_l, rows, cols, rhs, name, start;
};
QP QPSParser::Parse() {

View File

@ -77,6 +77,19 @@ void RawQP::addColumnDouble(
(*row_to_constraint_v[row2_])[row2_][varname_to_key[var_]] = coefficient2;
}
void RawQP::addRangeSingle(
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::cout << "SINGLE RANGE ADDED" << std::endl;
}
void RawQP::addRangeDouble(
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::cout << "DOUBLE RANGE ADDED" << std::endl;
}
void RawQP::addRHS(
boost::fusion::vector<std::vector<char>, std::vector<char>,
std::vector<char>, std::vector<char>, std::vector<char>, double,

View File

@ -30,6 +30,10 @@
#include <boost/fusion/include/vector.hpp>
namespace gtsam {
/**
* This class is responsible for collecting a QP problem as the parser parses a QPS file
* and then generating a QP problem.
*/
class RawQP {
private:
typedef std::unordered_map<Key, Matrix11> coefficient_v;
@ -56,7 +60,7 @@ public:
RawQP() :
row_to_constraint_v(), E(), IG(), IL(), varNumber(1), b(), g(), varname_to_key(), H(), f(), obj_name(), name_(), up(), lo(), Free() {
}
void setName(
boost::fusion::vector<std::vector<char>, std::vector<char>,
std::vector<char>> const & name);
@ -81,6 +85,16 @@ public:
std::vector<char>, std::vector<char>, std::vector<char>, double,
std::vector<char>, std::vector<char>, std::vector<char>, double> const & vars);
void addRangeSingle(
boost::fusion::vector<std::vector<char>, std::vector<char>,
std::vector<char>, std::vector<char>, std::vector<char>, double,
std::vector<char>> const & vars);
void addRangeDouble(
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);
void addRow(
boost::fusion::vector<std::vector<char>, char, std::vector<char>,
std::vector<char>, std::vector<char>> const & vars);

View File

@ -281,6 +281,18 @@ TEST(QPSolver, HS21) {
CHECK(assert_equal(expectedSolution, actualSolution))
}
TEST(QPSolver, HS118) {
QP problem = QPSParser("HS118.QPS").Parse();
VectorValues actualSolution;
VectorValues expectedSolution;
// expectedSolution.insert(Symbol('X',1), 2.0*I_1x1);
// expectedSolution.insert(Symbol('X',2), 0.0*I_1x1);
boost::tie(actualSolution, boost::tuples::ignore) = QPSolver(problem).optimize();
double error_actual = problem.cost.error(actualSolution);
CHECK(assert_equal(6.64820452e2,error_actual, 1e-7))
// CHECK(assert_equal(expectedSolution, actualSolution))
}
/* ************************************************************************* */
// Create Matlab's test graph as in http://www.mathworks.com/help/optim/ug/quadprog.html
QP createTestMatlabQPEx() {