deba@2316: /* -*- C++ -*- deba@2316: * deba@2316: * This file is a part of LEMON, a generic C++ optimization library deba@2316: * deba@2316: * Copyright (C) 2003-2006 deba@2316: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@2316: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@2316: * deba@2316: * Permission to use, modify and distribute this software is granted deba@2316: * provided that this copyright notice appears in all copies. For deba@2316: * precise terms see the accompanying LICENSE file. deba@2316: * deba@2316: * This software is provided "AS IS" with no warranty of any kind, deba@2316: * express or implied, and with no claim as to its suitability for any deba@2316: * purpose. deba@2316: * deba@2316: */ deba@2316: deba@2316: #ifndef LEMON_LP_UTILS_H deba@2316: #define LEMON_LP_UTILS_H deba@2316: deba@2316: #include deba@2316: deba@2316: #include deba@2363: #include deba@2316: deba@2316: namespace lemon { deba@2316: deba@2316: class LpReader : public LemonReader::SectionReader { deba@2316: typedef LemonReader::SectionReader Parent; deba@2316: public: deba@2316: deba@2316: deba@2316: /// \brief Constructor. deba@2316: /// deba@2316: /// Constructor for LpReader. It creates the LpReader and attach deba@2316: /// it into the given LemonReader. The lp reader will add deba@2316: /// variables, constraints and objective function to the deba@2316: /// given lp solver. deba@2316: LpReader(LemonReader& _reader, LpSolverBase& _lp, deba@2316: const std::string& _name = std::string()) deba@2316: : Parent(_reader), lp(_lp), name(_name) {} deba@2316: deba@2316: deba@2316: /// \brief Destructor. deba@2316: /// deba@2316: /// Destructor for NodeSetReader. deba@2316: virtual ~LpReader() {} deba@2316: deba@2316: private: deba@2316: LpReader(const LpReader&); deba@2316: void operator=(const LpReader&); deba@2316: deba@2316: protected: deba@2316: deba@2316: /// \brief Gives back true when the SectionReader can process deba@2316: /// the section with the given header line. deba@2316: /// deba@2316: /// It gives back true when the header line starts with \c \@lp, deba@2316: /// and the header line's name and the nodeset's name are the same. deba@2316: virtual bool header(const std::string& line) { deba@2316: std::istringstream ls(line); deba@2316: std::string command; deba@2316: std::string id; deba@2316: ls >> command >> id; deba@2316: return command == "@lp" && name == id; deba@2316: } deba@2316: deba@2316: private: deba@2316: deba@2316: enum Relation { deba@2316: LE, EQ, GE deba@2316: }; deba@2316: deba@2316: std::istream& readConstraint(std::istream& is, LpSolverBase::Constr& c) { deba@2316: char x; deba@2316: LpSolverBase::Expr e1, e2; deba@2316: Relation op1; deba@2316: is >> std::ws; deba@2316: readExpression(is, e1); deba@2316: is >> std::ws; deba@2316: readRelation(is, op1); deba@2316: is >> std::ws; deba@2316: readExpression(is, e2); deba@2316: if (!is.get(x)) { deba@2316: if (op1 == LE) { deba@2316: c = e1 <= e2; deba@2316: } else if (op1 == GE) { deba@2316: c = e1 >= e2; deba@2316: } else { deba@2316: c = e1 == e2; deba@2316: } deba@2316: } else { deba@2316: is.putback(x); deba@2316: LpSolverBase::Expr e3; deba@2316: Relation op2; deba@2316: readRelation(is, op2); deba@2316: is >> std::ws; deba@2316: readExpression(is, e3); deba@2316: if (!e1.empty() || !e3.empty()) { deba@2316: throw DataFormatError("Wrong range format"); deba@2316: } deba@2316: if (op2 != op1 || op1 == EQ) { deba@2316: throw DataFormatError("Wrong range format"); deba@2316: } deba@2316: if (op1 == LE) { deba@2316: c = e1.constComp() <= e2 <= e3.constComp(); deba@2316: } else { deba@2316: c = e1.constComp() >= e2 >= e3.constComp(); deba@2316: } deba@2316: } deba@2316: } deba@2316: deba@2316: std::istream& readExpression(std::istream& is, LpSolverBase::Expr& e) { deba@2316: LpSolverBase::Col c; deba@2316: double d; deba@2316: char x; deba@2316: readElement(is, c, d); deba@2316: if (c != INVALID) { deba@2316: e += d * c; deba@2316: } else { deba@2316: e += d; deba@2316: } deba@2316: is >> std::ws; deba@2316: while (is.get(x) && (x == '+' || x == '-')) { deba@2316: is >> std::ws; deba@2316: readElement(is, c, d); deba@2316: if (c != INVALID) { deba@2316: e += (x == '+' ? d : -d) * c; deba@2316: } else { deba@2316: e += (x == '+' ? d : -d); deba@2316: } deba@2316: is >> std::ws; deba@2316: } deba@2316: if (!is) { deba@2316: is.clear(); deba@2316: } else { deba@2316: is.putback(x); deba@2316: } deba@2316: return is; deba@2316: } deba@2316: deba@2316: std::istream& readElement(std::istream& is, deba@2316: LpSolverBase::Col& c, double& d) { deba@2316: d = 1.0; deba@2316: c = INVALID; deba@2316: char x, y; deba@2316: if (!is.get(x)) throw DataFormatError("Cannot find lp element"); deba@2316: if (x == '+' || x == '-') { deba@2316: is >> std::ws; deba@2316: d *= x == '-' ? -1 : 1; deba@2316: while (is.get(x) && (x == '+' || x == '-')) { deba@2316: d *= x == '-' ? -1 : 1; deba@2316: is >> std::ws; deba@2316: } deba@2316: if (!is) throw DataFormatError("Cannot find lp element"); deba@2316: } deba@2316: if (numFirstChar(x)) { deba@2316: is.putback(x); deba@2316: double e; deba@2316: readNum(is, e); deba@2316: d *= e; deba@2316: } else if (varFirstChar(x)) { deba@2316: is.putback(x); deba@2316: LpSolverBase::Col f; deba@2316: readCol(is, f); deba@2316: c = f; deba@2316: } else { deba@2316: throw DataFormatError("Invalid expression format"); deba@2316: } deba@2316: is >> std::ws; deba@2316: while (is.get(y) && (y == '*' || y == '/')) { deba@2316: is >> std::ws; deba@2316: if (!is.get(x)) throw DataFormatError("Cannot find lp element"); deba@2316: if (x == '+' || x == '-') { deba@2316: is >> std::ws; deba@2316: d *= x == '-' ? -1 : 1; deba@2316: while (is.get(x) && (x == '+' || x == '-')) { deba@2316: d *= x == '-' ? -1 : 1; deba@2316: is >> std::ws; deba@2316: } deba@2316: if (!is) throw DataFormatError("Cannot find lp element"); deba@2316: } deba@2316: if (numFirstChar(x)) { deba@2316: is.putback(x); deba@2316: double e; deba@2316: readNum(is, e); deba@2316: if (y == '*') { deba@2316: d *= e; deba@2316: } else { deba@2316: d /= e; deba@2316: } deba@2316: } else if (varFirstChar(x)) { deba@2316: is.putback(x); deba@2316: LpSolverBase::Col f; deba@2316: readCol(is, f); deba@2316: if (y == '*') { deba@2316: if (c == INVALID) { deba@2316: c = f; deba@2316: } else { deba@2316: throw DataFormatError("Quadratic element in expression"); deba@2316: } deba@2316: } else { deba@2316: throw DataFormatError("Division by variable"); deba@2316: } deba@2316: } else { deba@2316: throw DataFormatError("Invalid expression format"); deba@2316: } deba@2316: is >> std::ws; deba@2316: } deba@2316: if (!is) { deba@2316: is.clear(); deba@2316: } else { deba@2316: is.putback(y); deba@2316: } deba@2316: return is; deba@2316: } deba@2316: deba@2316: std::istream& readCol(std::istream& is, LpSolverBase::Col& c) { deba@2316: char x; deba@2316: std::string var; deba@2316: while (is.get(x) && varChar(x)) { deba@2316: var += x; deba@2316: } deba@2316: if (!is) { deba@2316: is.clear(); deba@2316: } else { deba@2316: is.putback(x); deba@2316: } deba@2316: ColMap::const_iterator it = cols.find(var); deba@2316: if (cols.find(var) != cols.end()) { deba@2316: c = it->second; deba@2316: } else { deba@2316: c = lp.addCol(); deba@2316: cols.insert(std::make_pair(var, c)); deba@2316: lp.colName(c, var); deba@2316: } deba@2316: return is; deba@2316: } deba@2316: deba@2316: std::istream& readNum(std::istream& is, double& d) { deba@2316: is >> d; deba@2316: if (!is) throw DataFormatError("Wrong number format"); deba@2316: return is; deba@2316: } deba@2316: deba@2316: std::istream& readRelation(std::istream& is, Relation& op) { deba@2316: char x, y; deba@2316: if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) { deba@2316: throw DataFormatError("Wrong relation operator"); deba@2316: } deba@2316: if (!is.get(y) || y != '=') { deba@2316: throw DataFormatError("Wrong relation operator"); deba@2316: } deba@2316: switch (x) { deba@2316: case '<': op = LE; deba@2316: break; deba@2316: case '=': op = EQ; deba@2316: break; deba@2316: case '>': op = GE; deba@2316: break; deba@2316: } deba@2316: return is; deba@2316: } deba@2316: deba@2316: static bool relationFirstChar(char c) { deba@2316: return c == '<' || c == '=' || c == '>'; deba@2316: } deba@2316: deba@2316: static bool varFirstChar(char c) { deba@2316: return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); deba@2316: } deba@2316: deba@2316: static bool numFirstChar(char c) { deba@2316: return (c >= '0' && c <= '9') || c == '.'; deba@2316: } deba@2316: deba@2316: static bool varChar(char c) { deba@2316: return (c >= '0' && c <= '9') || deba@2316: (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); deba@2316: } deba@2316: deba@2316: deba@2316: void addConstraint(const LpSolverBase::Constr& constr) { deba@2316: if (constr.expr().size() != 1) { deba@2316: lp.addRow(constr); deba@2316: } else { deba@2316: Lp::Expr e = constr.expr(); deba@2316: LpSolverBase::Col col = e.begin()->first; deba@2316: double coeff = e.begin()->second; deba@2316: double lb = LpSolverBase::NaN; deba@2316: double ub = LpSolverBase::NaN; deba@2316: if (coeff > 0) { deba@2316: if (constr.upperBounded()) { deba@2316: lb = (constr.lowerBound() - e.constComp()) / coeff; deba@2316: } deba@2316: if (constr.lowerBounded()) { deba@2316: ub = (constr.upperBound() - e.constComp()) / coeff; deba@2316: } deba@2316: } else if (coeff < 0) { deba@2316: if (constr.upperBounded()) { deba@2316: lb = (constr.upperBound() - e.constComp()) / coeff; deba@2316: } deba@2316: if (constr.lowerBounded()) { deba@2316: ub = (constr.lowerBound() - e.constComp()) / coeff; deba@2316: } deba@2316: } else { deba@2316: lb = -LpSolverBase::INF; deba@2316: ub = LpSolverBase::INF; deba@2316: } deba@2316: lp.colLowerBound(col, lb); deba@2316: lp.colUpperBound(col, ub); deba@2316: } deba@2316: } deba@2316: deba@2316: protected: deba@2316: deba@2316: /// \brief Reader function of the section. deba@2316: /// deba@2316: /// It reads the content of the section. deba@2316: virtual void read(std::istream& is) { deba@2316: std::string line; deba@2316: while (getline(is, line)) { deba@2316: std::istringstream ls(line); deba@2316: std::string sense; deba@2316: ls >> sense; deba@2316: if (sense == "min" || sense == "max") { deba@2316: LpSolverBase::Expr expr; deba@2316: ls >> std::ws; deba@2316: readExpression(ls, expr); deba@2316: lp.setObj(expr); deba@2316: if (sense == "min") { deba@2316: lp.min(); deba@2316: } else { deba@2316: lp.max(); deba@2316: } deba@2316: } else { deba@2316: ls.str(line); deba@2316: LpSolverBase::Constr constr; deba@2316: ls >> std::ws; deba@2316: readConstraint(ls, constr); deba@2316: addConstraint(constr); deba@2316: } deba@2316: } deba@2316: } deba@2316: deba@2316: virtual void missing() { deba@2316: ErrorMessage msg; deba@2316: msg << "Lp section not found in file: @lp " << name; deba@2316: throw IoParameterError(msg.message()); deba@2316: } deba@2316: deba@2316: private: deba@2316: deba@2316: typedef std::map ColMap; deba@2316: deba@2316: LpSolverBase& lp; deba@2316: std::string name; deba@2316: ColMap cols; deba@2316: }; deba@2316: deba@2363: deba@2363: // class LpWriter : public LemonWriter::SectionWriter { deba@2363: // typedef LemonWriter::SectionWriter Parent; deba@2363: // public: deba@2363: deba@2363: deba@2363: // /// \brief Constructor. deba@2363: // /// deba@2363: // /// Constructor for LpWriter. It creates the LpWriter and attach deba@2363: // /// it into the given LemonWriter. The lp writer will add deba@2363: // /// variables, constraints and objective function to the deba@2363: // /// given lp solver. deba@2363: // LpWriter(LemonWriter& _writer, LpSolverBase& _lp, deba@2363: // const std::string& _name = std::string()) deba@2363: // : Parent(_writer), lp(_lp), name(_name) {} deba@2363: deba@2363: deba@2363: // /// \brief Destructor. deba@2363: // /// deba@2363: // /// Destructor for NodeSetWriter. deba@2363: // virtual ~LpWriter() {} deba@2363: deba@2363: // private: deba@2363: // LpWriter(const LpWriter&); deba@2363: // void operator=(const LpWriter&); deba@2363: deba@2363: // protected: deba@2363: deba@2363: // /// \brief Gives back true when the SectionWriter can process deba@2363: // /// the section with the given header line. deba@2363: // /// deba@2363: // /// It gives back the header line of the \c \@lp section. deba@2363: // virtual std::string header() { deba@2363: // std::ostringstream ls(line); deba@2363: // ls << "@lp " << name; deba@2363: // return ls.str(); deba@2363: // } deba@2363: deba@2363: // private: deba@2363: deba@2363: // std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) { deba@2363: // char x; deba@2363: deba@2363: deba@2363: // LpSolverBase::Expr e1, e2; deba@2363: // Relation op1; deba@2363: // is >> std::ws; deba@2363: // writexpression(is, e1); deba@2363: // is >> std::ws; deba@2363: // writeRelation(is, op1); deba@2363: // is >> std::ws; deba@2363: // writexpression(is, e2); deba@2363: // if (!is.get(x)) { deba@2363: // if (op1 == LE) { deba@2363: // c = e1 <= e2; deba@2363: // } else if (op1 == GE) { deba@2363: // c = e1 >= e2; deba@2363: // } else { deba@2363: // c = e1 == e2; deba@2363: // } deba@2363: // } else { deba@2363: // is.putback(x); deba@2363: // LpSolverBase::Expr e3; deba@2363: // Relation op2; deba@2363: // writeRelation(is, op2); deba@2363: // is >> std::ws; deba@2363: // writexpression(is, e3); deba@2363: // if (!e1.empty() || !e3.empty()) { deba@2363: // throw DataFormatError("Wrong range format"); deba@2363: // } deba@2363: // if (op2 != op1 || op1 == EQ) { deba@2363: // throw DataFormatError("Wrong range format"); deba@2363: // } deba@2363: // if (op1 == LE) { deba@2363: // c = e1.constComp() <= e2 <= e3.constComp(); deba@2363: // } else { deba@2363: // c = e1.constComp() >= e2 >= e3.constComp(); deba@2363: // } deba@2363: // } deba@2363: // } deba@2363: deba@2363: // std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) { deba@2363: // LpSolverBase::Col c; deba@2363: // double d; deba@2363: // char x; deba@2363: // writelement(is, c, d); deba@2363: // if (c != INVALID) { deba@2363: // e += d * c; deba@2363: // } else { deba@2363: // e += d; deba@2363: // } deba@2363: // is >> std::ws; deba@2363: // while (is.get(x) && (x == '+' || x == '-')) { deba@2363: // is >> std::ws; deba@2363: // writelement(is, c, d); deba@2363: // if (c != INVALID) { deba@2363: // e += (x == '+' ? d : -d) * c; deba@2363: // } else { deba@2363: // e += (x == '+' ? d : -d); deba@2363: // } deba@2363: // is >> std::ws; deba@2363: // } deba@2363: // if (!is) { deba@2363: // is.clear(); deba@2363: // } else { deba@2363: // is.putback(x); deba@2363: // } deba@2363: // return is; deba@2363: // } deba@2363: deba@2363: // std::ostream& writelement(std::ostream& is, deba@2363: // LpSolverBase::Col& c, double& d) { deba@2363: // d = 1.0; deba@2363: // c = INVALID; deba@2363: // char x, y; deba@2363: // if (!is.get(x)) throw DataFormatError("Cannot find lp element"); deba@2363: // if (x == '+' || x == '-') { deba@2363: // is >> std::ws; deba@2363: // d *= x == '-' ? -1 : 1; deba@2363: // while (is.get(x) && (x == '+' || x == '-')) { deba@2363: // d *= x == '-' ? -1 : 1; deba@2363: // is >> std::ws; deba@2363: // } deba@2363: // if (!is) throw DataFormatError("Cannot find lp element"); deba@2363: // } deba@2363: // if (numFirstChar(x)) { deba@2363: // is.putback(x); deba@2363: // double e; deba@2363: // writeNum(is, e); deba@2363: // d *= e; deba@2363: // } else if (varFirstChar(x)) { deba@2363: // is.putback(x); deba@2363: // LpSolverBase::Col f; deba@2363: // writeCol(is, f); deba@2363: // c = f; deba@2363: // } else { deba@2363: // throw DataFormatError("Invalid expression format"); deba@2363: // } deba@2363: // is >> std::ws; deba@2363: // while (is.get(y) && (y == '*' || y == '/')) { deba@2363: // is >> std::ws; deba@2363: // if (!is.get(x)) throw DataFormatError("Cannot find lp element"); deba@2363: // if (x == '+' || x == '-') { deba@2363: // is >> std::ws; deba@2363: // d *= x == '-' ? -1 : 1; deba@2363: // while (is.get(x) && (x == '+' || x == '-')) { deba@2363: // d *= x == '-' ? -1 : 1; deba@2363: // is >> std::ws; deba@2363: // } deba@2363: // if (!is) throw DataFormatError("Cannot find lp element"); deba@2363: // } deba@2363: // if (numFirstChar(x)) { deba@2363: // is.putback(x); deba@2363: // double e; deba@2363: // writeNum(is, e); deba@2363: // if (y == '*') { deba@2363: // d *= e; deba@2363: // } else { deba@2363: // d /= e; deba@2363: // } deba@2363: // } else if (varFirstChar(x)) { deba@2363: // is.putback(x); deba@2363: // LpSolverBase::Col f; deba@2363: // writeCol(is, f); deba@2363: // if (y == '*') { deba@2363: // if (c == INVALID) { deba@2363: // c = f; deba@2363: // } else { deba@2363: // throw DataFormatError("Quadratic element in expression"); deba@2363: // } deba@2363: // } else { deba@2363: // throw DataFormatError("Division by variable"); deba@2363: // } deba@2363: // } else { deba@2363: // throw DataFormatError("Invalid expression format"); deba@2363: // } deba@2363: // is >> std::ws; deba@2363: // } deba@2363: // if (!is) { deba@2363: // is.clear(); deba@2363: // } else { deba@2363: // is.putback(y); deba@2363: // } deba@2363: // return is; deba@2363: // } deba@2363: deba@2363: // std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) { deba@2363: // char x; deba@2363: // std::string var; deba@2363: // while (is.get(x) && varChar(x)) { deba@2363: // var += x; deba@2363: // } deba@2363: // if (!is) { deba@2363: // is.clear(); deba@2363: // } else { deba@2363: // is.putback(x); deba@2363: // } deba@2363: // ColMap::const_iterator it = cols.find(var); deba@2363: // if (cols.find(var) != cols.end()) { deba@2363: // c = it->second; deba@2363: // } else { deba@2363: // c = lp.addCol(); deba@2363: // cols.insert(std::make_pair(var, c)); deba@2363: // lp.colName(c, var); deba@2363: // } deba@2363: // return is; deba@2363: // } deba@2363: deba@2363: // std::ostream& writeNum(std::ostream& is, double& d) { deba@2363: // is >> d; deba@2363: // if (!is) throw DataFormatError("Wrong number format"); deba@2363: // return is; deba@2363: // } deba@2363: deba@2363: // std::ostream& writeRelation(std::ostream& is, Relation& op) { deba@2363: // char x, y; deba@2363: // if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) { deba@2363: // throw DataFormatError("Wrong relation operator"); deba@2363: // } deba@2363: // if (!is.get(y) || y != '=') { deba@2363: // throw DataFormatError("Wrong relation operator"); deba@2363: // } deba@2363: // switch (x) { deba@2363: // case '<': op = LE; deba@2363: // break; deba@2363: // case '=': op = EQ; deba@2363: // break; deba@2363: // case '>': op = GE; deba@2363: // break; deba@2363: // } deba@2363: // return is; deba@2363: // } deba@2363: deba@2363: // static bool relationFirstChar(char c) { deba@2363: // return c == '<' || c == '=' || c == '>'; deba@2363: // } deba@2363: deba@2363: // static bool varFirstChar(char c) { deba@2363: // return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); deba@2363: // } deba@2363: deba@2363: // static bool numFirstChar(char c) { deba@2363: // return (c >= '0' && c <= '9') || c == '.'; deba@2363: // } deba@2363: deba@2363: // static bool varChar(char c) { deba@2363: // return (c >= '0' && c <= '9') || deba@2363: // (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); deba@2363: // } deba@2363: deba@2363: deba@2363: // void addConstraint(const LpSolverBase::Constr& constr) { deba@2363: // if (constr.expr().size() != 1) { deba@2363: // lp.addRow(constr); deba@2363: // } else { deba@2363: // Lp::Expr e = constr.expr(); deba@2363: // LpSolverBase::Col col = e.begin()->first; deba@2363: // double coeff = e.begin()->second; deba@2363: // double lb = LpSolverBase::NaN; deba@2363: // double ub = LpSolverBase::NaN; deba@2363: // if (coeff > 0) { deba@2363: // if (constr.upperBounded()) { deba@2363: // lb = (constr.lowerBound() - e.constComp()) / coeff; deba@2363: // } deba@2363: // if (constr.lowerBounded()) { deba@2363: // ub = (constr.upperBound() - e.constComp()) / coeff; deba@2363: // } deba@2363: // } else if (coeff < 0) { deba@2363: // if (constr.upperBounded()) { deba@2363: // lb = (constr.upperBound() - e.constComp()) / coeff; deba@2363: // } deba@2363: // if (constr.lowerBounded()) { deba@2363: // ub = (constr.lowerBound() - e.constComp()) / coeff; deba@2363: // } deba@2363: // } else { deba@2363: // lb = -LpSolverBase::INF; deba@2363: // ub = LpSolverBase::INF; deba@2363: // } deba@2363: // lp.colLowerBound(col, lb); deba@2363: // lp.colUpperBound(col, ub); deba@2363: // } deba@2363: // } deba@2363: deba@2363: // protected: deba@2363: deba@2363: // /// \brief Writer function of the section. deba@2363: // /// deba@2363: // /// It writes the content of the section. deba@2363: // virtual void write(std::ostream& is) { deba@2363: // std::string line; deba@2363: // std::map vars; deba@2363: // while (getline(is, line)) { deba@2363: // std::istringstream ls(line); deba@2363: // std::string sense; deba@2363: // ls >> sense; deba@2363: // if (sense == "min" || sense == "max") { deba@2363: // LpSolverBase::Expr expr; deba@2363: // ls >> std::ws; deba@2363: // writeExpression(ls, expr); deba@2363: // lp.setObj(expr); deba@2363: // if (sense == "min") { deba@2363: // lp.min(); deba@2363: // } else { deba@2363: // lp.max(); deba@2363: // } deba@2363: // } else { deba@2363: // ls.str(line); deba@2363: // LpSolverBase::Constr constr; deba@2363: // ls >> std::ws; deba@2363: // writeConstraint(ls, constr); deba@2363: // addConstraint(constr); deba@2363: // } deba@2363: // } deba@2363: // } deba@2363: deba@2363: // virtual void missing() { deba@2363: // ErrorMessage msg; deba@2363: // msg << "Lp section not found in file: @lp " << name; deba@2363: // throw IoParameterError(msg.message()); deba@2363: // } deba@2363: deba@2363: // private: deba@2363: deba@2363: // typedef std::map ColMap; deba@2363: deba@2363: // LpSolverBase& lp; deba@2363: // std::string name; deba@2363: // ColMap cols; deba@2363: // }; deba@2363: deba@2316: } deba@2316: deba@2316: #endif