lemon/lp_utils.h
author deba
Thu, 15 Feb 2007 14:22:08 +0000
changeset 2363 2aabce558574
parent 2316 c0fae4bbaa5c
child 2364 3a5e67bd42d2
permissions -rw-r--r--
Changes on the LP interface

_FixId => LpId
- handling of not common ids // soplex
LpGlpk row and col erase bug fix
- calling lpx_std_basis before simplex
LpSoplex
- added getter functions
- better m4 file
- integration to the tests
- better handling of unsolved lps
deba@2316
     1
/* -*- C++ -*-
deba@2316
     2
 *
deba@2316
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2316
     4
 *
deba@2316
     5
 * Copyright (C) 2003-2006
deba@2316
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2316
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2316
     8
 *
deba@2316
     9
 * Permission to use, modify and distribute this software is granted
deba@2316
    10
 * provided that this copyright notice appears in all copies. For
deba@2316
    11
 * precise terms see the accompanying LICENSE file.
deba@2316
    12
 *
deba@2316
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2316
    14
 * express or implied, and with no claim as to its suitability for any
deba@2316
    15
 * purpose.
deba@2316
    16
 *
deba@2316
    17
 */
deba@2316
    18
deba@2316
    19
#ifndef LEMON_LP_UTILS_H
deba@2316
    20
#define LEMON_LP_UTILS_H
deba@2316
    21
deba@2316
    22
#include <lemon/lp_base.h>
deba@2316
    23
deba@2316
    24
#include <lemon/lemon_reader.h>
deba@2363
    25
#include <lemon/lemon_writer.h>
deba@2316
    26
deba@2316
    27
