COIN-OR::LEMON - Graph Library

Changeset 2363:2aabce558574 in lemon-0.x for lemon


Ignore:
Timestamp:
02/15/07 15:22:08 (17 years ago)
Author:
Balazs Dezso
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@3174
Message:

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
Location:
lemon
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • lemon/Makefile.am

    r2360 r2363  
    1616        lemon/random.cc
    1717
    18 lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CFLAGS)
    19 lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_CFLAGS)
     18lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS)
     19lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS)
    2020
    2121if HAVE_GLPK
     
    124124        lemon/bits/item_reader.h \
    125125        lemon/bits/item_writer.h \
     126        lemon/bits/lp_id.h \
    126127        lemon/bits/map_extender.h \
    127128        lemon/bits/mingw32_time.h \
  • lemon/lp_base.h

    r2345 r2363  
    2828#include<cmath>
    2929
    30 #include<lemon/bits/utility.h>
    3130#include<lemon/error.h>
    3231#include<lemon/bits/invalid.h>
     32#include<lemon/bits/utility.h>
     33#include<lemon/bits/lp_id.h>
    3334
    3435///\file
     
    3738namespace lemon {
    3839
    39 
    40   ///Internal data structure to convert floating id's to fix one's
    41    
    42   ///\todo This might be implemented to be also usable in other places.
    43   class _FixId
    44   {
    45   protected:
    46     int _first_index;
    47     int first_free;
    48   public:
    49     std::vector<int> index;
    50     std::vector<int> cross;
    51     _FixId() : _first_index(-1), first_free(-1) {};
    52     ///Convert a floating id to a fix one
    53 
    54     ///\param n is a floating id
    55     ///\return the corresponding fix id
    56     int fixId(int n) const {return cross[n];}
    57     ///Convert a fix id to a floating one
    58 
    59     ///\param n is a fix id
    60     ///\return the corresponding floating id
    61     int floatingId(int n) const { return index[n];}
    62     ///Add a new floating id.
    63 
    64     ///\param n is a floating id
    65     ///\return the fix id of the new value
    66     ///\todo Multiple additions should also be handled.
    67     int insert(int n)
    68     {
    69       if(cross.empty()) _first_index=n;
    70       if(n>=int(cross.size())) {
    71         cross.resize(n+1);
    72         if(first_free==-1) {
    73           cross[n]=index.size();
    74           index.push_back(n);
    75         }
    76         else {
    77           cross[n]=first_free;
    78           int next=index[first_free];
    79           index[first_free]=n;
    80           first_free=next;
    81         }
    82         return cross[n];
    83       }
    84       else {
    85         ///\todo Create an own exception type.
    86         throw LogicError(); //floatingId-s must form a continuous range;
    87       }
    88     }
    89     ///Remove a fix id.
    90 
    91     ///\param n is a fix id
    92     ///
    93     void erase(int n)
    94     {
    95       int fl=index[n];
    96       index[n]=first_free;
    97       first_free=n;
    98       for(int i=fl+1;i<int(cross.size());++i) {
    99         cross[i-1]=cross[i];
    100         index[cross[i]]--;
    101       }
    102       cross.pop_back();
    103     }
    104     ///An upper bound on the largest fix id.
    105 
    106     ///\todo Do we need this?
    107     ///
    108     std::size_t maxFixId() { return cross.size()-1; }
    109  
    110     ///Returns the first (smallest) inserted index
    111 
    112     ///Returns the first (smallest) inserted index
    113     ///or -1 if no index has been inserted before.
    114     int firstIndex() {return _first_index;}
    115   };
    116 
    11740  ///Common base class for LP solvers
    11841 
     
    12245
    12346  protected:
    124     _FixId rows;
    125     _FixId cols;
    126 
     47
     48    _lp_bits::LpId rows;
     49    _lp_bits::LpId cols;
     50   
    12751  public:
    12852
     
    216140      ColIt(LpSolverBase &lp) : _lp(&lp)
    217141      {
    218         id = _lp->cols.cross.empty()?-1:
    219           _lp->cols.fixId(_lp->cols.firstIndex());
     142        _lp->cols.firstFix(id);
    220143      }
    221144      ColIt(const Invalid&) : Col(INVALID) {}
    222145      ColIt &operator++()
    223146      {
    224         int fid = _lp->cols.floatingId(id)+1;
    225         id = unsigned(fid)<_lp->cols.cross.size() ? _lp->cols.fixId(fid) : -1;
     147        _lp->cols.nextFix(id);
    226148        return *this;
    227149      }
     
    747669    virtual void _setColUpperBound(int i, Value value) = 0;
    748670    virtual Value _getColUpperBound(int i) = 0;
    749 //     virtual void _setRowLowerBound(int i, Value value) = 0;
    750 //     virtual void _setRowUpperBound(int i, Value value) = 0;
    751671    virtual void _setRowBounds(int i, Value lower, Value upper) = 0;
    752672    virtual void _getRowBounds(int i, Value &lower, Value &upper)=0;
     
    796716
    797717    ///Add a new empty column (i.e a new variable) to the LP
    798     Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
     718    Col addCol() { Col c; _addCol(); c.id = cols.addId(); return c;}
    799719
    800720    ///\brief Adds several new columns
     
    888808    ///This function adds a new empty row (i.e a new constraint) to the LP.
    889809    ///\return The created row
    890     Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
     810    Row addRow() { Row r; _addRow(); r.id = rows.addId(); return r;}
    891811
    892812    ///\brief Add several new rows
     
    966886      _setRowCoeffs(_lpId(r), LpRowIterator(e.begin(), *this),
    967887                    LpRowIterator(e.end(), *this));
    968 //       _setRowLowerBound(_lpId(r),l-e.constComp());
    969 //       _setRowUpperBound(_lpId(r),u-e.constComp());
    970888       _setRowBounds(_lpId(r),l-e.constComp(),u-e.constComp());
    971889    }
     
    1009927    void eraseCol(Col c) {
    1010928      _eraseCol(_lpId(c));
    1011       cols.erase(c.id);
     929      cols.eraseId(c.id);
    1012930    }
    1013931    ///Erase a  row (i.e a constraint) from the LP
     
    1017935    void eraseRow(Row r) {
    1018936      _eraseRow(_lpId(r));
    1019       rows.erase(r.id);
     937      rows.eraseId(r.id);
    1020938    }
    1021939
     
    12171135#endif
    12181136   
    1219 //     /// Set the lower bound of a row (i.e a constraint)
    1220 
    1221 //     /// The lower bound of a linear expression (row) has to be given by an
    1222 //     /// extended number of type Value, i.e. a finite number of type
    1223 //     /// Value or -\ref INF.
    1224 //     void rowLowerBound(Row r, Value value) {
    1225 //       _setRowLowerBound(_lpId(r),value);
    1226 //     };
    1227 //     /// Set the upper bound of a row (i.e a constraint)
    1228 
    1229 //     /// The upper bound of a linear expression (row) has to be given by an
    1230 //     /// extended number of type Value, i.e. a finite number of type
    1231 //     /// Value or \ref INF.
    1232 //     void rowUpperBound(Row r, Value value) {
    1233 //       _setRowUpperBound(_lpId(r),value);
    1234 //     };
    12351137
    12361138    /// Set the lower and the upper bounds of a row (i.e a constraint)
    12371139
    1238     /// The lower and the upper bound of
    1239     /// a constraint (row) have to be given by an
    1240     /// extended number of type Value, i.e. a finite number of type
    1241     /// Value, -\ref INF or \ref INF. There is no separate function for the
    1242     /// lower and the upper bound because that would have been hard to implement
    1243     /// for CPLEX.
     1140    /// The lower and the upper bound of a constraint (row) have to be
     1141    /// given by an extended number of type Value, i.e. a finite
     1142    /// number of type Value, -\ref INF or \ref INF. There is no
     1143    /// separate function for the lower and the upper bound because
     1144    /// that would have been hard to implement for CPLEX.
    12441145    void rowBounds(Row c, Value lower, Value upper) {
    12451146      _setRowBounds(_lpId(c),lower, upper);
  • lemon/lp_cplex.cc

    r2361 r2363  
    2525 
    2626  LpCplex::LpCplex() : LpSolverBase() {
    27 
    2827    //    env = CPXopenCPLEXdevelop(&status);     
    2928    env = CPXopenCPLEX(&status);     
  • lemon/lp_glpk.cc

    r2349 r2363  
    2525
    2626
    27   LpGlpk::LpGlpk() : Parent(),
    28                      lp(lpx_create_prob()) {
    29     ///\todo constrol function for this:
     27  LpGlpk::LpGlpk() : Parent() {
     28    rows = _lp_bits::LpId(1);
     29    cols = _lp_bits::LpId(1);
     30    lp = lpx_create_prob();
     31    ///\todo control function for this:
    3032    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    3133    messageLevel(0);
    3234  }
    3335 
    34   LpGlpk::LpGlpk(const LpGlpk &glp) : Parent(glp),
    35                                       lp(lpx_create_prob()) {
    36     ///\todo constrol function for this:
     36  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
     37    rows = _lp_bits::LpId(1);
     38    cols = _lp_bits::LpId(1);
     39    lp = lpx_create_prob();
     40    ///\todo control function for this:
    3741    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
    3842    messageLevel(0);
     
    350354  }
    351355 
    352 //   void LpGlpk::_setRowLowerBound(int i, Value lo)
    353 //   {
    354 //     if (lo==INF) {
    355 //       //FIXME error
    356 //     }
    357 //     int b=lpx_get_row_type(lp, i);
    358 //     double up=lpx_get_row_ub(lp, i);
    359 //     if (lo==-INF) {
    360 //       switch (b) {
    361 //       case LPX_FR:
    362 //       case LPX_LO:
    363 //      lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
    364 //      break;
    365 //       case LPX_UP:
    366 //      break;
    367 //       case LPX_DB:
    368 //       case LPX_FX:
    369 //      lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
    370 //      break;
    371 //       default: ;
    372 //      //FIXME error
    373 //       }
    374 //     } else {
    375 //       switch (b) {
    376 //       case LPX_FR:
    377 //       case LPX_LO:
    378 //      lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
    379 //      break;
    380 //       case LPX_UP:     
    381 //       case LPX_DB:
    382 //       case LPX_FX:
    383 //      if (lo==up)
    384 //        lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
    385 //      else
    386 //        lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
    387 //      break;
    388 //       default: ;
    389 //      //FIXME error
    390 //       }
    391 //     }
    392 //   }
    393  
    394 //   void LpGlpk::_setRowUpperBound(int i, Value up)
    395 //   {
    396 //     if (up==-INF) {
    397 //       //FIXME error
    398 //     }
    399 //     int b=lpx_get_row_type(lp, i);
    400 //     double lo=lpx_get_row_lb(lp, i);
    401 //     if (up==INF) {
    402 //       switch (b) {
    403 //       case LPX_FR:
    404 //       case LPX_LO:
    405 //      break;
    406 //       case LPX_UP:
    407 //      lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
    408 //      break;
    409 //       case LPX_DB:
    410 //       case LPX_FX:
    411 //      lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
    412 //      break;
    413 //       default: ;
    414 //      //FIXME error
    415 //       }
    416 //     } else {
    417 //       switch (b) {
    418 //       case LPX_FR:
    419 //      lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
    420 //      break;
    421 //       case LPX_UP:
    422 //      lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
    423 //      break;
    424 //       case LPX_LO:
    425 //       case LPX_DB:
    426 //       case LPX_FX:
    427 //      if (lo==up)
    428 //        lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
    429 //      else
    430 //        lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
    431 //      break;
    432 //       default: ;
    433 //      //FIXME error
    434 //       }
    435 //     }
    436 //   }
    437 
    438356  void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
    439357  {
     
    509427    }
    510428  }
    511 //   void LpGlpk::_setObj(int length,
    512 //                     int  const * indices,
    513 //                     Value  const * values )
    514 //   {
    515 //     Value new_values[1+lpx_num_cols()];
    516 //     for (i=0;i<=lpx_num_cols();++i){
    517 //       new_values[i]=0;
    518 //     }
    519 //     for (i=1;i<=length;++i){
    520 //       new_values[indices[i]]=values[i];
    521 //     }
    522    
    523 //     for (i=0;i<=lpx_num_cols();++i){
    524 //       lpx_set_obj_coef(lp, i, new_values[i]);
    525 //     }
    526 //   }
    527429
    528430  LpGlpk::SolveExitStatus LpGlpk::_solve()
     
    531433    //lpx_write_cpxlp(lp,"naittvan.cpx");   
    532434
     435    lpx_std_basis(lp);
    533436    int i =  lpx_simplex(lp);
     437   
    534438    switch (i) {
    535439    case LPX_E_OK:
  • lemon/lp_skeleton.h

    r2328 r2363  
    3131   
    3232  protected:
     33
    3334    ///\e
    3435    virtual LpSolverBase &_newLp();
  • lemon/lp_soplex.cc

    r2313 r2363  
    2828 
    2929  LpSoplex::LpSoplex() : LpSolverBase() {
     30    rows.setIdHandler(relocateIdHandler);
     31    cols.setIdHandler(relocateIdHandler);
    3032    soplex = new soplex::SoPlex;
     33    solved = false;
    3134  }
    3235 
     
    4851  int LpSoplex::_addCol() {
    4952    soplex::LPCol col;
     53    col.setLower(-soplex::infinity);
     54    col.setUpper(soplex::infinity);
    5055    soplex->addCol(col);
    5156
    5257    colNames.push_back(std::string());
    53     primal.push_back(0.0);
     58    primal_value.push_back(0.0);
     59    solved = false;
    5460
    5561    return soplex->nCols() - 1;
     
    5864  int LpSoplex::_addRow() {
    5965    soplex::LPRow row;
     66    row.setLhs(-soplex::infinity);
     67    row.setRhs(soplex::infinity);
    6068    soplex->addRow(row);
    6169
    62     dual.push_back(0.0);
     70    dual_value.push_back(0.0);
     71    solved = false;
    6372
    6473    return soplex->nRows() - 1;
     
    6877  void LpSoplex::_eraseCol(int i) {
    6978    soplex->removeCol(i);
    70     primal[i] = primal.back();
    71     primal.pop_back();
     79    colNames[i] = colNames.back();
     80    colNames.pop_back();
     81    primal_value[i] = primal_value.back();
     82    primal_value.pop_back();
     83    solved = false;
    7284  }
    7385 
    7486  void LpSoplex::_eraseRow(int i) {
    7587    soplex->removeRow(i);
    76     dual[i] = dual.back();
    77     dual.pop_back();
     88    dual_value[i] = dual_value.back();
     89    dual_value.pop_back();
     90    solved = false;
    7891  }
    7992 
     
    94107      soplex->changeElement(i, it->first, it->second);
    95108    }
     109    solved = false;
    96110  }
    97111 
     
    103117      soplex->changeElement(it->first, j, it->second);
    104118    }
    105   }
    106  
    107   void LpSoplex::_setCoeff(int row, int col, Value value) {
    108     soplex->changeElement(row, col, value);
     119    solved = false;
     120  }
     121 
     122  void LpSoplex::_setCoeff(int i, int j, Value value) {
     123    soplex->changeElement(i, j, value);
     124    solved = false;
     125  }
     126
     127  LpSoplex::Value LpSoplex::_getCoeff(int i, int j) {
     128    return soplex->rowVector(i)[j];
    109129  }
    110130
    111131  void LpSoplex::_setColLowerBound(int i, Value value) {
    112     soplex->changeLower(i, value);
    113   }
    114  
     132    soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
     133    solved = false;
     134  }
     135 
     136  LpSoplex::Value LpSoplex::_getColLowerBound(int i) {
     137    double value = soplex->lower(i);
     138    return value != -soplex::infinity ? value : -INF;
     139  }
     140
    115141  void LpSoplex::_setColUpperBound(int i, Value value) {
    116     soplex->changeUpper(i, value);
     142    soplex->changeUpper(i, value != INF ? value : soplex::infinity);
     143    solved = false;
     144  }
     145
     146  LpSoplex::Value LpSoplex::_getColUpperBound(int i) {
     147    double value = soplex->upper(i);
     148    return value != soplex::infinity ? value : INF;
    117149  }
    118150
    119151  void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
    120     soplex->changeRange(i, lb, ub);
     152    soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
     153                        ub != INF ? ub : soplex::infinity);
     154    solved = false;
     155  }
     156  void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) {
     157    lower = soplex->lhs(i);
     158    if (lower == -soplex::infinity) lower = -INF;
     159    upper = soplex->rhs(i);
     160    if (upper == -soplex::infinity) upper = INF;
    121161  }
    122162
    123163  void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
    124164    soplex->changeObj(i, obj_coef);
     165    solved = false;
     166  }
     167
     168  LpSoplex::Value LpSoplex::_getObjCoeff(int i) {
     169    return soplex->obj(i);
    125170  }
    126171
     
    129174      soplex->changeObj(i, 0.0);
    130175    }
     176    solved = false;
    131177  }
    132178
     
    134180    soplex::SPxSolver::Status status = soplex->solve();
    135181
    136     soplex::Vector pv(primal.size(), &primal[0]);
     182    soplex::Vector pv(primal_value.size(), &primal_value[0]);
    137183    soplex->getPrimal(pv);
    138184
    139     soplex::Vector dv(dual.size(), &dual[0]);
     185    soplex::Vector dv(dual_value.size(), &dual_value[0]);
    140186    soplex->getDual(dv);
    141187
     
    144190    case soplex::SPxSolver::INFEASIBLE:
    145191    case soplex::SPxSolver::UNBOUNDED:
     192      solved = true;
    146193      return SOLVED;
    147194    default:
     
    151198
    152199  LpSoplex::Value LpSoplex::_getPrimal(int i) {
    153     return primal[i];
     200    return primal_value[i];
    154201  }
    155202
    156203  LpSoplex::Value LpSoplex::_getDual(int i) {
    157     return dual[i];
     204    return dual_value[i];
    158205  }
    159206 
     
    167214
    168215  LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() {
     216    if (!solved) return UNDEFINED;
    169217    switch (soplex->status()) {
    170218    case soplex::SPxSolver::OPTIMAL:
     
    180228
    181229  LpSoplex::SolutionStatus LpSoplex::_getDualStatus() {
    182     switch (0) {
    183     case 0:
     230    if (!solved) return UNDEFINED;
     231    switch (soplex->status()) {
     232    case soplex::SPxSolver::OPTIMAL:
     233      return OPTIMAL;
     234    case soplex::SPxSolver::UNBOUNDED:
     235      return INFEASIBLE;
     236    default:
    184237      return UNDEFINED;
    185       return OPTIMAL;
    186       return INFEASIBLE;
    187       return UNDEFINED;
    188238    }
    189239  }
    190240
    191241  LpSoplex::ProblemTypes LpSoplex::_getProblemType() {
    192     switch (0) {
    193     case 0:
     242    if (!solved) return UNKNOWN;
     243    switch (soplex->status()) {
     244    case soplex::SPxSolver::OPTIMAL:
    194245      return PRIMAL_DUAL_FEASIBLE;
     246    case soplex::SPxSolver::UNBOUNDED:
    195247      return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
     248    default:
    196249      return UNKNOWN;
    197250    }
     
    200253  void LpSoplex::_setMax() {
    201254    soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
     255    solved = false;
    202256  }
    203257  void LpSoplex::_setMin() {
    204258    soplex->changeSense(soplex::SPxSolver::MINIMIZE);
    205   }
     259    solved = false;
     260  }
     261  bool LpSoplex::_isMax() {
     262    return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;
     263  }
     264
    206265 
    207266} //namespace lemon
  • lemon/lp_soplex.h

    r2313 r2363  
    4141  protected:
    4242
     43    _lp_bits::RelocateIdHandler relocateIdHandler;
     44
    4345    soplex::SoPlex* soplex;
     46    bool solved;
    4447
    4548    std::vector<std::string> colNames;
    4649
    47     std::vector<Value> primal;
    48     std::vector<Value> dual;
     50    std::vector<Value> primal_value;
     51    std::vector<Value> dual_value;
    4952
    5053
     
    6871    virtual void _eraseCol(int i);
    6972    virtual void _eraseRow(int i);
    70     virtual void _getColName(int col,       std::string & name);
     73    virtual void _getColName(int col, std::string & name);
    7174    virtual void _setColName(int col, const std::string & name);
    7275    virtual void _setRowCoeffs(int i, LpRowIterator b, LpRowIterator e);
    7376    virtual void _setColCoeffs(int i, LpColIterator b, LpColIterator e);
    7477    virtual void _setCoeff(int row, int col, Value value);
     78    virtual Value _getCoeff(int row, int col);
    7579    virtual void _setColLowerBound(int i, Value value);
     80    virtual Value _getColLowerBound(int i);
    7681    virtual void _setColUpperBound(int i, Value value);
     82    virtual Value _getColUpperBound(int i);
    7783    virtual void _setRowBounds(int i, Value lower, Value upper);
     84    virtual void _getRowBounds(int i, Value &lower, Value &upper);
    7885    virtual void _setObjCoeff(int i, Value obj_coef);
     86    virtual Value _getObjCoeff(int i);
    7987    virtual void _clearObj();
    8088   
     
    92100    virtual void _setMax();
    93101    virtual void _setMin();
     102    virtual bool _isMax();
    94103
    95104  };
  • lemon/lp_utils.h

    r2316 r2363  
    2323
    2424#include <lemon/lemon_reader.h>
     25#include <lemon/lemon_writer.h>
    2526
    2627namespace lemon {
     
    320321    virtual void read(std::istream& is) {
    321322      std::string line;
    322       std::map<std::string, LpSolverBase::Col> vars;
    323323      while (getline(is, line)) {
    324324        std::istringstream ls(line);
     
    360360  };
    361361
     362
     363//   class LpWriter : public LemonWriter::SectionWriter {
     364//     typedef LemonWriter::SectionWriter Parent;
     365//   public:
     366
     367
     368//     /// \brief Constructor.
     369//     ///
     370//     /// Constructor for LpWriter. It creates the LpWriter and attach
     371//     /// it into the given LemonWriter. The lp writer will add
     372//     /// variables, constraints and objective function to the
     373//     /// given lp solver.
     374//     LpWriter(LemonWriter& _writer, LpSolverBase& _lp,
     375//              const std::string& _name = std::string())
     376//       : Parent(_writer), lp(_lp), name(_name) {}
     377
     378
     379//     /// \brief Destructor.
     380//     ///
     381//     /// Destructor for NodeSetWriter.
     382//     virtual ~LpWriter() {}
     383
     384//   private:
     385//     LpWriter(const LpWriter&);
     386//     void operator=(const LpWriter&);
     387 
     388//   protected:
     389
     390//     /// \brief Gives back true when the SectionWriter can process
     391//     /// the section with the given header line.
     392//     ///
     393//     /// It gives back the header line of the \c \@lp section.
     394//     virtual std::string header() {
     395//       std::ostringstream ls(line);
     396//       ls << "@lp " << name;
     397//       return ls.str();
     398//     }
     399
     400//   private:
     401
     402//     std::ostream& writeConstraint(std::ostream& is, LpSolverBase::Constr& c) {
     403//       char x;
     404
     405     
     406//       LpSolverBase::Expr e1, e2;
     407//       Relation op1;
     408//       is >> std::ws;
     409//       writexpression(is, e1);
     410//       is >> std::ws;
     411//       writeRelation(is, op1);
     412//       is >> std::ws;
     413//       writexpression(is, e2);
     414//       if (!is.get(x)) {
     415//         if (op1 == LE) {
     416//           c = e1 <= e2;
     417//         } else if (op1 == GE) {
     418//           c = e1 >= e2;
     419//         } else {
     420//           c = e1 == e2;
     421//         }
     422//       } else {
     423//         is.putback(x);
     424//         LpSolverBase::Expr e3;
     425//         Relation op2;
     426//         writeRelation(is, op2);
     427//         is >> std::ws;
     428//         writexpression(is, e3);
     429//         if (!e1.empty() || !e3.empty()) {
     430//           throw DataFormatError("Wrong range format");
     431//         }
     432//         if (op2 != op1 || op1 == EQ) {
     433//           throw DataFormatError("Wrong range format");
     434//         }
     435//         if (op1 == LE) {
     436//           c = e1.constComp() <= e2 <= e3.constComp();
     437//         } else {
     438//           c = e1.constComp() >= e2 >= e3.constComp();
     439//         }
     440//       }
     441//     }
     442
     443//     std::ostream& writexpression(std::ostream& is, LpSolverBase::Expr& e) {
     444//       LpSolverBase::Col c;
     445//       double d;
     446//       char x;
     447//       writelement(is, c, d);
     448//       if (c != INVALID) {
     449//         e += d * c;
     450//       } else {
     451//         e += d;
     452//       }
     453//       is >> std::ws;
     454//       while (is.get(x) && (x == '+' || x == '-')) {
     455//         is >> std::ws;
     456//         writelement(is, c, d);
     457//         if (c != INVALID) {
     458//           e += (x == '+' ? d : -d) * c;
     459//         } else {
     460//           e += (x == '+' ? d : -d);
     461//         }
     462//         is >> std::ws;
     463//       }
     464//       if (!is) {
     465//         is.clear();
     466//       } else {
     467//         is.putback(x);
     468//       }
     469//       return is;
     470//     }
     471
     472//     std::ostream& writelement(std::ostream& is,
     473//                               LpSolverBase::Col& c, double& d) {
     474//       d = 1.0;
     475//       c = INVALID;
     476//       char x, y;
     477//       if (!is.get(x)) throw DataFormatError("Cannot find lp element");
     478//       if (x == '+' || x == '-') {
     479//         is >> std::ws;
     480//         d *= x == '-' ? -1 : 1;
     481//         while (is.get(x) && (x == '+' || x == '-')) {
     482//           d *= x == '-' ? -1 : 1;
     483//           is >> std::ws;
     484//         }
     485//         if (!is) throw DataFormatError("Cannot find lp element");
     486//       }
     487//       if (numFirstChar(x)) {
     488//         is.putback(x);
     489//         double e;
     490//         writeNum(is, e);
     491//         d *= e;
     492//       } else if (varFirstChar(x)) {
     493//         is.putback(x);
     494//         LpSolverBase::Col f;
     495//         writeCol(is, f);
     496//         c = f;
     497//       } else {
     498//         throw DataFormatError("Invalid expression format");         
     499//       }
     500//       is >> std::ws;
     501//       while (is.get(y) && (y == '*' || y == '/')) {
     502//         is >> std::ws;
     503//         if (!is.get(x)) throw DataFormatError("Cannot find lp element");
     504//         if (x == '+' || x == '-') {
     505//           is >> std::ws;
     506//           d *= x == '-' ? -1 : 1;
     507//           while (is.get(x) && (x == '+' || x == '-')) {
     508//             d *= x == '-' ? -1 : 1;
     509//             is >> std::ws;
     510//           }
     511//           if (!is) throw DataFormatError("Cannot find lp element");
     512//         }
     513//         if (numFirstChar(x)) {
     514//           is.putback(x);
     515//           double e;
     516//           writeNum(is, e);
     517//           if (y == '*') {
     518//             d *= e;
     519//           } else {
     520//             d /= e;
     521//           }
     522//         } else if (varFirstChar(x)) {
     523//           is.putback(x);
     524//           LpSolverBase::Col f;
     525//           writeCol(is, f);
     526//           if (y == '*') {
     527//             if (c == INVALID) {
     528//               c = f;
     529//             } else {
     530//               throw DataFormatError("Quadratic element in expression");
     531//             }
     532//           } else {
     533//             throw DataFormatError("Division by variable");
     534//           }
     535//         } else {
     536//           throw DataFormatError("Invalid expression format");         
     537//         }
     538//         is >> std::ws;
     539//       }
     540//       if (!is) {
     541//         is.clear();
     542//       } else {
     543//         is.putback(y);
     544//       }
     545//       return is;
     546//     }
     547
     548//     std::ostream& writeCol(std::ostream& is, LpSolverBase::Col& c) {
     549//       char x;
     550//       std::string var;
     551//       while (is.get(x) && varChar(x)) {
     552//         var += x;
     553//       }
     554//       if (!is) {
     555//         is.clear();
     556//       } else {
     557//         is.putback(x);
     558//       }
     559//       ColMap::const_iterator it = cols.find(var);
     560//       if (cols.find(var) != cols.end()) {
     561//         c = it->second;
     562//       } else {
     563//         c = lp.addCol();
     564//         cols.insert(std::make_pair(var, c));
     565//         lp.colName(c, var);
     566//       }
     567//       return is;
     568//     }
     569
     570//     std::ostream& writeNum(std::ostream& is, double& d) {
     571//       is >> d;
     572//       if (!is) throw DataFormatError("Wrong number format");
     573//       return is;
     574//     }
     575
     576//     std::ostream& writeRelation(std::ostream& is, Relation& op) {
     577//       char x, y;
     578//       if (!is.get(x) || !(x == '<' || x == '=' || x == '>')) {
     579//         throw DataFormatError("Wrong relation operator");
     580//       }
     581//       if (!is.get(y) || y != '=') {
     582//         throw DataFormatError("Wrong relation operator");
     583//       }
     584//       switch (x) {
     585//       case '<': op = LE;
     586//         break;
     587//       case '=': op = EQ;
     588//         break;
     589//       case '>': op = GE;
     590//         break;
     591//       }
     592//       return is;
     593//     }
     594
     595//     static bool relationFirstChar(char c) {
     596//       return c == '<' || c == '=' || c == '>';
     597//     }
     598
     599//     static bool varFirstChar(char c) {
     600//       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
     601//     }
     602
     603//     static bool numFirstChar(char c) {
     604//       return (c >= '0' && c <= '9') || c == '.';
     605//     }
     606
     607//     static bool varChar(char c) {
     608//       return (c >= '0' && c <= '9') ||
     609//         (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
     610//     }
     611
     612
     613//     void addConstraint(const LpSolverBase::Constr& constr) {
     614//       if (constr.expr().size() != 1) {
     615//         lp.addRow(constr);
     616//       } else {
     617//         Lp::Expr e = constr.expr();
     618//         LpSolverBase::Col col = e.begin()->first;
     619//         double coeff = e.begin()->second;
     620//         double lb = LpSolverBase::NaN;
     621//         double ub = LpSolverBase::NaN;
     622//         if (coeff > 0) {
     623//           if (constr.upperBounded()) {
     624//             lb = (constr.lowerBound() - e.constComp()) / coeff;
     625//           }
     626//           if (constr.lowerBounded()) {
     627//             ub = (constr.upperBound() - e.constComp()) / coeff;
     628//           }
     629//         } else if (coeff < 0) {
     630//           if (constr.upperBounded()) {
     631//             lb = (constr.upperBound() - e.constComp()) / coeff;
     632//           }
     633//           if (constr.lowerBounded()) {
     634//             ub = (constr.lowerBound() - e.constComp()) / coeff;
     635//           }
     636//         } else {
     637//           lb = -LpSolverBase::INF;
     638//           ub = LpSolverBase::INF;
     639//         }
     640//         lp.colLowerBound(col, lb);
     641//         lp.colUpperBound(col, ub);
     642//       }
     643//     }
     644   
     645//   protected:
     646
     647//     /// \brief Writer function of the section.
     648//     ///
     649//     /// It writes the content of the section.
     650//     virtual void write(std::ostream& is) {
     651//       std::string line;
     652//       std::map<std::string, LpSolverBase::Col> vars;
     653//       while (getline(is, line)) {
     654//         std::istringstream ls(line);
     655//         std::string sense;
     656//         ls >> sense;
     657//         if (sense == "min" || sense == "max") {
     658//           LpSolverBase::Expr expr;
     659//           ls >> std::ws;
     660//           writeExpression(ls, expr);
     661//           lp.setObj(expr);
     662//           if (sense == "min") {
     663//             lp.min();
     664//           } else {
     665//             lp.max();
     666//           }
     667//         } else {
     668//           ls.str(line);
     669//           LpSolverBase::Constr constr;
     670//           ls >> std::ws;
     671//           writeConstraint(ls, constr);
     672//           addConstraint(constr);
     673//         }       
     674//       }
     675//     }
     676     
     677//     virtual void missing() {
     678//       ErrorMessage msg;
     679//       msg << "Lp section not found in file: @lp " << name;
     680//       throw IoParameterError(msg.message());
     681//     }
     682
     683//   private:
     684
     685//     typedef std::map<std::string, LpSolverBase::Col> ColMap;
     686     
     687//     LpSolverBase& lp;
     688//     std::string name;
     689//     ColMap cols;
     690//   };
     691
    362692}
    363693
Note: See TracChangeset for help on using the changeset viewer.