[Lemon-commits] deba: r3092 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Wed Nov 29 18:35:31 CET 2006
Author: deba
Date: Wed Nov 29 18:35:31 2006
New Revision: 3092
Added:
hugo/trunk/lemon/lp_utils.h
Modified:
hugo/trunk/lemon/Makefile.am
Log:
Lp section reader
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Wed Nov 29 18:35:31 2006
@@ -76,6 +76,7 @@
lemon/lp_glpk.h \
lemon/lp_skeleton.h \
lemon/lp_soplex.h \
+ lemon/lp_utils.h \
lemon/map_iterator.h \
lemon/maps.h \
lemon/matrix_maps.h \
Added: hugo/trunk/lemon/lp_utils.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/lp_utils.h Wed Nov 29 18:35:31 2006
@@ -0,0 +1,364 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_LP_UTILS_H
+#define LEMON_LP_UTILS_H
+
+#include <lemon/lp_base.h>
+
+#include <lemon/lemon_reader.h>
+
+namespace lemon {
+
+ class LpReader : public LemonReader::SectionReader {
+ typedef LemonReader::SectionReader Parent;
+ public:
+
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for LpReader. It creates the LpReader and attach
+ /// it into the given LemonReader. The lp reader will add
+ /// variables, constraints and objective function to the
+ /// given lp solver.
+ LpReader(LemonReader& _reader, LpSolverBase& _lp,
+ const std::string& _name = std::string())
+ : Parent(_reader), lp(_lp), name(_name) {}
+
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for NodeSetReader.
+ virtual ~LpReader() {}
+
+ private:
+ LpReader(const LpReader&);
+ void operator=(const LpReader&);
+
+ protected:
+
+ /// \brief Gives back true when the SectionReader can process
+ /// the section with the given header line.
+ ///
+ /// It gives back true when the header line starts with \c \@lp,
+ /// and the header line's name and the nodeset's name are the same.
+ virtual bool header(const std::string& line) {
+ std::istringstream ls(line);
+ std::string command;
+ std::string id;
+ ls >> command >> id;
+ return command == "@lp" && name == id;
+ }
+
+ private:
+
+ enum Relation {
+ LE, EQ, GE
+ };
+
+ std::istream& readConstraint(std::istream& is, LpSolverBase::Constr& c) {
+ char x;
+ LpSolverBase::Expr e1, e2;
+ Relation op1;
+ is >> std::ws;
+ readExpression(is, e1);
+ is >> std::ws;
+ readRelation(is, op1);
+ is >> std::ws;
+ readExpression(is, e2);
+ if (!is.get(x)) {
+ if (op1 == LE) {
+ c = e1 <= e2;
+ } else if (op1 == GE) {
+ c = e1 >= e2;
+ } else {
+ c = e1 == e2;
+ }
+ } else {
+ is.putback(x);
+ LpSolverBase::Expr e3;
+ Relation op2;
+ readRelation(is, op2);
+ is >> std::ws;
+ readExpression(is, e3);
+ if (!e1.empty() || !e3.empty()) {
+ throw DataFormatError("Wrong range format");
+ }
+ if (op2 != op1 || op1 == EQ) {
+ throw DataFormatError("Wrong range format");
+ }
+ if (op1 == LE) {
+ c = e1.constComp() <= e2 <= e3.constComp();
+ } else {
+ c = e1.constComp() >= e2 >= e3.constComp();
+ }
+ }
+ }
+
+ std::istream& readExpression(std::istream& is, LpSolverBase::Expr& e) {
+ LpSolverBase::Col c;
+ double d;
+ char x;
+ readElement(is, c, d);
+ if (c != INVALID) {
+ e += d * c;
+ } else {
+ e += d;
+ }
+ is >> std::ws;
+ while (is.get(x) && (x == '+' || x == '-')) {
+ is >> std::ws;
+ readElement(is, c, d);
+ if (c != INVALID) {
+ e += (x == '+' ? d : -d) * c;
+ } else {
+ e += (x == '+' ? d : -d);
+ }
+ is >> std::ws;
+ }
+ if (!is) {
+ is.clear();
+ } else {
+ is.putback(x);
+ }
+ return is;
+ }
+
+ std::istream& readElement(std::istream& is,
+ LpSolverBase::Col& c, double& d) {
+ d = 1.0;
+ c = INVALID;
+ char x, y;
+ if (!is.get(x)) throw DataFormatError("Cannot find lp element");
+ if (x == '+' || x == '-') {
+ is >> std::ws;
+ d *= x == '-' ? -1 : 1;
+ while (is.get(x) && (x == '+' || x == '-')) {
+ d *= x == '-' ? -1 : 1;
+ is >> std::ws;
+ }
+ if (!is) throw DataFormatError("Cannot find lp element");
+ }
+ if (numFirstChar(x)) {
+ is.putback(x);
+ double e;
+ readNum(is, e);
+ d *= e;
+ } else if (varFirstChar(x)) {
+ is.putback(x);
+ LpSolverBase::Col f;
+ readCol(is, f);
+ c = f;
+ } else {
+ throw DataFormatError("Invalid expression format");
+ }
+ is >> std::ws;
+ while (is.get(y) && (y == '*' || y == '/')) {
+ is >> std::ws;
+ if (!is.get(x)) throw DataFormatError("Cannot find lp element");
+ if (x == '+' || x == '-') {
+ is >> std::ws;
+ d *= x == '-' ? -1 : 1;
+ while (is.get(x) && (x == '+' || x == '-')) {
+ d *= x == '-' ? -1 : 1;
+ is >> std::ws;
+ }
+ if (!is) throw DataFormatError("Cannot find lp element");
+ }
+ if (numFirstChar(x)) {
+ is.putback(x);
+ double e;
+ readNum(is, e);
+ if (y == '*') {
+ d *= e;
+ } else {
+ d /= e;
+ }
+ } else if (varFirstChar(x)) {
+ is.putback(x);
+ LpSolverBase::Col f;
+ readCol(is, f);
+ if (y == '*') {
+ if (c == INVALID) {
+ c = f;
+ } else {
+ throw DataFormatError("Quadratic element in expression");
+ }
+ } else {
+ throw DataFormatError("Division by variable");
+ }
+ } else {
+ throw DataFormatError("Invalid expression format");
+ }
+ is >> std::ws;
+ }
+ if (!is) {
+ is.clear();
+ } else {
+ is.putback(y);
+ }
+ return is;
+ }
+
+ std::istream& readCol(std::istream& is, LpSolverBase::Col& c) {
+ char x;
+ std::string var;
+ while (is.get(x) && varChar(x)) {
+ var += x;
+ }
+ if (!is) {
+ is.clear();
+ } else {
+ is.putback(x);
+ }
+ ColMap::const_iterator it = cols.find(var);
+ if (cols.find(var) != cols.end()) {
+ c = it->second;
+ } else {
+ c = lp.addCol();
+ cols.insert(std::make_pair(var, c));
+ lp.colName(c, var);
+ }
+ return is;
+ }
+
+ std::istream& readNum(std::istream& is, double& d) {
+ is >> d;
+ if (!is) throw DataFormatError("Wrong number format");
+ return is;
+ }
+
+ std::istream& readRelation(std::istream& is, Relation& op) {
+ char x, y;
+ if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) {
+ throw DataFormatError("Wrong relation operator");
+ }
+ if (!is.get(y) || y != '=') {
+ throw DataFormatError("Wrong relation operator");
+ }
+ switch (x) {
+ case '<': op = LE;
+ break;
+ case '=': op = EQ;
+ break;
+ case '>': op = GE;
+ break;
+ }
+ return is;
+ }
+
+ static bool relationFirstChar(char c) {
+ return c == '<' || c == '=' || c == '>';
+ }
+
+ static bool varFirstChar(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+ static bool numFirstChar(char c) {
+ return (c >= '0' && c <= '9') || c == '.';
+ }
+
+ static bool varChar(char c) {
+ return (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+
+ void addConstraint(const LpSolverBase::Constr& constr) {
+ if (constr.expr().size() != 1) {
+ lp.addRow(constr);
+ } else {
+ Lp::Expr e = constr.expr();
+ LpSolverBase::Col col = e.begin()->first;
+ double coeff = e.begin()->second;
+ double lb = LpSolverBase::NaN;
+ double ub = LpSolverBase::NaN;
+ if (coeff > 0) {
+ if (constr.upperBounded()) {
+ lb = (constr.lowerBound() - e.constComp()) / coeff;
+ }
+ if (constr.lowerBounded()) {
+ ub = (constr.upperBound() - e.constComp()) / coeff;
+ }
+ } else if (coeff < 0) {
+ if (constr.upperBounded()) {
+ lb = (constr.upperBound() - e.constComp()) / coeff;
+ }
+ if (constr.lowerBounded()) {
+ ub = (constr.lowerBound() - e.constComp()) / coeff;
+ }
+ } else {
+ lb = -LpSolverBase::INF;
+ ub = LpSolverBase::INF;
+ }
+ lp.colLowerBound(col, lb);
+ lp.colUpperBound(col, ub);
+ }
+ }
+
+ protected:
+
+ /// \brief Reader function of the section.
+ ///
+ /// It reads the content of the section.
+ virtual void read(std::istream& is) {
+ std::string line;
+ std::map<std::string, LpSolverBase::Col> vars;
+ while (getline(is, line)) {
+ std::istringstream ls(line);
+ std::string sense;
+ ls >> sense;
+ if (sense == "min" || sense == "max") {
+ LpSolverBase::Expr expr;
+ ls >> std::ws;
+ readExpression(ls, expr);
+ lp.setObj(expr);
+ if (sense == "min") {
+ lp.min();
+ } else {
+ lp.max();
+ }
+ } else {
+ ls.str(line);
+ LpSolverBase::Constr constr;
+ ls >> std::ws;
+ readConstraint(ls, constr);
+ addConstraint(constr);
+ }
+ }
+ }
+
+ virtual void missing() {
+ ErrorMessage msg;
+ msg << "Lp section not found in file: @lp " << name;
+ throw IoParameterError(msg.message());
+ }
+
+ private:
+
+ typedef std::map<std::string, LpSolverBase::Col> ColMap;
+
+ LpSolverBase& lp;
+ std::string name;
+ ColMap cols;
+ };
+
+}
+
+#endif
More information about the Lemon-commits
mailing list