namespace lemon {
deba@2316
    28
deba@2316
    29
  class LpReader : public LemonReader::SectionReader {
deba@2316
    30
    typedef LemonReader::SectionReader Parent;
deba@2316
    31
  public:
deba@2316
    32
deba@2316
    33
deba@2316
    34
    /// \brief Constructor.
deba@2316
    35
    ///
deba@2316
    36
    /// Constructor for LpReader. It creates the LpReader and attach
deba@2316
    37
    /// it into the given LemonReader. The lp reader will add
deba@2316
    38
    /// variables, constraints and objective function to the
deba@2316
    39
    /// given lp solver.
deba@2316
    40
    LpReader(LemonReader& _reader, LpSolverBase& _lp, 
deba@2316
    41
             const std::string& _name = std::string())
deba@2316
    42
      : Parent(_reader), lp(_lp), name(_name) {} 
deba@2316
    43
deba@2316
    44
deba@2316
    45
    /// \brief Destructor.
deba@2316
    46
    ///
deba@2316
    47
    /// Destructor for NodeSetReader.
deba@2316
    48
    virtual ~LpReader() {}
deba@2316
    49
deba@2316
    50
  private:
deba@2316
    51
    LpReader(const LpReader&);
deba@2316
    52
    void operator=(const LpReader&);
deba@2316
    53
  
deba@2316
    54
  protected:
deba@2316
    55
deba@2316
    56
    /// \brief Gives back true when the SectionReader can process 
deba@2316
    57
    /// the section with the given header line.
deba@2316
    58
    ///
deba@2316
    59
    /// It gives back true when the header line starts with \c \@lp,
deba@2316
    60
    /// and the header line's name and the nodeset's name are the same.
deba@2316
    61
    virtual bool header(const std::string& line) {
deba@2316
    62
      std::istringstream ls(line);
deba@2316
    63
      std::string command;
deba@2316
    64
      std::string id;
deba@2316
    65
      ls >> command >> id;
deba@2316
    66
      return command == "@lp" && name == id;
deba@2316
    67
    }
deba@2316
    68
deba@2316
    69
  private:
deba@2316
    70
deba@2316
    71
    enum Relation {
deba@2316
    72
      LE, EQ, GE
deba@2316
    73
    };
deba@2316
    74
deba@2316
    75
    std::istream& readConstraint(std::istream& is, LpSolverBase::Constr& c) {
deba@2316
    76
      char x;
deba@2316
    77
      LpSolverBase::Expr e1, e2;
deba@2316
    78
      Relation op1;
deba@2316
    79
      is >> std::ws;
deba@2316
    80
      readExpression(is, e1);
deba@2316
    81
      is >> std::ws;
deba@2316
    82
      readRelation(is, op1);
deba@2316
    83
      is >> std::ws;
deba@2316
    84
      readExpression(is, e2);
deba@2316
    85
      if (!is.get(x)) {
deba@2316
    86
        if (op1 == LE) {
deba@2316
    87
          c = e1 <= e2;
deba@2316
    88
        } else if (op1 == GE) {
deba@2316
    89
          c = e1 >= e2;
deba@2316
    90
        } else {
deba@2316
    91
          c = e1 == e2;
deba@2316
    92
        }
deba@2316
    93
      } else {
deba@2316
    94
        is.putback(x);
deba@2316
    95
        LpSolverBase::Expr e3;
deba@2316
    96
        Relation op2;
deba@2316
    97
        readRelation(is, op2);
deba@2316
    98
        is >> std::ws;
deba@2316
    99
        readExpression(is, e3);
deba@2316
   100
        if (!e1.empty() || !e3.empty()) {
deba@2316
   101
          throw DataFormatError("Wrong range format");
deba@2316
   102
        }
deba@2316
   103
        if (op2 != op1 || op1 == EQ) {
deba@2316
   104
          throw DataFormatError("Wrong range format");
deba@2316
   105
        }
deba@2316
   106
        if (op1 == LE) {
deba@2316
   107
          c = e1.constComp() <= e2 <= e3.constComp();
deba@2316
   108
        } else {
deba@2316
   109
          c = e1.constComp() >= e2 >= e3.constComp();
deba@2316
   110
        }
deba@2316
   111
      }
deba@2316
   112
    }
deba@2316
   113
deba@2316
   114
    std::istream& readExpression(std::istream& is, LpSolverBase::Expr& e) {
deba@2316
   115
      LpSolverBase::Col c;
deba@2316
   116
      double d;
deba@2316
   117
      char x;
deba@2316
   118
      readElement(is, c, d);
deba@2316
   119
      if (c != INVALID) {
deba@2316
   120
        e += d * c;
deba@2316
   121
      } else {
deba@2316
   122
        e += d;
deba@2316
   123
      }
deba@2316
   124
      is >> std::ws;
deba@2316
   125
      while (is.get(x) && (x == '+' || x == '-')) {
deba@2316
   126
        is >> std::ws;
deba@2316
   127
        readElement(is, c, d);
deba@2316
   128
        if (c != INVALID) {
deba@2316
   129
          e += (x == '+' ? d : -d) * c;
deba@2316
   130
        } else {
deba@2316
   131
          e += (x == '+' ? d : -d);
deba@2316
   132
        }
deba@2316
   133
        is >> std::ws;
deba@2316
   134
      }
deba@2316
   135
      if (!is) {
deba@2316
   136
        is.clear();
deba@2316
   137
      } else {
deba@2316
   138
        is.putback(x);
deba@2316
   139
      }
deba@2316
   140
      return is;
deba@2316
   141
    }
deba@2316
   142
deba@2316
   143
    std::istream& readElement(std::istream& is, 
deba@2316
   144
                              LpSolverBase::Col& c, double& d) { 
deba@2316
   145
      d = 1.0;
deba@2316
   146
      c = INVALID;
deba@2316
   147
      char x, y;
deba@2316
   148
      if (!is.get(x)) throw DataFormatError("Cannot find lp element");
deba@2316
   149
      if (x == '+' || x == '-') {
deba@2316
   150
        is >> std::ws;
deba@2316
   151
        d *= x == '-' ? -1 : 1;
deba@2316
   152
        while (is.get(x) && (x == '+' || x == '-')) {
deba@2316
   153
          d *= x == '-' ? -1 : 1;
deba@2316
   154
          is >> std::ws;
deba@2316
   155
        }
deba@2316
   156
        if (!is) throw DataFormatError("Cannot find lp element");
deba@2316
   157
      }
deba@2316
   158
      if (numFirstChar(x)) {
deba@2316
   159
        is.putback(x);
deba@2316
   160
        double e;
deba@2316
   161
        readNum(is, e);
deba@2316
   162
        d *= e;
deba@2316
   163
      } else if (varFirstChar(x)) {
deba@2316
   164
        is.putback(x);
deba@2316
   165
        LpSolverBase::Col f;
deba@2316
   166
        readCol(is, f);
deba@2316
   167
        c = f;
deba@2316
   168
      } else {
deba@2316
   169
        throw DataFormatError("Invalid expression format");          
deba@2316
   170
      }
deba@2316
   171
      is >> std::ws;
deba@2316
   172
      while (is.get(y) && (y == '*' || y == '/')) {
deba@2316
   173
        is >> std::ws;
deba@2316
   174
        if (!is.get(x)) throw DataFormatError("Cannot find lp element");
deba@2316
   175
        if (x == '+' || x == '-') {
deba@2316
   176
          is >> std::ws;
deba@2316
   177
          d *= x == '-' ? -1 : 1;
deba@2316
   178
          while (is.get(x) && (x == '+' || x == '-')) {
deba@2316
   179
            d *= x == '-' ? -1 : 1;
deba@2316
   180
            is >> std::ws;
deba@2316
   181
          }
deba@2316
   182
          if (!is) throw DataFormatError("Cannot find lp element");
deba@2316
   183
        }
deba@2316
   184
        if (numFirstChar(x)) {
deba@2316
   185
          is.putback(x);
deba@2316
   186
          double e;
deba@2316
   187
          readNum(is, e);
deba@2316
   188
          if (y == '*') {
deba@2316
   189
            d *= e;
deba@2316
   190
          } else {
deba@2316
   191
            d /= e;
deba@2316
   192
          }
deba@2316
   193
        } else if (varFirstChar(x)) {
deba@2316
   194
          is.putback(x);
deba@2316
   195
          LpSolverBase::Col f;
deba@2316
   196
          readCol(is, f);
deba@2316
   197
          if (y == '*') {
deba@2316
   198
            if (c == INVALID) {
deba@2316
   199
              c = f;
deba@2316
   200
            } else {
deba@2316
   201
              throw DataFormatError("Quadratic element in expression");
deba@2316
   202
            }
deba@2316
   203
          } else {
deba@2316
   204
            throw DataFormatError("Division by variable");
deba@2316
   205
          }
deba@2316
   206
        } else {
deba@2316
   207
          throw DataFormatError("Invalid expression format");          
deba@2316
   208
        }
deba@2316
   209
        is >> std::ws;
deba@2316
   210
      }
deba@2316
   211
      if (!is) {
deba@2316
   212
        is.clear();
deba@2316
   213
      } else {
deba@2316
   214
        is.putback(y);
deba@2316
   215
      }
deba@2316
   216
      return is;
deba@2316
   217
    }
deba@2316
   218
deba@2316
   219
    std::istream& readCol(std::istream& is, LpSolverBase::Col& c) {
deba@2316
   220
      char x;
deba@2316
   221
      std::string var;
deba@2316
   222
      while (is.get(x) && varChar(x)) {
deba@2316
   223
        var += x;
deba@2316
   224
      }
deba@2316
   225
      if (!is) {
deba@2316
   226
        is.clear();
deba@2316
   227
      } else {
deba@2316
   228
        is.putback(x);
deba@2316
   229
      }
deba@2316
   230
      ColMap::const_iterator it = cols.find(var);
deba@2316
   231
      if (cols.find(var) != cols.end()) {
deba@2316
   232
        c = it->second;
deba@2316
   233
      } else {
deba@2316
   234
        c = lp.addCol();
deba@2316
   235
        cols.insert(std::make_pair(var, c));
deba@2316
   236
        lp.colName(c, var);
deba@2316
   237
      }
deba@2316
   238
      return is;
deba@2316
   239
    }
deba@2316
   240
deba@2316
   241
    std::istream& readNum(std::istream& is, double& d) {
deba@2316
   242
      is >> d;
deba@2316
   243
      if (!is) throw DataFormatError("Wrong number format");
deba@2316
   244
      return is;
deba@2316
   245
    }
deba@2316
   246
deba@2316
   247
    std::istream& readRelation(std::istream& is, Relation& op) {
deba@2316
   248
      char x, y;
deba@2316
   249
      if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) {
deba@2316
   250
        throw DataFormatError("Wrong relation operator");
deba@2316
   251
      }
deba@2316
   252
      if (!is.get(y) || y != '=') {
deba@2316
   253
        throw DataFormatError("Wrong relation operator");
deba@2316
   254
      }
deba@2316
   255
      switch (x) {
deba@2316
   256
      case '<': op = LE; 
deba@2316
   257
        break;
deba@2316
   258
      case '=': op = EQ; 
deba@2316
   259
        break;
deba@2316
   260
      case '>': op = GE; 
deba@2316
   261
        break;
deba@2316
   262
      }
deba@2316
   263
      return is;
deba@2316
   264
    }
deba@2316
   265
deba@2316
   266
    static bool relationFirstChar(char c) {
deba@2316
   267
      return c == '<' || c == '=' || c == '>';
deba@2316
   268
    }
deba@2316
   269
deba@2316
   270
    static bool varFirstChar(char c) {
deba@2316
   271
      return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
deba@2316
   272
    }
deba@2316
   273
deba@2316
   274
    static bool numFirstChar(char c) {
deba@2316
   275
      return (c >= '0' && c <= '9') || c == '.';
deba@2316
   276
    }
deba@2316
   277
deba@2316
   278
    static bool varChar(char c) {
deba@2316
   279
      return (c >= '0' && c <= '9') || 
deba@2316
   280
        (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
deba@2316
   281
    }
deba@2316
   282
deba@2316
   283
deba@2316
   284
    void addConstraint(const LpSolverBase::Constr& constr) {
deba@2316
   285
      if (constr.expr().size() != 1) {
deba@2316
   286
        lp.addRow(constr);
deba@2316
   287
      } else {
deba@2316
   288
        Lp::Expr e = constr.expr();
deba@2316
   289
        LpSolverBase::Col col = e.begin()->first;
deba@2316
   290
        double coeff = e.begin()->second;
deba@2316
   291
        double lb = LpSolverBase::NaN;
deba@2316
   292
        double ub = LpSolverBase::NaN;
deba@2316
   293
        if (coeff > 0) {
deba@2316
   294
          if (constr.upperBounded()) {
deba@2316
   295
            lb = (constr.lowerBound() - e.constComp()) / coeff;
deba@2316
   296
          }
deba@2316
   297
          if (constr.lowerBounded()) {
deba@2316
   298
            ub = (constr.upperBound() - e.constComp()) / coeff;
deba@2316
   299
          }
deba@2316
   300
        } else if (coeff < 0) {
deba@2316
   301
          if (constr.upperBounded()) {
deba@2316
   302
            lb = (constr.upperBound() - e.constComp()) / coeff;
deba@2316
   303
          }
deba@2316
   304
          if (constr.lowerBounded()) {
deba@2316
   305
            ub = (constr.lowerBound() - e.constComp()) / coeff;
deba@2316
   306
          }
deba@2316
   307
        } else {
deba@2316
   308
          lb = -LpSolverBase::INF;
deba@2316
   309
          ub = LpSolverBase::INF;
deba@2316
   310
        }
deba@2316
   311
        lp.colLowerBound(col, lb);
deba@2316
   312
        lp.colUpperBound(col, ub);
deba@2316
   313
      }
deba@2316
   314
    }
deba@2316
   315
    
deba@2316
   316
  protected:
deba@2316
   317
deba@2316
   318
    /// \brief Reader function of the section.
deba@2316
   319
    ///
deba@2316
   320
    /// It reads the content of the section.
deba@2316
   321
    virtual void read(std::istream& is) {
deba@2316
   322
      std::string line;
deba@2316
   323
      while (getline(is, line)) {
deba@2316
   324
        std::istringstream ls(line);
deba@2316
   325
        std::string sense;
deba@2316
   326
        ls >> sense;
deba@2316
   327
        if (sense == "min" || sense == "max") {
deba@2316
   328
          LpSolverBase::Expr expr;
deba@2316
   329
          ls >> std::ws;
deba@2316
   330
          readExpression(ls, expr);
deba@2316
   331
          lp.setObj(expr);
deba@2316
   332
          if (sense == "min") {
deba@2316
   333
            lp.min();
deba@2316
   334
          } else {
deba@2316
   335
            lp.max();
deba@2316
   336
          }
deba@2316
   337
        } else {
deba@2316
   338
          ls.str(line);
deba@2316
   339
          LpSolverBase::Constr constr;
deba@2316
   340
          ls >> std::ws;
deba@2316
   341
          readConstraint(ls, constr);
deba@2316
   342
          addConstraint(constr);
deba@2316
   343
        }        
deba@2316
   344
      }
deba@2316
   345
    }
deba@2316
   346
      
deba@2316
   347
    virtual void missing() {
deba@2316
   348
      ErrorMessage msg;
deba@2316
   349
      msg << "Lp section not found in file: @lp " << name;
deba@2316
   350
      throw IoParameterError(msg.message());
deba@2316
   351
    }
deba@2316
   352
deba@2316
   353
  private:
deba@2316
   354
deba@2316
   355
    typedef std::map<std::string, LpSolverBase::Col> ColMap;
deba@2316
   356
      
deba@2316
   357
    LpSolverBase& lp;
deba@2316
   358
    std::string name;
deba@2316
   359
    ColMap cols;
deba@2316
   360
  };
deba@2316
   361
deba@2363
   362
deba@2363
   363
//   class LpWriter : public LemonWriter::SectionWriter {
deba@2363
   364
//     typedef LemonWriter::SectionWriter Parent;
deba@2363
   365
//   public:
deba@2363
   366
deba@2363
   367
deba@2363
   368
//     /// \brief Constructor.
deba@2363
   369
//     ///
deba@2363
   370
//     /// Constructor for LpWriter. It creates the LpWriter and attach
deba@2363
   371
//     /// it into the given LemonWriter. The lp writer will add
deba@2363
   372
//     /// variables, constraints and objective function to the
deba@2363
   373
//     /// given lp solver.
deba@2363
   374
//     LpWriter(LemonWriter& _writer, LpSolverBase& _lp, 
deba@2363
   375
//              const std::string& _name = std::string())
deba@2363
   376
//       : Parent(_writer), lp(_lp), name(_name) {} 
deba@2363
   377
deba@2363
   378
deba@2363
   379
//     /// \brief Destructor.
deba@2363
   380
//     ///
deba@2363
   381
//     /// Destructor for NodeSetWriter.
deba@2363
   382
//     virtual ~LpWriter() {}
deba@2363
   383
deba@2363
   384
//   private:
deba@2363
   385
//     LpWriter(const LpWriter&);
deba@2363
   386
//     void operator=(const LpWriter&);
deba@2363
   387
  
deba@2363
   388
//   protected:
deba@2363
   389
deba@2363
   390
//     /// \brief Gives back true when the SectionWriter can process 
deba@2363
   391
//     /// the section with the given header line.
deba@2363
   392
//     ///
deba@2363
   393
//     /// It gives back the header line of the \c \@lp section.
deba@2363
   394
//     virtual std::string header() {
deba@2363
   395
//       std::ostringstream ls(line);
deba@2363
   396
//       ls << "@lp " << name;
deba@2363
   397
//       return ls.str();
deba@2363
   398
//     }
deba@2363
   399
deba@2363
   400
//   private:
deba@2363
   401
deba@2363
   402
//     std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) {
deba@2363
   403
//       char x;
deba@2363
   404
deba@2363
   405
      
deba@2363
   406
//       LpSolverBase::Expr e1, e2;
deba@2363
   407
//       Relation op1;
deba@2363
   408
//       is >> std::ws;
deba@2363
   409
//       writexpression(is, e1);
deba@2363
   410
//       is >> std::ws;
deba@2363
   411
//       writeRelation(is, op1);
deba@2363
   412
//       is >> std::ws;
deba@2363
   413
//       writexpression(is, e2);
deba@2363
   414
//       if (!is.get(x)) {
deba@2363
   415
//         if (op1 == LE) {
deba@2363
   416
//           c = e1 <= e2;
deba@2363
   417
//         } else if (op1 == GE) {
deba@2363
   418
//           c = e1 >= e2;
deba@2363
   419
//         } else {
deba@2363
   420
//           c = e1 == e2;
deba@2363
   421
//         }
deba@2363
   422
//       } else {
deba@2363
   423
//         is.putback(x);
deba@2363
   424
//         LpSolverBase::Expr e3;
deba@2363
   425
//         Relation op2;
deba@2363
   426
//         writeRelation(is, op2);
deba@2363
   427
//         is >> std::ws;
deba@2363
   428
//         writexpression(is, e3);
deba@2363
   429
//         if (!e1.empty() || !e3.empty()) {
deba@2363
   430
//           throw DataFormatError("Wrong range format");
deba@2363
   431
//         }
deba@2363
   432
//         if (op2 != op1 || op1 == EQ) {
deba@2363
   433
//           throw DataFormatError("Wrong range format");
deba@2363
   434
//         }
deba@2363
   435
//         if (op1 == LE) {
deba@2363
   436
//           c = e1.constComp() <= e2 <= e3.constComp();
deba@2363
   437
//         } else {
deba@2363
   438
//           c = e1.constComp() >= e2 >= e3.constComp();
deba@2363
   439
//         }
deba@2363
   440
//       }
deba@2363
   441
//     }
deba@2363
   442
deba@2363
   443
//     std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) {
deba@2363
   444
//       LpSolverBase::Col c;
deba@2363
   445
//       double d;
deba@2363
   446
//       char x;
deba@2363
   447
//       writelement(is, c, d);
deba@2363
   448
//       if (c != INVALID) {
deba@2363
   449
//         e += d * c;
deba@2363
   450
//       } else {
deba@2363
   451
//         e += d;
deba@2363
   452
//       }
deba@2363
   453
//       is >> std::ws;
deba@2363
   454
//       while (is.get(x) && (x == '+' || x == '-')) {
deba@2363
   455
//         is >> std::ws;
deba@2363
   456
//         writelement(is, c, d);
deba@2363
   457
//         if (c != INVALID) {
deba@2363
   458
//           e += (x == '+' ? d : -d) * c;
deba@2363
   459
//         } else {
deba@2363
   460
//           e += (x == '+' ? d : -d);
deba@2363
   461
//         }
deba@2363
   462
//         is >> std::ws;
deba@2363
   463
//       }
deba@2363
   464
//       if (!is) {
deba@2363
   465
//         is.clear();
deba@2363
   466
//       } else {
deba@2363
   467
//         is.putback(x);
deba@2363
   468
//       }
deba@2363
   469
//       return is;
deba@2363
   470
//     }
deba@2363
   471
deba@2363
   472
//     std::ostream& writelement(std::ostream& is, 
deba@2363
   473
//                               LpSolverBase::Col& c, double& d) { 
deba@2363
   474
//       d = 1.0;
deba@2363
   475
//       c = INVALID;
deba@2363
   476
//       char x, y;
deba@2363
   477
//       if (!is.get(x)) throw DataFormatError("Cannot find lp element");
deba@2363
   478
//       if (x == '+' || x == '-') {
deba@2363
   479
//         is >> std::ws;
deba@2363
   480
//         d *= x == '-' ? -1 : 1;
deba@2363
   481
//         while (is.get(x) && (x == '+' || x == '-')) {
deba@2363
   482
//           d *= x == '-' ? -1 : 1;
deba@2363
   483
//           is >> std::ws;
deba@2363
   484
//         }
deba@2363
   485
//         if (!is) throw DataFormatError("Cannot find lp element");
deba@2363
   486
//       }
deba@2363
   487
//       if (numFirstChar(x)) {
deba@2363
   488
//         is.putback(x);
deba@2363
   489
//         double e;
deba@2363
   490
//         writeNum(is, e);
deba@2363
   491
//         d *= e;
deba@2363
   492
//       } else if (varFirstChar(x)) {
deba@2363
   493
//         is.putback(x);
deba@2363
   494
//         LpSolverBase::Col f;
deba@2363
   495
//         writeCol(is, f);
deba@2363
   496
//         c = f;
deba@2363
   497
//       } else {
deba@2363
   498
//         throw DataFormatError("Invalid expression format");          
deba@2363
   499
//       }
deba@2363
   500
//       is >> std::ws;
deba@2363
   501
//       while (is.get(y) && (y == '*' || y == '/')) {
deba@2363
   502
//         is >> std::ws;
deba@2363
   503
//         if (!is.get(x)) throw DataFormatError("Cannot find lp element");
deba@2363
   504
//         if (x == '+' || x == '-') {
deba@2363
   505
//           is >> std::ws;
deba@2363
   506
//           d *= x == '-' ? -1 : 1;
deba@2363
   507
//           while (is.get(x) && (x == '+' || x == '-')) {
deba@2363
   508
//             d *= x == '-' ? -1 : 1;
deba@2363
   509
//             is >> std::ws;
deba@2363
   510
//           }
deba@2363
   511
//           if (!is) throw DataFormatError("Cannot find lp element");
deba@2363
   512
//         }
deba@2363
   513
//         if (numFirstChar(x)) {
deba@2363
   514
//           is.putback(x);
deba@2363
   515
//           double e;
deba@2363
   516
//           writeNum(is, e);
deba@2363
   517
//           if (y == '*') {
deba@2363
   518
//             d *= e;
deba@2363
   519
//           } else {
deba@2363
   520
//             d /= e;
deba@2363
   521
//           }
deba@2363
   522
//         } else if (varFirstChar(x)) {
deba@2363
   523
//           is.putback(x);
deba@2363
   524
//           LpSolverBase::Col f;
deba@2363
   525
//           writeCol(is, f);
deba@2363
   526
//           if (y == '*') {
deba@2363
   527
//             if (c == INVALID) {
deba@2363
   528
//               c = f;
deba@2363
   529
//             } else {
deba@2363
   530
//               throw DataFormatError("Quadratic element in expression");
deba@2363
   531
//             }
deba@2363
   532
//           } else {
deba@2363
   533
//             throw DataFormatError("Division by variable");
deba@2363
   534
//           }
deba@2363
   535
//         } else {
deba@2363
   536
//           throw DataFormatError("Invalid expression format");          
deba@2363
   537
//         }
deba@2363
   538
//         is >> std::ws;
deba@2363
   539
//       }
deba@2363
   540
//       if (!is) {
deba@2363
   541
//         is.clear();
deba@2363
   542
//       } else {
deba@2363
   543
//         is.putback(y);
deba@2363
   544
//       }
deba@2363
   545
//       return is;
deba@2363
   546
//     }
deba@2363
   547
deba@2363
   548
//     std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) {
deba@2363
   549
//       char x;
deba@2363
   550
//       std::string var;
deba@2363
   551
//       while (is.get(x) && varChar(x)) {
deba@2363
   552
//         var += x;
deba@2363
   553
//       }
deba@2363
   554
//       if (!is) {
deba@2363
   555
//         is.clear();
deba@2363
   556
//       } else {
deba@2363
   557
//         is.putback(x);
deba@2363
   558
//       }
deba@2363
   559
//       ColMap::const_iterator it = cols.find(var);
deba@2363
   560
//       if (cols.find(var) != cols.end()) {
deba@2363
   561
//         c = it->second;
deba@2363
   562
//       } else {
deba@2363
   563
//         c = lp.addCol();
deba@2363
   564
//         cols.insert(std::make_pair(var, c));
deba@2363
   565
//         lp.colName(c, var);
deba@2363
   566
//       }
deba@2363
   567
//       return is;
deba@2363
   568
//     }
deba@2363
   569
deba@2363
   570
//     std::ostream& writeNum(std::ostream& is, double& d) {
deba@2363
   571
//       is >> d;
deba@2363
   572
//       if (!is) throw DataFormatError("Wrong number format");
deba@2363
   573
//       return is;
deba@2363
   574
//     }
deba@2363
   575
deba@2363
   576
//     std::ostream& writeRelation(std::ostream& is, Relation& op) {
deba@2363
   577
//       char x, y;
deba@2363
   578
//       if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) {
deba@2363
   579
//         throw DataFormatError("Wrong relation operator");
deba@2363
   580
//       }
deba@2363
   581
//       if (!is.get(y) || y != '=') {
deba@2363
   582
//         throw DataFormatError("Wrong relation operator");
deba@2363
   583
//       }
deba@2363
   584
//       switch (x) {
deba@2363
   585
//       case '<': op = LE; 
deba@2363
   586
//         break;
deba@2363
   587
//       case '=': op = EQ; 
deba@2363
   588
//         break;
deba@2363
   589
//       case '>': op = GE; 
deba@2363
   590
//         break;
deba@2363
   591
//       }
deba@2363
   592
//       return is;
deba@2363
   593
//     }
deba@2363
   594
deba@2363
   595
//     static bool relationFirstChar(char c) {
deba@2363
   596
//       return c == '<' || c == '=' || c == '>';
deba@2363
   597
//     }
deba@2363
   598
deba@2363
   599
//     static bool varFirstChar(char c) {
deba@2363
   600
//       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
deba@2363
   601
//     }
deba@2363
   602
deba@2363
   603
//     static bool numFirstChar(char c) {
deba@2363
   604
//       return (c >= '0' && c <= '9') || c == '.';
deba@2363
   605
//     }
deba@2363
   606
deba@2363
   607
//     static bool varChar(char c) {
deba@2363
   608
//       return (c >= '0' && c <= '9') || 
deba@2363
   609
//         (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
deba@2363
   610
//     }
deba@2363
   611
deba@2363
   612
deba@2363
   613
//     void addConstraint(const LpSolverBase::Constr& constr) {
deba@2363
   614
//       if (constr.expr().size() != 1) {
deba@2363
   615
//         lp.addRow(constr);
deba@2363
   616
//       } else {
deba@2363
   617
//         Lp::Expr e = constr.expr();
deba@2363
   618
//         LpSolverBase::Col col = e.begin()->first;
deba@2363
   619
//         double coeff = e.begin()->second;
deba@2363
   620
//         double lb = LpSolverBase::NaN;
deba@2363
   621
//         double ub = LpSolverBase::NaN;
deba@2363
   622
//         if (coeff > 0) {
deba@2363
   623
//           if (constr.upperBounded()) {
deba@2363
   624
//             lb = (constr.lowerBound() - e.constComp()) / coeff;
deba@2363
   625
//           }
deba@2363
   626
//           if (constr.lowerBounded()) {
deba@2363
   627
//             ub = (constr.upperBound() - e.constComp()) / coeff;
deba@2363
   628
//           }
deba@2363
   629
//         } else if (coeff < 0) {
deba@2363
   630
//           if (constr.upperBounded()) {
deba@2363
   631
//             lb = (constr.upperBound() - e.constComp()) / coeff;
deba@2363
   632
//           }
deba@2363
   633
//           if (constr.lowerBounded()) {
deba@2363
   634
//             ub = (constr.lowerBound() - e.constComp()) / coeff;
deba@2363
   635
//           }
deba@2363
   636
//         } else {
deba@2363
   637
//           lb = -LpSolverBase::INF;
deba@2363
   638
//           ub = LpSolverBase::INF;
deba@2363
   639
//         }
deba@2363
   640
//         lp.colLowerBound(col, lb);
deba@2363
   641
//         lp.colUpperBound(col, ub);
deba@2363
   642
//       }
deba@2363
   643
//     }
deba@2363
   644
    
deba@2363
   645
//   protected:
deba@2363
   646
deba@2363
   647
//     /// \brief Writer function of the section.
deba@2363
   648
//     ///
deba@2363
   649
//     /// It writes the content of the section.
deba@2363
   650
//     virtual void write(std::ostream& is) {
deba@2363
   651
//       std::string line;
deba@2363
   652
//       std::map<std::string, LpSolverBase::Col> vars;
deba@2363
   653
//       while (getline(is, line)) {
deba@2363
   654
//         std::istringstream ls(line);
deba@2363
   655
//         std::string sense;
deba@2363
   656
//         ls >> sense;
deba@2363
   657
//         if (sense == "min" || sense == "max") {
deba@2363
   658
//           LpSolverBase::Expr expr;
deba@2363
   659
//           ls >> std::ws;
deba@2363
   660
//           writeExpression(ls, expr);
deba@2363
   661
//           lp.setObj(expr);
deba@2363
   662
//           if (sense == "min") {
deba@2363
   663
//             lp.min();
deba@2363
   664
//           } else {
deba@2363
   665
//             lp.max();
deba@2363
   666
//           }
deba@2363
   667
//         } else {
deba@2363
   668
//           ls.str(line);
deba@2363
   669
//           LpSolverBase::Constr constr;
deba@2363
   670
//           ls >> std::ws;
deba@2363
   671
//           writeConstraint(ls, constr);
deba@2363
   672
//           addConstraint(constr);
deba@2363
   673
//         }        
deba@2363
   674
//       }
deba@2363
   675
//     }
deba@2363
   676
      
deba@2363
   677
//     virtual void missing() {
deba@2363
   678
//       ErrorMessage msg;
deba@2363
   679
//       msg << "Lp section not found in file: @lp " << name;
deba@2363
   680
//       throw IoParameterError(msg.message());
deba@2363
   681
//     }
deba@2363
   682
deba@2363
   683
//   private:
deba@2363
   684
deba@2363
   685
//     typedef std::map<std::string, LpSolverBase::Col> ColMap;
deba@2363
   686
      
deba@2363
   687
//     LpSolverBase& lp;
deba@2363
   688
//     std::string name;
deba@2363
   689
//     ColMap cols;
deba@2363
   690
//   };
deba@2363
   691
deba@2316
   692
}
deba@2316
   693
deba@2316
   694
#endif