Modelib: Fichier source de FichierLP.cpp

Page principale | Liste des namespaces | Hiérarchie des classes | Liste alphabétique | Liste des classes | Liste des fichiers | Membres de namespace | Membres de classe | Membres de fichier

# FichierLP.cpp

Aller à la documentation de ce fichier.

    00001 /*
    00002     Copyright (c) 2005, Quentin Lequy and Romain Gaucher
    00003     All rights reserved.
    00004
    00005     Redistribution and use in source and binary forms, with or
    00006     without modification, are permitted provided that the following
    00007     conditions are met:
    00008
    00009         * Redistributions of source code must retain the above copyright
    00010           notice, this list of conditions and the following disclaimer.
    00011
    00012         * Redistributions in binary form must reproduce the above copyright
    00013           notice, this list of conditions and the following disclaimer in the
    00014           documentation and/or other materials provided with the distribution.
    00015
    00016         * Neither the name of Quentin Lequy or Romain Gaucher nor the names
    00017           of its contributors may be used to endorse or promote products
    00018           derived from this software without specific prior written permission.
    00019
    00020     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    00021     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00022     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00023     ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    00024     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    00025     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    00026     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
    00027     AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    00029     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030 */
    00031
    00032 //:~ sof
    00033 #include "Config.h"
    00034 #include "FichierLP.h"
    00035 #include <iostream>
    00036 #include <fstream>
    00037 #include <sstream>
    00038 #include <list>
    00039 #include <string>
    00040 #include <algorithm>
    00041 #include <cctype>
    00042 #include <map>
    00043 #include <utility>
    00044 #include <vector>
    00045
    00046 namespace Modelib {
    00047
    00048 using namespace std;
    00049
    00050
    00059 ostream& operator<<(ostream &o, const string& str)
    00060 {
    00061     for (string::const_iterator iter=str.begin();iter!=str.end();++iter)
    00062     {
    00063         // on ignore les caracteres non affichables !
    00064         if (*iter < 32)
    00065             continue;
    00066         o << *iter;
    00067     }
    00068     return o;
    00069 }
    00070
    00076 ostream& operator<<(ostream &o, const plExprNode& pl)
    00077 {
    00078   o << (pl.signe == MINUS ? '-' : '+') << pl.num << "*" << pl.var;
    00079   return o;
    00080 }
    00081
    00087 ostream& operator<<(ostream &o, const plGlobalNode& pl)
    00088 {
    00089   if (pl.nom != "")
    00090     o << pl.nom << ": ";
    00091   for (list<plExprNode *>::const_iterator iter = pl.expr.begin();iter!=pl.expr.end(); ++iter)
    00092   {
    00093     if (iter == pl.expr.begin())
    00094        o << ((*iter)->signe == MINUS ? "-" : " ") << (*iter)->num << '*' << (*iter)->var << ' ';
    00095     else
    00096        o << **iter;
    00097   }
    00098   o << "  " << comp[pl.cont.comp] << " " << pl.cont.bound;
    00099   return o;
    00100 }
    00101
    00102
    00108 ostream& operator<<(ostream& o, const plConstraintNode& pl)
    00109 {
    00110   o << pl.minBound << " ";
    00111   o << comp[pl.comp1] << " ";
    00112   if (pl.num != "1")
    00113      o << pl.num << "*";
    00114   o << pl.var;
    00115
    00116   if (pl.comp2 != 99)
    00117      o << comp[pl.comp2] << " " << pl.maxBound;
    00118
    00119   return o;
    00120 }
    00121
    00140 ostream& operator<<(ostream &o, const FichierProbleme& pblm)
    00141 {
    00142     o << "\\Sortie du fichier de probleme: " << pblm.nom << endl;
    00143
    00144     // Affichage de la fonction objectif
    00145     if (pblm.isMax == true)
    00146        o << "Maximize" << endl;
    00147     else
    00148        o << "Minimize" << endl;
    00149
    00150     for (list<plExprNode *>::const_iterator iter  = pblm.exprObj.begin();
    00151                                             iter != pblm.exprObj.end()  ;
    00152                                           ++iter)
    00153       if (iter == pblm.exprObj.begin() && (*iter)->var.length())
    00154          o << "\t" << ((*iter)->signe == MINUS ? "-" : " ") << (*iter)->num << "*" << (*iter)->var << ' ';
    00155       else
    00156          o << **iter;
    00157
    00158     // Affichages des contraintes (fonctions)
    00159     o << endl;
    00160     o << "Subject to" << endl;
    00161
    00162
    00163     for (list<plGlobalNode *>::const_iterator iter  = pblm.exprConstraint.begin();
    00164                                             iter != pblm.exprConstraint.end()  ;
    00165                                           ++iter)
    00166          o << "\t" << **iter << endl;
    00167
    00168     if (!pblm.exprBounds.empty())
    00169     {
    00170       o << "Bounds" << endl;
    00171
    00172
    00173       for (list<plConstraintNode *>::const_iterator iter  = pblm.exprBounds.begin();
    00174                                               iter != pblm.exprBounds.end()  ;
    00175                                             ++iter)
    00176            o << "\t" << **iter << endl;
    00177     }
    00178     if (!pblm.exprGeneral.empty())
    00179     {
    00180       o << "Generals" << endl;
    00181       for (list<string>::const_iterator iter =pblm.exprGeneral.begin();
    00182                                         iter!=pblm.exprGeneral.end()  ;
    00183                                       ++iter)
    00184            o << "\t" << *iter << endl;
    00185     }
    00186
    00187     if (!pblm.exprBinary.empty())
    00188     {
    00189       o << "Binaries" << endl;
    00190       for (list<string>::const_iterator iter =pblm.exprBinary.begin();
    00191                                         iter!=pblm.exprBinary.end()  ;
    00192                                       ++iter)
    00193            o << "\t" << *iter << endl;
    00194     }
    00195
    00196     o << "End";
    00197     return o;
    00198 }
    00199
    00200
    00201
    00209 FichierLP::FichierLP()
    00210 {
    00211
    00212   mmap.insert(pair<string,unsigned>("maximize",MAXIMIZE));
    00213   mmap.insert(pair<string,unsigned>("max",MAXIMIZE));
    00214
    00215   mmap.insert(pair<string,unsigned>("minimize",MINIMIZE));
    00216   mmap.insert(pair<string,unsigned>("min",MINIMIZE));
    00217
    00218   mmap.insert(pair<string,unsigned>("subject to",SUBJECT));
    00219   mmap.insert(pair<string,unsigned>("subject",SUBJECT));
    00220   mmap.insert(pair<string,unsigned>("such that",SUBJECT));
    00221   mmap.insert(pair<string,unsigned>("st",SUBJECT));
    00222   mmap.insert(pair<string,unsigned>("st.",SUBJECT));
    00223   mmap.insert(pair<string,unsigned>("s.t.",SUBJECT));
    00224
    00225   mmap.insert(pair<string,unsigned>("bounds",BOUNDS));
    00226   mmap.insert(pair<string,unsigned>("bound",BOUNDS));
    00227
    00228   mmap.insert(pair<string,unsigned>("end",END));
    00229
    00230   mmap.insert(pair<string,unsigned>("generals",GENERALS));
    00231   mmap.insert(pair<string,unsigned>("general",GENERALS));
    00232   mmap.insert(pair<string,unsigned>("gen",GENERALS));
    00233   mmap.insert(pair<string,unsigned>("integers",GENERALS));
    00234   mmap.insert(pair<string,unsigned>("integer",GENERALS));
    00235
    00236   mmap.insert(pair<string,unsigned>("binaries",BINARIES));
    00237   mmap.insert(pair<string,unsigned>("binary",BINARIES));
    00238   mmap.insert(pair<string,unsigned>("bin",BINARIES));
    00239
    00240   mmap.insert(pair<string,unsigned>("free",FREE));
    00241
    00242   // remplir le Comp2Int
    00243   for (unsigned i=0;i<6;i++)
    00244       Comp2Int[comp[i]] = i;
    00245 }
    00246
    00251 bool FichierLP::IsComment(string& s)
    00252 {
    00253   // on return false si c pas un comentaire complet
    00254   // et on efface tout ce qu'il y a apres
    00255   string::iterator iter = s.begin();
    00256   string           tmp;
    00257   // si c'est une ligne complete
    00258   if (*iter == '\\') {
    00259      commentaires.push_back( pair<long,string>( (long)exprConstraint.size()
    00260      + ( exprObj.size()==0?0:1) ,s) );
    00261      return true;
    00262   }
    00263   // sinon... on gicle tout ce qu'il y a apres le char
    00264   for (;iter!=s.end();++iter)
    00265   {
    00266     if (*iter == '\\')
    00267        break;
    00268     tmp += *iter;
    00269   }
    00270   s.erase();
    00271   s = tmp;
    00272   return false;
    00273 }
    00274
    00279 string FichierLP::trim(const string& s) const
    00280 {
    00281   if(s.empty())
    00282     return s;
    00283   int b = s.find_first_not_of(" ");
    00284   int e = s.find_last_not_of(" ");
    00285   if(b == -1)
    00286     return "";
    00287   return string(s, b, e - b + 1);
    00288 }
    00289
    00294 string FichierLP::AvoidSpaces(const string& s) const
    00295 {
    00296   string t;
    00297   string::const_iterator iter = s.begin();
    00298   for(;iter!=s.end();++iter)
    00299     if (*iter != ' ')
    00300       t += *iter;
    00301   return t;
    00302 }
    00303
    00309 bool FichierLP::IsNumber(const string& s) const
    00310 {
    00311   const string nums="0123456789./";
    00312   string::const_iterator iter;
    00313   bool pointWOSlash = false;
    00314   for (iter=s.begin();iter!=s.end();++iter)
    00315   {
    00316     if (pointWOSlash && *iter=='.')
    00317       return false;
    00318     if (nums.find(*iter) != string::npos)
    00319     {
    00320       if (*iter == '.')  pointWOSlash=true;
    00321       if (*iter == '/' ) pointWOSlash=false;
    00322     }
    00323     else
    00324       return false;
    00325   }
    00326   return true;
    00327 /* tests effectués là dessus
    00328   cout << endl;
    00329   cout << "2.000 = " << IsNumber("2.000") << endl;
    00330   cout << "2.000. = " << IsNumber("2.000.") << endl;
    00331   cout << "2.000/1 = " << IsNumber("2.000/1") << endl;
    00332   cout << "2.000/0.00 = " << IsNumber("2.000/0.00") << endl;
    00333   cout << "2.000/0.00. = " << IsNumber("2.000/0.00.") << endl;
    00334   cout << endl;
    00335 */
    00336 }
    00337
    00343 void FichierLP::Tokenize(const string& str,list<string>& tokens_plus
    00344                                           ,list<string>& tokens_minus)
    00345 {
    00346     enum Token_Value {PLUS='+', MINUS='-'};
    00347     Token_Value cur_token = PLUS;
    00348     string tmp;
    00349     string::size_type i=0;
    00350     const string::size_type len = str.length();
    00351
    00352     do
    00353     {
    00354       while(str[i]==' ') ++i;
    00355       if (str[i] == PLUS || str[i] == MINUS)
    00356       {
    00357         if(tmp.length())
    00358         {
    00359             // on le balance dans le container de tokens
    00360             switch(cur_token)
    00361             {
    00362               case PLUS :  tokens_plus.push_back(tmp); break;
    00363               case MINUS:  tokens_minus.push_back(tmp); break;
    00364               default   :                              break;
    00365             }
    00366             // alors on flush tmp
    00367             tmp.clear();
    00368             // actualisation du token
    00369             cur_token = (str[i]=='+'?PLUS:MINUS);
    00370         }
    00371         else
    00372           cur_token = (str[i]=='+'?PLUS:MINUS);
    00373       }
    00374       else
    00375         tmp += str[i];
    00376       ++i;
    00377     }
    00378     while (i < len);
    00379
    00380     // il reste necessairement la derniere partie
    00381     switch(cur_token)
    00382     {
    00383       case PLUS :  tokens_plus.push_back(tmp); break;
    00384       case MINUS: tokens_minus.push_back(tmp); break;
    00385       default   :                              break;
    00386     }
    00387 }
    00388
    00394 void FichierLP::GetNumVar(const string& str, string& num, string& var)
    00395 {
    00396   string::const_iterator iter=str.begin();
    00397   unsigned i=0;
    00398   if (!isdigit(*iter))
    00399   {
    00400     num = "1";
    00401     var = str;
    00402   }
    00403   else
    00404   {
    00405     for (;iter!=str.end();++iter,++i)
    00406     {
    00407       if (!IsNumber(str.substr(0,i)))
    00408       {
    00409         num=str.substr(0,i-1);
    00410         var=str.substr(i-1,str.length());
    00411         break;
    00412       }
    00413     }
    00414   }
    00415 }
    00416
    00417
    00418
    00419
    00423 void FichierLP::ParseObjective(const string& s)
    00424 {
    00425   // on va tokeniser par +/-
    00426   list<string> token_plus;
    00427   list<string> token_minus;
    00428   list<string>::iterator iter;
    00429
    00430   if (s.length() <= 1)
    00431      return;
    00432
    00433   Tokenize (s,token_plus,token_minus);
    00434
    00435   for(iter=token_plus.begin();iter!=token_plus.end();++iter)
    00436   {
    00437     string var,num;
    00438     GetNumVar(*iter,var,num);
    00439
    00440     //cout << "PLUS: "<< var << '(' << trim(var) << ')' << '(' << var.size() << ')' << endl;
    00441
    00442     auto_ptr<plExprNode> exprNode (new plExprNode (num,var,PLUS)) ;
    00443     exprObj.push_back(exprNode.release());
    00444   }
    00445
    00446   for(iter=token_minus.begin();iter!=token_minus.end();++iter)
    00447   {
    00448     string var,num;
    00449     GetNumVar(*iter,var,num);
    00450     //cout << "PLUS: "<< var << '(' << trim(var) << ')' << '(' << var.size() << ')' << endl;
    00451
    00452     auto_ptr<plExprNode> exprNode (new plExprNode (num,var,MINUS)) ;
    00453     exprObj.push_back(exprNode.release());
    00454   }
    00455
    00456   // ca marche !
    00457   //cout << "Et là ?" << endl;
    00458   // afficher les données
    00459   //for (list<plExprNode *>::iterator i=exprObj.begin(); i!=exprObj.end(); ++i)
    00460   //    cout << **i << endl;
    00461
    00462
    00463 }
    00464
    00465
    00470 void FichierLP::ParseSubjects (const string& s, const string& nom)
    00471 {
    00472   // contraintes SubJects...
    00473   // trouver le délimitage :]
    00474   string::size_type place_comp=string::npos;
    00475   unsigned i=0;
    00476
    00477
    00478     if (s.length() <= 1)
    00479      return;
    00480
    00481
    00482   for (;i<6;i++)
    00483   {
    00484     if ((place_comp = s.find(comp[i])) != string::npos)
    00485        break;
    00486   }
    00487
    00488   if (place_comp == string::npos)
    00489   {
    00490     // bah ca merde !
    00491     return;
    00492   }
    00493
    00494   string compareTo;
    00495   string second;
    00496   compareTo = s.substr(place_comp+comp[i].length(),s.length());
    00497   second    = s.substr(0,place_comp);
    00498
    00499   //cout << i << " chaine=" << second << "| compare a=" << compareTo << " par " << comp[i] << endl;
    00500
    00501   list<string> token_plus;
    00502   list<string> token_minus;
    00503   list<string>::iterator iter;
    00504   Tokenize (second,token_plus,token_minus);
    00505
    00506   // ce qu'on va pusher !
    00507   //auto_ptr<plGlobalNode> tmpNode;
    00508   list<plExprNode *>     tmpObj;
    00509
    00510   for(iter=token_plus.begin();iter!=token_plus.end();++iter)
    00511   {
    00512     string var,num;
    00513     GetNumVar(*iter,var,num);
    00514     auto_ptr<plExprNode> exprNode (new plExprNode (num,var,PLUS)) ;
    00515     tmpObj.push_back(exprNode.release());
    00516   }
    00517
    00518   for(iter=token_minus.begin();iter!=token_minus.end();++iter)
    00519   {
    00520     string var,num;
    00521     GetNumVar(*iter,var,num);
    00522     auto_ptr<plExprNode> exprNode (new plExprNode (num,var,MINUS)) ;
    00523     tmpObj.push_back(exprNode.release());
    00524   }
    00525
    00526   // ca, ca nous ressort bien ce qu'on veut !
    00527   // ie la liste des tokens
    00528   //cout << "Ce qu'on devrait avoir..." << endl;
    00529   //for (list<plExprNode *>::iterator i=tmpObj.begin(); i!=tmpObj.end(); ++i)
    00530   //    cout << **i << endl;
    00531
    00532   // Creation de notre ptr qui sera pushé
    00533   plSimpleConstraint tmpConst(compareTo,i);
    00534   auto_ptr<plGlobalNode> tmpNode (new plGlobalNode (nom,tmpObj,tmpConst));
    00535
    00536   // gnourf ?
    00537   //cout << "Ce qu'on a :|" << endl;
    00538
    00539   // afficher les données
    00540   //cout << "Choppage en manuel des 'values'" << endl;
    00541   //list<plExprNode *>::const_iterator iterNode=tmpNode.get()->expr.begin();
    00542
    00543   // boucle avec l'itérateur
    00544   //cout << "et avec l'itérateur.. et là, c le drame" << endl;
    00545   //for (iterNode=tmpNode.get()->expr.begin();iterNode!=tmpNode.get()->expr.end(); ++iterNode)
    00546   //    cout << **iterNode << endl;
    00547
    00548   //cout << *(tmpNode.get()) << endl;
    00549
    00550   exprConstraint.push_back(tmpNode.release());
    00551 }
    00552
    00553
    00558 unsigned GetNbComparator(const string& _str)
    00559 {
    00560   unsigned nbComp=0;
    00561   string::size_type pos;
    00562   string sub=_str;
    00563
    00564   for (unsigned j=0;j<6;)
    00565   {
    00566     if ((pos=sub.find(comp[j])) != string::npos)
    00567     {
    00568       nbComp++;
    00569       sub = sub.substr(pos+comp[j].length(),sub.length());
    00570     }
    00571     else
    00572       j++;
    00573   }
    00574   return nbComp;
    00575 }
    00576
    00577
    00585 void FichierLP::ParseBounds(const string& s)
    00586 {
    00587   // parser :
    00588   // -Inf <= a <= bsup
    00589   //         b <= bsup
    00590   // binf <= c
    00591   string str;
    00592
    00593   if (s.length() <= 1)
    00594      return;
    00595
    00596
    00597   string::const_iterator iter,it2=s.begin(),next;
    00598   // compter le nombre de de signes
    00599   unsigned nbComp = GetNbComparator(s);
    00600   // 2*nbComp+1 champs !
    00601
    00602   // on ajoute des espaces pour utiliser les stringstream
    00603   // iter: cour
    00604   // it2 : prec
    00605   next = s.begin(); ++next;
    00606   for (iter=s.begin();iter!=s.end();++iter, ++next)
    00607   {
    00608       switch(*iter)
    00609       {
    00610         case '<': // Si <
    00611         case '>': // ou >
    00612              str.push_back(' ');   // on ajoute l'espace
    00613              str.push_back(*iter); // et < ou >
    00614
    00615                 // ajouter un espace s'il n'y a pas de signe apres
    00616                 if (*next != '=')
    00617                    str.push_back(' ');
    00618              break;
    00619
    00620         case '=':
    00621              if (*it2 != '<' && *it2 != '>')
    00622                str.push_back(' ');
    00623              str.push_back(*iter);
    00624              str.push_back(' ');
    00625              break;
    00626
    00627         default:
    00628              str.push_back(*iter);
    00629              break;
    00630       }
    00631       it2 = iter;
    00632   }
    00633
    00634   string *t = 0;
    00635   if (nbComp > 0)
    00636   {
    00637     istringstream sstring(str);
    00638     t = new string[(2*nbComp+1)];
    00639
    00640     for (unsigned i=0;i<(nbComp<<1) + 1;i++)
    00641     {
    00642         sstring >> t[i];
    00643     }
    00644   }
    00645
    00646
    00647   // on va remplir le exprBounds
    00648   // exprBounds
    00649   switch (nbComp)
    00650   {
    00651     case 2:
    00652       {
    00653           // 2 comparateurs => min <= var <= max
    00654           //plConstraintNode(const std::string& _var, const std::string& _num,
    00655           //                   const std::string& _b1 , const std::string& _b2 ,
    00656           //                   const unsigned     _c1 , const unsigned     _c2)
    00657          auto_ptr<plConstraintNode> cNode (new plConstraintNode (t[2],"1",t[0],t[4],Comp2Int[t[1]],Comp2Int[t[3]]));
    00658          exprBounds.push_back(cNode.release());
    00659       }
    00660     break;
    00661
    00662     case 1:
    00663       {
    00664          // si t[0] est un nombre alors
    00665          //   forme 0 <= var      _num _var _minbound _comp1
    00666          // sinon
    00667          //   autre forme         _num _var _comp1 _maxbound
    00668          //cout << "t0 = " << t[0] << endl;
    00669          if (IsNumber(t[0]))
    00670          {
    00671            auto_ptr<plConstraintNode> cNode (new plConstraintNode ("1",t[2],t[0],Comp2Int[t[1]]));
    00672            exprBounds.push_back(cNode.release());
    00673          }
    00674          else
    00675          {
    00676            auto_ptr<plConstraintNode> cNode (new plConstraintNode ("1",t[0],t[2],(Comp2Int[t[1]]+2)%4));
    00677            exprBounds.push_back(cNode.release());
    00678          }
    00679       }
    00680     break;
    00681
    00682     case 0:
    00683      {
    00684         // Le free est ici
    00685         // x1 Free
    00686         string tmp;
    00687         istringstream sstring(str);
    00688         sstring >> tmp;
    00689         auto_ptr<plConstraintNode> cNode (new plConstraintNode (tmp,"1","-Inf","Inf",LOWER_THAN,LOWER_THAN));
    00690         exprBounds.push_back(cNode.release());
    00691      }
    00692     break;
    00693
    00694     default:
    00695         // on levera une exception ici pke ca ne peut pas exister !
    00696         // enfin, je pense sincèremetn que CPlex ne gere pas :
    00697         // MIN <= x1 <= x2 <= x3 <= ... <= MAX
    00698     break;
    00699   }
    00700   if (t)
    00701     delete [] t;
    00702 }
    00703
    00707 void FichierLP::ParseGenerals(const string& s)
    00708 {
    00709      // on a une ligne x2,x3,x4...
    00710      // ou  x1
    00711      //     x2
    00712      //     x3
    00713
    00714      // 1/ on va donc se normaliser l'expression en x4 x2 etc. sur une ligne
    00715      // 2/ utiliser un stringstream et pusher le tout dans la liste
    00716
    00717
    00718     if (s.length() <= 1)
    00719        return;
    00720
    00721
    00722     // 1/ Il suffit de remplacer toutes les virgules par des espaces :]
    00723     string str;
    00724     string::const_iterator iter=s.begin();
    00725     for (;iter!=s.end(); ++iter)
    00726     {
    00727       if (*iter == ',')
    00728          str.push_back(' ');
    00729       else
    00730          str.push_back(*iter);
    00731     }
    00732
    00733     // 2/ istringstream est sympatique :]
    00734     istringstream istring(str);
    00735     string tmp;
    00736     while (istring >> tmp) {
    00737          exprGeneral.push_back(tmp);
    00738          tmp.erase();
    00739     }
    00740 }
    00741
    00742
    00746 void FichierLP::ParseBinaries(const string& s)
    00747 {
    00748      // on a une ligne x2,x3,x4...
    00749      // ou  x1
    00750      //     x2
    00751      //     x3
    00752
    00753   if (s.length() <= 1)
    00754      return;
    00755
    00756
    00757      // 1/ on va donc se normaliser l'expression en x4 x2 etc. sur une ligne
    00758      // 2/ utiliser un stringstream et pusher le tout dans la liste
    00759
    00760
    00761      // 1/ Il suffit de remplacer toutes les virgules par des espaces :]
    00762      string str;
    00763      string::const_iterator iter=s.begin();
    00764      for (;iter!=s.end(); ++iter)
    00765      {
    00766         if (*iter == ',')
    00767            str.push_back(' ');
    00768         else
    00769            str.push_back(*iter);
    00770      }
    00771
    00772      // 2/ istringstream est sympatique :]
    00773      istringstream istring(str);
    00774      string tmp;
    00775      while (istring >> tmp) {
    00776            exprBinary.push_back(tmp);
    00777            tmp.erase();
    00778      }
    00779 }
    00780
    00781
    00782
    00787 bool FichierLP::Open(const string& nomFile)
    00788 {
    00789   ifstream ifile(nomFile.c_str());
    00790
    00791   string   s,tempInlineString;
    00792   multimap<string,unsigned>::iterator k;
    00793   unsigned oldK=42;
    00794   bool continu=false,f=false;
    00795   bool objectiveInline = false;
    00796
    00797
    00798   if (!ifile.is_open())
    00799      return false;
    00800
    00801   //while (getline(ifile,s))
    00802   //      cout << s << endl;
    00803   //ifile.clear();
    00804   // on revient au début apres avoir affiché le source lp
    00805   //if (!ifile.seekg(0,ifstream::beg))
    00806   //   return false;
    00807
    00808   while (getline(ifile,s,'\n'))
    00809   {
    00810     if (!s.empty() && IsComment(s) == false)
    00811     {
    00812         string::size_type position = s.rfind('\r');
    00813         if (position != string::npos)
    00814             s.replace(position,1," ");
    00815
    00817       // par la casse
    00818       if (objectiveInline)
    00819       {
    00820         objectiveInline = false;
    00821         // on traite tempInelinestring comme un ParseObjective
    00822         ParseObjective(tempInlineString);
    00823       }
    00824
    00825       //string c=s;
    00826       string c;
    00827       for (string::const_iterator iter = s.begin(); iter!=s.end();++iter)
    00828       {
    00829         if (*iter == ' ')
    00830            break;
    00831         c.push_back(*iter);
    00832       }
    00833
    00834       transform (c.begin(),c.end(),c.begin(),::tolower);
    00835       // On peut maintenant travailler sur le "string s"
    00836
    00837       k = mmap.find(trim(c)); // Recherche de la value !s
    00838       if (k == mmap.end())    // si value non trouvée dans la table
    00839          continu = true;
    00840       else                    // c'est que ce n'est pas un nouveau champ
    00841           continu = false,
    00842           oldK = 42;
    00843
    00844       if (!continu && k->second == END)
    00845       {
    00846
    00847         // affichage des tous les commentaires
    00848         /*for (list<string>::iterator iC =commentaires.begin();
    00849                                     iC!=commentaires.end();
    00850                                     ++iC)
    00851             cout << "Commentaires: " << *iC << endl;
    00852         */
    00853
    00854          return true;
    00855       }
    00856
    00857       if (oldK==42 && objectiveInline==false && ((k->second == MAXIMIZE && oldK != MAXIMIZE) || (k->second == MINIMIZE && oldK != MINIMIZE)))
    00858       {
    00859         objectiveInline = true;
    00860         tempInlineString = s.substr(8,s.length());
    00861       }
    00862
    00863       switch(oldK)
    00864       {
    00865          //
    00866          // on doit gérer le multiligne
    00867          // ce n'est pas encore fait pour les contraintes
    00868          // ca devrait y etre bientot ...
    00869          // quand tous les champs seront gérés
    00870          //
    00871          //                                         13/12/2004
    00872          case MINIMIZE:
    00873          case MAXIMIZE:
    00874          {
    00875            if (f==false){
    00876                if (oldK==MINIMIZE) isMax=false, f=true;
    00877              else                isMax=true,  f=true;
    00878            }
    00879            // string | list<lpExprNode *> | plSimpleConstraint
    00880            size_t pos;
    00881            string _nom="(null)";
    00882
    00883            s = AvoidSpaces(s);
    00884            // on va avancer jusqu'aux ':'
    00885            if ((pos = s.find(':',0)) != string::npos)
    00886            {
    00887              _nom = s.substr(0,pos);
    00888              nom = _nom;
    00889              s.erase(0,pos+1);
    00890            }
    00891            ParseObjective(s);
    00892              break;
    00893          }
    00894          case SUBJECT:
    00895          {
    00896            size_t pos;
    00897            string nom;
    00898
    00899            s = AvoidSpaces(s);
    00900            if ((pos = s.find(':',0)) != string::npos) {
    00901              nom = s.substr(0,pos);
    00902              s.erase(0,pos+1);
    00903            }
    00904            ParseSubjects(s,nom);
    00905              break;
    00906          }
    00907          case BOUNDS:
    00908              ParseBounds(trim(s));
    00909              break;
    00910          case GENERALS:
    00911              ParseGenerals(trim(s));
    00912              break;
    00913          case BINARIES:
    00914              ParseBinaries(trim(s));
    00915              break;
    00916          case END:
    00917            break;
    00918          default:
    00919            break;
    00920       }
    00921
    00922       if (continu == false)
    00923         oldK = k->second;
    00924     }
    00925   }
    00926
    00927   return true;
    00928 }
    00929
    00930 }
    00931
    00932 //:~ eof