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

Model.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 #include "Model.h"
00033 #include "FichierLP.h"
00034 #include "FichierMPS.h"
00035 #include <list>
00036 #include <iostream>
00037 #include <sstream>
00038 #include <cmath>
00039 #include <stdexcept>
00040 
00041 namespace Modelib {
00042 
00043 using namespace std;
00044 
00046 Model::Model(const Model &m)
00047 {
00048     *this = m;
00049 }
00050 
00052 Model & Model::operator=(const Model &m)
00053 {
00054     if( this != &m)
00055     {
00056       hacheVarId=m.hacheVarId;
00057       unknowMap=m.unknowMap;
00058       A.matrix = m.A.matrix;
00059       A.nbLignes = m.A.nbLignes;
00060       A.nbCols = m.A.nbCols;
00061       constraintMap = m.constraintMap;
00062   
00063       isMax = m.isMax;
00064       isRelaxed = m.isRelaxed;
00065       isFract = m.isFract;
00066       isOptimal = m.isOptimal;
00067       isSolved = m.isSolved;
00068       MIPVar = m.MIPVar;
00069   
00070       objectif = m.objectif;
00071       objectifActivity = m.objectifActivity;
00072       objectifName = m.objectifName;
00073       problemName = m.problemName;
00074       
00075       solverAPI = m.solverAPI;
00076     }
00077     return *this;
00078 }
00079 
00080 /*-------------------------------------------------------------------------------------------------------*/
00084 float Model::GetLagrangianParamValue( VarId id ) const
00085 {
00086   std::map<VarId,InternalConstraint>::const_iterator trouve = constraintMap.find(id);
00087   if(trouve!=constraintMap.end())
00088      return trouve->second.lagrangianValue;
00089   else
00090      cerr << "Warning in Model::GetLagrangianParamValue : undefined id " << id<< endl;
00091   return 0;
00092 }
00093 
00094 
00098 void Model::SetLagrangianParamValue(VarId id, float value)
00099 {
00100   std::map<VarId,InternalConstraint>::iterator trouve = constraintMap.find(id);
00101   if( trouve!=constraintMap.end())
00102   {
00103     //selon le type de contrainte les domaines de définition du multiplicateur varient
00104     switch(trouve->second.type)
00105     {
00106         case InternalConstraint::INFSTRICT :
00107         case InternalConstraint::INF :
00108         //Pour les contraintes de type inférieur, le multiplicateur est positif
00109         if(value < 0)
00110           {
00111              value = 0;
00112            cerr << "Warning in Model::SetLagrangianParamValue : constraint " << id
00113                   << " lagrangian value is out of his definition area" << endl;
00114           }
00115         break;
00116 
00117         case InternalConstraint::SUPSTRICT :
00118         case InternalConstraint::SUP :
00119         //Pour les contraintes de type inférieur, le multiplicateur est positif
00120         if(value > 0)
00121           {
00122              value = 0;
00123              cerr << "Warning in Model::SetLagrangianParamValue : constraint " << id
00124                   << " lagrangian value is out of his definition area" << endl;
00125           }
00126         break;
00127 
00128         case InternalConstraint::EGAL :
00129         //Pour les contraintes de type egal, le multiplicateur est réel
00130         break;
00131 
00132         default:
00133            cerr << "Warning in Model::SetLagrangianParamValue : wrong InternalConstraint::Type" << endl;
00134         break;
00135      }
00136      trouve->second.lagrangianValue = value;
00137   }
00138   else
00139      cerr << "Warning in Model::SetLagrangianParamValue : undefined id " << id << endl;
00140 }
00141 
00142 
00143 /*--------------------------------------------------------------------------------------------------------*/
00151 VarId Model::AddVar( const MuteVar & muteVar, const std::string & _nom )
00152 {
00153   string tmpnom;
00154   //futur nom de la variable
00155   //si la variable n'a pas de nom défini
00156   if( _nom == "unknow" )
00157   {
00158     char * nomId = new char[30];
00159     //on recupere son futur identifiant dans un buffer de caractère
00160     sprintf(nomId,"%d",hacheVarId);
00161     tmpnom = _nom + nomId ;
00162     //le futur nom de la variable sera donc unknow{id}
00163     delete [] nomId;
00164     //on libere le buffer
00165   }
00166   else
00167     tmpnom = _nom;
00168   //sinon on son futur nom est le nom donner par l'utilisateur
00169   unknowMap[hacheVarId]=Paire(muteVar,tmpnom);
00170   //on insere la variable dans le map
00171   if( muteVar.GetType() != MuteVar::FLOAT)
00172     MIPVar++;
00173   //si la variable n'est pas continues on augmente le compteur des variables MIP
00174   return hacheVarId++;
00175   //on retourne l'identifiant puis on l'augmente
00176 }
00177 
00178 /*--------------------------------------------------------------------------------------------------------*/
00184 MuteVar Model::GetMuteVar( VarId varId) const
00185 {
00186   std::map<VarId,Paire>::const_iterator trouve = unknowMap.find(varId);
00187   if(trouve!=unknowMap.end())
00188      return trouve->second.variable;
00189   else
00190      cerr << "Warning in Model::GetMuteVar : undefined id " << varId << endl;
00191   return MuteVar();
00192 }
00193 
00194 
00200 NumVar Model::GetNumVar( VarId varId) const
00201 {
00202   return NumVar(this,varId);
00203 }
00204 
00210 std::string Model::GetName( VarId varId ) const
00211 {
00212   std::map<VarId,Paire>::const_iterator trouve = unknowMap.find(varId);
00213   if(trouve!=unknowMap.end())
00214      return trouve->second.nom;
00215   else
00216      cerr << "Warning in Model::GetName : undefined id " << varId << endl;
00217   return defaultGetName;
00218 }
00219 
00225 void Model::SetName( VarId varId, const std::string & name )
00226 {
00227   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00228   if(trouve!=unknowMap.end())
00229      trouve->second.nom = name;
00230   else
00231      cerr << "Warning in Model::GetName : undefined id " << varId << endl;
00232 }
00233 
00234 VarId Model::GetVarId(const std::string & name) const
00235 {
00236    std::map<VarId,Paire>::const_iterator trouve = unknowMap.begin();
00237    VarId retour = 0;
00238    //Pour toutes les variables
00239    for(;trouve!=unknowMap.end();++trouve)
00240      //si on trouve le nom
00241      if(trouve->second.nom == name)
00242      {
00243        retour = trouve->first;
00244        //on récupère l'identifiant et on arrête la boucle
00245        break;
00246      }
00247    if(retour == 0)
00248      cerr << "Warning in Model::GetVarId : undefined name " << name << endl;
00249    return retour;
00250 
00251 }
00252 
00253 
00254 /*--------------------------------------------------------------------------------------------------------*/
00260 float Model::GetMuteVarLB( VarId varId) const
00261 {
00262   std::map<VarId,Paire>::const_iterator trouve = unknowMap.find(varId);
00263   if(trouve!=unknowMap.end())
00264      return (trouve->second.variable).GetLowerBound();
00265   else
00266      cerr << "Warning in Model::GetMuteVarLB : undefined id " << varId << endl;
00267   return 0.0;
00268 }
00269 
00275 void Model::SetMuteVarLB( VarId varId, float _value)
00276 {
00277   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00278   if(trouve!=unknowMap.end())
00279      (trouve->second.variable).SetLowerBound( _value);
00280   else
00281       cerr << "Warning in Model::SetMuteVarLB : undefined id " << varId << endl;
00282  return;
00283 }
00284 
00285 /*--------------------------------------------------------------------------------------------------------*/
00291 float Model::GetMuteVarUB( VarId varId) const
00292 {
00293   std::map<VarId,Paire>::const_iterator trouve = unknowMap.find(varId);
00294   if(trouve!=unknowMap.end())
00295      return  (trouve->second.variable).GetUpperBound();
00296   else
00297       cerr << "Warning in Model::GetMuteVarUB : undefined id " << varId << endl;
00298   return Infinity;
00299 }
00300 
00301 
00307 void Model::SetMuteVarUB( VarId varId, float _value)
00308 {
00309   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00310   if(trouve!=unknowMap.end())
00311      (trouve->second.variable).SetUpperBound( _value);
00312   else
00313       cerr << "Warning in Model::SetMuteVarUB : undefined id " << varId << endl;
00314   return;
00315 }
00316 
00317 /*--------------------------------------------------------------------------------------------------------*/
00324 void Model::SetMuteVarLBStrict( VarId varId, bool _value)
00325 {
00326   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00327   if(trouve!=unknowMap.end())
00328      (trouve->second.variable).SetIsLBStrict( _value);
00329   else
00330       cerr << "Warning in Model::SetMuteVarLBStrict : undefined id " << varId << endl;
00331   return;
00332 }
00333 
00340 void Model::SetMuteVarUBStrict( VarId varId, bool _value)
00341 {
00342   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00343   if(trouve!=unknowMap.end())
00344      (trouve->second.variable).SetIsUBStrict( _value);
00345   else
00346       cerr << "Warning in Model::SetMuteVarUBStrict : undefined id " << varId << endl;
00347   return;
00348 }
00349 
00350 /*--------------------------------------------------------------------------------------------------------*/
00356 MuteVar::VarType Model::GetType( VarId varId) const
00357 {
00358   std::map<VarId,Paire>::const_iterator trouve = unknowMap.find(varId);
00359   if(trouve!=unknowMap.end())
00360      return (trouve->second.variable).GetType();
00361   else
00362      cerr << "Warning in Model::GetType : undefined id " << varId << endl;
00363   return MuteVar::FLOAT;
00364 }
00365 
00371 void Model::SetType(  VarId varId, MuteVar::VarType _type)
00372 {
00373   std::map<VarId,Paire>::iterator trouve = unknowMap.find(varId);
00374   if(trouve!=unknowMap.end())
00375   {
00376     if( trouve->second.variable.GetType()!=MuteVar::FLOAT 
00377       &&  _type == MuteVar::FLOAT)
00378          MIPVar++;
00379     if( trouve->second.variable.GetType()==MuteVar::FLOAT
00380        &&  _type != MuteVar::FLOAT)
00381          MIPVar--;
00382     (trouve->second.variable).SetType( _type);
00383   }
00384   else
00385      cerr << "Warning in Model::SetType : undefined id " << varId << endl;
00386   return;
00387 }
00388 
00389 /*--------------------------------------------------------------------------------------------------------*/
00394 void Model::Maximize(const Expr & expr , const std::string & name )
00395 {
00396    objectif = expr;
00397    objectif.Simplify();
00398    isMax = true;
00399    objectifName = name;
00400 }
00401 
00406 void Model::Minimize(const Expr & expr, const std::string & name )
00407 {
00408    objectif = expr;
00409    objectif.Simplify();
00410    isMax = false;
00411    objectifName = name;
00412 }
00413 
00414 /*--------------------------------------------------------------------------------------------------------*/
00422 VarId Model::AddExpr( Expr & expr , MatriceCreuse<float> & A )
00423 {
00424    std::list<ExprNode>::iterator iter;
00425    unsigned p = A.GetNbLignes()+1;
00426    for( iter = expr.nodeList.begin(); iter != expr.nodeList.end(); ++iter)
00427    {
00428       float coef = iter->GetCoefficient().GetValue();
00429       NumVar varTmp = iter->GetVariable();
00430       VarId varId = (varTmp.GetModel()?varTmp.GetVarId():0);
00431       if(varId && unknowMap.find(varId) != unknowMap.end())
00432       {
00433         A.Set(varId,p,coef);
00434       }
00435       else
00436       {
00437         if(varId)
00438             cerr << "Warning in Model::AddExpr : undefined id " << varId << endl;
00439       }
00440     }
00441   return hacheConstraintId++;
00442 }
00443 
00444 /*---------------------------------------------------------------------------------------*/
00445 
00452 //Attention: Contraint a mettre ici
00453 Constraint Model::Add( const ConstraintBuilder & c , const std::string & nom)
00454 {
00455   Constraint retour;
00456   if( c.IsBound() )  //La contrainte est une borne
00457   {
00458        NumVar var = (++c.expressions.begin())->nodeList.front().GetVariable();
00459 
00460        //La borne est de type: {value} {Operateur} {Variable} ou {Variable} {Operateur} {value}
00461        if(c.operateurs.size()==1)
00462        {
00463 
00464          float bound;
00465          bool prems = ( c.expressions.back().nodeList.front().GetVariable().GetModel() == 0 );
00466          //booleen servant a savoir si la variable est en premier ou pas
00467          //si elle est en premier
00468          if(prems)
00469             bound = c.expressions.back().nodeList.front().GetCoefficient().GetValue();
00470             //on récupere le coefficient de la seconde partie de l'expression qui est la borne supérieure
00471          else
00472             bound = c.expressions.front().nodeList.front().GetCoefficient().GetValue();
00473             //on récupere le coefficient de la premire partie de l'expression qui est la borne inférieure
00474          list<ConstraintBuilder::Operateur>::const_iterator op = c.operateurs.begin();
00475          //En cas de contraintes stricte il faut modifié le caractere des borne
00476          //suivant le type de contraintes
00477          switch( *op )
00478          {
00479            case ConstraintBuilder::INFSTRICT: //cas similaire à INFERIEUR
00480               if(prems)
00481                  var.SetUpperBoundStrict( true );
00482               else
00483                  var.SetLowerBoundStrict( true );
00484            case ConstraintBuilder::INFERIEUR:
00485               if(prems)
00486                  var.SetUpperBound( bound );
00487               else
00488                  var.SetLowerBound( bound );
00489            break;
00490            case ConstraintBuilder::SUPSTRICT: //cas similaire à SUPERIEUR
00491               if(!prems)
00492                  var.SetUpperBoundStrict( true );
00493               else
00494                  var.SetLowerBoundStrict( true );
00495            case ConstraintBuilder::SUPERIEUR:
00496              if(!prems)
00497                  var.SetUpperBound( bound );
00498               else
00499                  var.SetLowerBound( bound );
00500            break;
00501            default:
00502                  cerr << "Warning in Model::Add : wrong ConstraintBuilder::Operator for single constraint" << endl;
00503            break;
00504          }
00505        }
00506 
00507        //La Contrainte est de la forme {value} {Operateur} {variable} {Operateur} {value}
00508        if(c.operateurs.size()==2)
00509        {
00510          float lrB = c.expressions.front().nodeList.front().GetCoefficient().GetValue();
00511          //on récupere la borne inférieure
00512          float urB = c.expressions.back().nodeList.front().GetCoefficient().GetValue();
00513          //on récupere la borne supérieure
00514          list<ConstraintBuilder::Operateur>::const_iterator op = c.operateurs.begin();
00515          //on récupere l'opérateur de comparaison
00516          float swap;
00517          //En cas de contraintes superieure il faut inverser les bornes
00518          switch( *op )
00519          {
00520            case ConstraintBuilder::INFSTRICT:
00521              var.SetLowerBoundStrict( true );
00522            break;
00523            case ConstraintBuilder::INFERIEUR:
00524            break;
00525            case ConstraintBuilder::SUPSTRICT:
00526              var.SetUpperBoundStrict( true );
00527            case ConstraintBuilder::SUPERIEUR:
00528              swap = lrB;
00529              lrB = urB;
00530              urB = swap;
00531            break;
00532            default:
00533              cerr << "Warning in Model::Add : wrong ConstraintBuilder::Operator for double constraint" << endl;
00534            break;
00535          }
00536          ++op;
00537          //on récupere l'opérateur de comparaison suivant
00538          if( *op == ConstraintBuilder::INFSTRICT)
00539            var.SetUpperBoundStrict( true );
00540          if( *op == ConstraintBuilder::SUPSTRICT) 
00541            var.SetLowerBoundStrict( true );
00542          var.SetLowerBound( lrB );
00543          var.SetUpperBound( urB );
00544        }
00545   }
00546   //sinon c'est une contrainte generique
00547   else
00548   {
00549     if( c.operateurs.size() >=1 && c.operateurs.size() + 1 == c.expressions.size()  )
00550     {
00551         //La contrainte est valide
00552       list<Expr>::const_iterator exp = c.expressions.begin();
00553         list<Expr>::const_iterator exp2 = ++c.expressions.begin();
00554         list<ConstraintBuilder::Operateur>::const_iterator op = c.operateurs.begin();
00555 
00556         //Decompostion de la suite de contraintes
00557         while( exp2!=c.expressions.end() )
00558         {
00559           Expr tmp; //expressions temporaire qui va aider à séparer la chaine de contraintes
00560           ostringstream id;
00561           if(c.operateurs.size()!=1 || nom.length()== 0 )
00562              if( nom.length()== 0 )
00563                 id << "__c" << A.nbLignes+1;
00564              else
00565                 id << nom << A.nbLignes+1;
00566           else
00567               id << nom;
00568           string nom2 = id.str();
00569 
00570           tmp = *exp - *exp2;
00571           //la partie linéaire de la contrainte est le premier membre moins le second membre
00572           tmp.Simplify();
00573           //on simplifie
00574 
00575           VarId p;
00576           float coef = -(tmp.nodeList.front().GetVariable().GetModel()?0.0f:tmp.nodeList.front().GetCoefficient().GetValue());
00577           //on recupere le coefficient qui se trouve en premiere position dans l'expression
00578           //suivant le type de contrainte
00579           //on ajoute la partie linéaire à la matrice
00580           //et on créé la representation interne de la contrainte dans le vecteur de contrainte
00581           switch( *op )
00582           {
00583             case ConstraintBuilder::INFERIEUR:
00584                p = AddExpr( tmp, A );
00585                constraintMap[p] = InternalConstraint(InternalConstraint::INF,coef,0.0,0.0,nom2,false,false);
00586             break;
00587 
00588             case ConstraintBuilder::SUPERIEUR:
00589                p = AddExpr( tmp, A );
00590                constraintMap[p] = InternalConstraint(InternalConstraint::SUP,coef,0.0,0.0,nom2,false,false);
00591             break;
00592 
00593             case ConstraintBuilder::EGAL:
00594                p = AddExpr( tmp, A );
00595                constraintMap[p] = InternalConstraint(InternalConstraint::EGAL,coef,0.0,0.0,nom2,false,false);
00596             break;
00597 
00598             case ConstraintBuilder::INFSTRICT:
00599                p = AddExpr( tmp, A );
00600                constraintMap[p] = InternalConstraint(InternalConstraint::INFSTRICT,coef,0.0,0.0,nom2,false,false);
00601             break;
00602 
00603             case ConstraintBuilder::SUPSTRICT:
00604                p = AddExpr( tmp, A );
00605                constraintMap[p] = InternalConstraint(InternalConstraint::SUPSTRICT,coef,0.0,0.0,nom2,false,false);
00606             break;
00607 
00608             default:
00609               cerr << "Warning in Model::Add : wrong ConstraintBuilder::Operator" << endl;
00610               break;
00611           }
00612            ++exp2;++exp;++op;
00613            //on passe à  la contrainte suivante 
00614            retour = Constraint(*this,p);
00615         }
00616     }
00617     else
00618       cerr << "Warning in Model::Add : the ConstraintBuilder is bad structured" << endl;
00619   }
00620   return retour;
00621 }
00622 
00623 
00624 /*---------------------------------------------------------------------------------------*/
00625 
00631 std::ostream & Model::Out( std::ostream & flux, const std::string & newline )
00632 {
00633     flux << (isMax?"Maximize: ":"Minimize") << objectif << newline << endl << endl;
00634     flux << "A =" << newline << endl;
00635     A.Out();
00636     flux << "Matrice de taille: " << A.GetNbLignes() 
00637         << "x" << A.GetNbCols() << newline << endl;
00638     return flux;
00639 }
00640 
00641 
00642 /*---------------------------------------------------------------------------------------*/
00643 
00650 std::ostream& Model::SurchargeFlux(std::ostream& flux) const
00651 {
00652     flux << "\\" << problemName << endl;
00653 
00654     if( isMax)
00655         flux <<  "Maximize " << endl;
00656     else
00657         flux <<  "Minimize " << endl;
00658     flux << objectifName << (objectifName.length()?": ":" ") << objectif << endl;
00659 
00660     flux << endl << "Subject to" << endl;
00661 
00662     string op[]  = { "<=",">=","="," > "," < "};
00663 
00664 
00665     VarId p = A.nbLignes+1;
00666     bool normal = false;
00667 
00668     std::map<VarId,Paire>::const_iterator variable;
00669     std::map<VarId,InternalConstraint>::const_iterator constraint = constraintMap.end();
00670     std::map<VarId,std::string>::const_iterator comment = comments.begin();
00671 
00672     for(map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
00673                                                        iter != A.matrix.end();
00674                                                      ++iter)
00675     {
00676         unsigned i = iter->first.i; //colonne
00677         unsigned j = iter->first.j; //ligne attention au décalage d'indice avec tB
00678 
00679         variable  = unknowMap.find(VarId(i));
00680 
00681         if(j != p)  //nouvelle contrainte
00682         {
00683             if(constraint != constraintMap.end())
00684                 flux << op[constraint->second.type] << constraint->second.b << endl;
00685 
00686             constraint = constraintMap.find(j);
00687             p = constraint->first;
00688 
00689             while( comment != comments.end() && comment->first <= p)
00690             {
00691                 flux << "\\" << comment->second << endl;
00692                 ++comment;
00693             }
00694             if( constraint->second.name.length())
00695                 flux << constraint->second.name << ": ";
00696 
00697             normal = false;
00698         }
00699 
00700         float coeff = iter->second;
00701 
00702         if( normal )
00703         {
00704             if(coeff != 0.0f)
00705             {
00706                 if(coeff != 1.0f && coeff != -1.0f )
00707                         if( coeff > 0 )
00708                                flux  << "+" << coeff << variable->second.nom;
00709                         else
00710                                flux << coeff << variable->second.nom;
00711                 else
00712                         if( coeff == 1.0f )
00713                                flux  << "+" << variable->second.nom;
00714                         else
00715                                flux  << "-" << variable->second.nom;
00716             }
00717         }
00718         else
00719         {
00720             if(coeff != 0.0f)
00721             {
00722                 if(coeff != 1.0f && coeff != -1.0f )
00723                     flux  << coeff << variable->second.nom;
00724                 else
00725                     flux << (coeff == 1.0?"":"-") << variable->second.nom;
00726                 normal = true;
00727             }
00728         }
00729 
00730     }
00731     if(constraint != constraintMap.end())
00732         flux << op[constraint->second.type] << constraint->second.b << endl;
00733 
00734     while( comment != comments.end() )
00735     {
00736         flux << "\\" << comment->second << endl;
00737         ++comment;
00738     }
00739 
00740 
00741     bool bounds = false;
00742     for(std::map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
00743                                               variable != unknowMap.end();
00744                                             ++variable)
00745     {
00746         bool lbs = variable->second.variable.IsLowerBoundStrict();
00747         bool ubs = variable->second.variable.IsUpperBoundStrict();
00748         float lb = variable->second.variable.GetLowerBound();
00749         float ub = variable->second.variable.GetUpperBound();
00750 
00751         if( variable->second.variable.GetType() != MuteVar::BOOL)
00752         {
00753             if( (lb != 0 || ub != Infinity) && bounds == false  )
00754             {
00755                flux << endl << "Bounds" << endl;
00756                  bounds = true;
00757               }
00758             if( bounds == true )
00759             {
00760                 if(lb == -Infinity && ub == Infinity)
00761                     flux <<  variable->second.nom << " Free";
00762                 else
00763                 {
00764                    if(lb!=0.0)
00765                    {
00766                        if( lb != -Infinity )
00767                             flux << lb << (lbs?" < ":"<=");
00768                         else
00769                             flux << "-Inf" << " < ";
00770                     }
00771 
00772                     if(ub!=Infinity)
00773                         flux << variable->second.nom << (ubs?" < ":" <= ") << ub;
00774                     else
00775                         if(lb!=0.0)
00776                             flux << variable->second.nom;
00777                 }
00778                 if( lb!=0.0 || ub!=Infinity )
00779                   flux << endl;
00780             }
00781         }
00782     }
00783 
00784     bool generals = false;
00785     for(std::map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
00786                                             variable != unknowMap.end();
00787                                           ++variable)
00788     {
00789         if(variable->second.variable.GetType() == MuteVar::INT)
00790         {
00791             if(generals)
00792                 flux << variable->second.nom << endl;
00793             else
00794             {
00795                 flux << endl  << "Generals" << endl
00796                      << variable->second.nom << endl;
00797                 generals = true;
00798             }
00799         }
00800     }
00801 
00802 
00803     bool binaries = false;
00804     for(std::map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
00805                                             variable != unknowMap.end();
00806                                           ++variable)
00807     {
00808         if(variable->second.variable.GetType() == MuteVar::BOOL)
00809         {
00810             if(binaries == true)
00811                 flux << variable->second.nom << endl;
00812             else
00813             {
00814                 flux << endl << endl << "Binaries" << endl
00815                      << variable->second.nom << endl;
00816                 binaries = true;
00817             }
00818         }
00819     }
00820   
00821     flux<< endl << endl << "End" << endl;
00822 
00823     return flux;
00824 }
00825 
00829 std::ostream & Model::OutDimensions( std::ostream & flux, const std::string & newline)
00830 {
00831    flux << "Tailles des matrices:" << newline << endl;
00832    flux << "   Matrice des inégalités: " << A.GetNbLignes()
00833         << "x" << A.GetNbCols() << newline << endl
00834         << "       taux d'occupation: "
00835         << (A.GetNbLignes()!=0.0f?A.matrix.size()*100.0/(1.0*A.nbLignes*A.nbCols):0)
00836         << "% "   << endl << newline;
00837    flux << "Nombre de Variables:  " << unknowMap.size() << newline << endl;
00838    flux << "Nombre de Contraintes:  " << constraintMap.size() << newline << endl;
00839    flux << "Taille de la fonction objectif:  " << objectif.Size() << newline << endl;
00840    return flux;
00841 }
00842 
00843 /*---------------------------------------------------------------------------------------*/
00844 
00850 std::ostream& Model::SurchargeFluxRelaxed(std::ostream& flux) const
00851 {
00852 
00853   flux << "\\" << problemName << endl;
00854 
00855 /*  list<ExprNode>::const_iterator src = objectif.nodeList.begin();
00856 
00857   for(;src!=objectif.nodeList.end();++src)
00858     cout << "+" << src->GetCoefficient() << "*" << src->GetVariable().GetName()
00859          << "*" << src->GetLagrangianParam().GetValue();
00860     cout << endl;
00861 */
00862     if( isMax)
00863         flux <<  "Maximize " << endl;
00864     else
00865         flux <<  "Minimize " << endl;
00866     flux << "\\Constante à ajouter: " << objectif.GetConstant( true ) << endl;
00867     flux << objectifName << (objectifName.length()?": ":" ") << objectif << endl;
00868 
00869     flux << endl << "Subject to" << endl;
00870 
00871     string op[]  = { "<=",">=","="," > "," < "};
00872 
00873     VarId p = A.nbLignes+1;
00874     bool normal = false;
00875 
00876     map<VarId,Paire>::const_iterator variable;
00877     map<VarId,InternalConstraint>::const_iterator constraint = constraintMap.end();
00878     map<VarId,std::string>::const_iterator comment = comments.begin();
00879 
00880     for(map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
00881                                                        iter != A.matrix.end();
00882                                                      ++iter)
00883     {
00884         unsigned i = iter->first.i; //colonne
00885         unsigned j = iter->first.j; //ligne
00886 
00887         variable  = unknowMap.find(VarId(i));
00888 
00889         if(j != p)  //nouvelle contrainte
00890         {
00891              if(  constraint != constraintMap.end()
00892              && !constraint->second.isLagrangianParamActive )
00893                 flux << op[constraint->second.type] << constraint->second.b << endl;
00894 
00895             constraint = constraintMap.find(j);
00896             p = constraint->first;
00897 
00898             while( comment != comments.end() && comment->first <= p)
00899             {
00900                 flux << "\\" << comment->second << endl;
00901                 ++comment;
00902             }
00903 
00904             if( constraint->second.name.length() && !constraint->second.isLagrangianParamActive)
00905                 flux << constraint->second.name << ": ";
00906 
00907             normal = false;
00908         }
00909 
00910         float coeff = iter->second;
00911 
00912         if( !constraint->second.isLagrangianParamActive )
00913         {
00914             if( normal )
00915             {
00916                 if(coeff != 0.0f)
00917                 {
00918                     if(coeff != 1.0f && coeff != -1.0f )
00919                             if( coeff > 0 )
00920                                    flux  << "+" << coeff << variable->second.nom;
00921                             else
00922                                    flux << coeff << variable->second.nom;
00923                     else
00924                             if( coeff == 1.0f )
00925                                    flux  << "+" << variable->second.nom;
00926                             else
00927                                    flux  << "-" << variable->second.nom;
00928                 }
00929             }
00930             else
00931             {
00932                 if(coeff != 0.0f)
00933                 {
00934                     if(coeff != 1.0f && coeff != -1.0f )
00935                         flux  << coeff << variable->second.nom;
00936                     else
00937                         flux << (coeff == 1.0?"":"-") << variable->second.nom;
00938                     normal = true;
00939                 }
00940             }
00941         }
00942 
00943     }
00944     if(  constraint != constraintMap.end()
00945      && !constraint->second.isLagrangianParamActive )
00946         flux << op[constraint->second.type] << constraint->second.b << endl;
00947 
00948     while( comment != comments.end() )
00949     {
00950         flux << "\\" << comment->second << endl;
00951         ++comment;
00952     }
00953 
00954 
00955   bool bounds = false;
00956   for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
00957                                        variable != unknowMap.end();
00958                                      ++variable)
00959   {
00960     bool lbs = variable->second.variable.IsLowerBoundStrict();
00961     bool ubs = variable->second.variable.IsUpperBoundStrict();
00962     float lb = variable->second.variable.GetLowerBound();
00963     float ub = variable->second.variable.GetUpperBound();
00964 
00965     if( variable->second.variable.GetType() != MuteVar::BOOL)
00966     {
00967       if( (lb != 0 || ub != Infinity) && bounds == false )
00968       {
00969         flux << endl << "Bounds" << endl;
00970         bounds = true;
00971       }
00972 
00973       if( bounds == true )
00974       {
00975         if(lb == -Infinity && ub == Infinity)
00976             flux <<  variable->second.nom << " Free";
00977         else
00978         {
00979             if(lb!=0.0)
00980             {
00981                if( lb != -Infinity )
00982                  flux << lb << (lbs?" < ":"<=");
00983                else
00984                  flux << "-Inf" << " < ";
00985             }
00986 
00987             if(ub!=Infinity)
00988                flux << variable->second.nom << (ubs?" < ":"<=") << ub;
00989             else
00990                if(lb!=0.0)
00991                  flux << variable->second.nom;
00992         }
00993         if( lb!=0.0 || ub!=Infinity )
00994           flux << endl;
00995       }
00996     }
00997   }
00998 
00999   bool generals = false;
01000   for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
01001                                        variable != unknowMap.end();
01002                                      ++variable)
01003   {
01004      if(variable->second.variable.GetType() == MuteVar::INT && !variable->second.variable.IsRelaxed())
01005      {
01006         if( generals == true )
01007           flux << variable->second.nom << endl;
01008         else
01009         {
01010             flux << endl  << "Generals" << endl
01011                  << variable->second.nom << endl;
01012             generals = true;
01013         }
01014      }
01015   }
01016 
01017 
01018   bool binaries = false;
01019   for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
01020                                        variable != unknowMap.end();
01021                                      ++variable)
01022   {
01023      if(variable->second.variable.GetType() == MuteVar::BOOL && !variable->second.variable.IsRelaxed())
01024      {
01025         if(binaries == true )
01026           flux << variable->second.nom << endl;
01027         else
01028         {
01029             flux << endl << endl << "Binaries" << endl
01030                  << variable->second.nom << endl;
01031             binaries = true;
01032         }
01033      }
01034   }
01035 
01036   flux<< endl << endl << "End" << endl;
01037 
01038   return flux;
01039 }
01040 
01046 std::ostream& operator<<(std::ostream& flux,const Model& m)
01047 {
01048   if( m.IsRelaxed() )
01049      return m.SurchargeFluxRelaxed(flux);
01050   else
01051      return m.SurchargeFlux(flux);
01052 
01053 }
01054 
01055 
01056 /*-----------------------------------------------------------------------------------------------*/
01057 
01063 std::ostream & Model::SurchargeMPSFlux(std::ostream & flux,bool verbose) const
01064 {
01065   string pbName(problemName,0,8);
01066   if( problemName.length() >= 8 )
01067   {
01068     cerr << "Warning in Model::SurchargeMPSFlux : the probleme name is too long for MPS" << endl;
01069   }
01070   string::size_type endline = pbName.find('\n');
01071   if( endline != string::npos && verbose==true )
01072   {
01073     cerr << "Warning in Model::SurchargeMPSFlux : the probleme name is reduced to a single line" << endl;
01074   }
01075   pbName = pbName.substr(0,endline);
01076   flux << "NAME          " << pbName << endl;
01077   
01078   string objName(objectifName,0,8);
01079   if( objectifName.length() > 8 && verbose==true )
01080   {
01081     cerr << "Warning in Model::SurchargeMPSFlux : the objectif name is too long for MPS format" << endl;
01082   }
01083   
01084   flux << "ROWS" << endl << " N  " << objName << endl;
01085   map<VarId, InternalConstraint>::const_iterator constraint;
01086   string strType[5] = {" L  "," G  "," E  "," L  "," G  "};
01087   for( constraint = constraintMap.begin(); constraint != constraintMap.end(); ++constraint )
01088   {
01089     string strConstraintName(constraint->second.name);
01090     if( strConstraintName.length() > 8 )
01091     {
01092       if( verbose==true )
01093         cerr << "Warning in Model::SurchargeMPSFlux : The constraint " << strConstraintName << " has a too long name for the MPS format. This name will be replaced by ";
01094       strConstraintName = Nom("_",constraint->first)();
01095       if( verbose==true )
01096         cerr << strConstraintName << "." << endl;
01097    }
01098      flux << strType[int(constraint->second.type)] << strConstraintName << endl;
01099   }
01100   
01101   map< VarId, ostringstream * > tempM;
01102   map< VarId, ostringstream *>::iterator iterStr;
01103   list< ostringstream * > generals[2];
01104   list< ostringstream * >::iterator iterlistStr;
01105   for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
01106                                        variable != unknowMap.end();
01107                                      ++variable)
01108   {
01109     ostringstream * nom = new ostringstream;
01110     string variableName( variable->second.nom);
01111     if( variableName.length() > 8 )
01112     {
01113       if( verbose==true )
01114         cerr << "Warning in Model::SurchargeMPSFlux : The variable " << variableName << " has a too long name for the MPS format. This name will be replaced by ";
01115       variableName = Nom("_",variable->first)();
01116       if( verbose==true )
01117         cerr << variableName << "." << endl;
01118     }
01119     *nom << variableName;
01120     tempM[variable->first] = nom;
01121     unsigned i = (variable->second.variable.GetType() == MuteVar::INT?0:1);
01122     generals[i].push_back(nom);
01123   }
01124 
01125    std::list<ExprNode>::const_iterator iter;
01126    float signe = (isMax?-1.0:1.0);
01127 
01128    for( iter = objectif.nodeList.begin(); iter != objectif.nodeList.end(); ++iter)
01129    {
01130       NumVar varTmp = iter->GetVariable();
01131       VarId varId = (varTmp.GetModel()?varTmp.GetVarId():0);
01132       
01133       iterStr = tempM.find(varId);
01134       if( iterStr != tempM.end() )
01135       {
01136          float coef = iter->GetCoefficient().GetValue();
01137          *(iterStr->second)  << " " << objName << " " << signe*coef;
01138       }
01139    }
01140 
01141   VarId p = A.nbLignes+1;
01142   string strConstraintName;
01143   for(map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
01144                                                      iter != A.matrix.end();
01145                                                    ++iter)
01146   {
01147       unsigned i = iter->first.i; //colonne
01148       unsigned j = iter->first.j; //ligne
01149 
01150       if(j != p)  //nouvelle contrainte
01151       {
01152           constraint = constraintMap.find(j);
01153           p = constraint->first;
01154 
01155           strConstraintName = constraint->second.name;
01156           if( strConstraintName.length() > 8 )
01157           {
01158             strConstraintName = Nom("_",j)();
01159           }
01160       }
01161 
01162       float coeff = iter->second;
01163 
01164       iterStr = tempM.find((VarId)i);
01165       if( iterStr != tempM.end() )
01166       {
01167          *(iterStr->second)  << " " << strConstraintName << " " << coeff;
01168       }
01169   }
01170 
01171   flux << "COLUMNS" << endl;
01172   string markers[2];
01173   if( generals[0].size() != 0 )
01174   {
01175     markers[0] = "    MARK0000  'MARKER'                 'INTORG'";
01176     markers[1] = "    MARK0000  'MARKER'                 'INTEND'";
01177   }
01178   else
01179   {
01180     markers[0] = "";
01181     markers[1] = "";
01182   }
01183 
01184 
01185   for( unsigned i=0; i < 2; ++ i)
01186   {
01187     flux << markers[i] << endl;
01188     for( iterlistStr = generals[i].begin(); iterlistStr != generals[i].end();  ++iterlistStr )
01189     {
01190       istringstream chaine((*iterlistStr)->str());
01191       string variable;
01192       string row;
01193       string value;
01194       string row2;
01195       string value2;
01196   
01197       chaine >> variable;
01198       
01199       variable+=string(8-variable.length(),' ') ;
01200   
01201       while( chaine >> row >> value )
01202       {
01203         if( !(chaine >> row2 >> value2) )
01204         {
01205           row2="";
01206           value2="";
01207         }
01208         row+=string(8-row.length(),' ') ;
01209         value+=string(14-value.length(),' ') ;
01210         row2+=string(8-row2.length(),' ') ;
01211         value2+=string(14-value2.length(),' ') ;
01212         flux << "    " << variable
01213              << "  " << row
01214              << "  " << value
01215              << "  " << row2
01216              << "  " << value2
01217              << endl;
01218       }
01219       delete *iterlistStr;
01220     }
01221   }
01222 
01223   flux << "RHS" << endl;
01224   for( constraint = constraintMap.begin(); constraint != constraintMap.end(); ++constraint )
01225   {
01226     string strConstraintName(constraint->second.name);
01227     if( strConstraintName.length() > 8 )
01228     {
01229       strConstraintName = Nom("_",constraint->first)();
01230     }
01231     strConstraintName+=string(8-strConstraintName.length(),' ');
01232     flux << "    rhs       " << strConstraintName << "  " << constraint->second.b << endl;
01233   }
01234 
01235   flux << "BOUNDS" << endl;
01236   for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
01237                                        variable != unknowMap.end();
01238                                      ++variable)
01239   {
01240     float lb = variable->second.variable.GetLowerBound();
01241     float ub = variable->second.variable.GetUpperBound();
01242     string variableName( variable->second.nom);
01243     if( variableName.length() > 8 )
01244     {
01245       variableName = Nom("_",variable->first)();
01246     }
01247     variableName+=string(8-variableName.length(),' ');
01248 
01249     if( variable->second.variable.GetType() == MuteVar::BOOL )
01250     {
01251           flux << " BV bnd       " << variableName  << endl;
01252     }
01253     else
01254     {
01255         if( lb != -Infinity || ub != Infinity )
01256       {
01257         if( lb != -Infinity  )
01258         {
01259           if( !(lb == 0 && ub == Infinity) )
01260           {
01261             flux << " LO bnd       " << variableName << "  " << lb << endl;
01262           }
01263         }
01264         else
01265         {
01266           flux << " MI bnd       " << variableName << endl;
01267         }
01268         if( ub != Infinity )
01269         {
01270           flux << " UP bnd       " << variableName << "  " << ub << endl;
01271         }
01272       }
01273       else
01274       {
01275           flux << " FR bnd       " << variableName  << endl;
01276       }
01277     }
01278   }
01279   flux << "ENDATA" << endl;
01280 
01281   return flux;
01282 }
01283 
01289 std::ostream & ToMPS(std::ostream& flux, const Model& m, bool verbose)
01290 {
01291   return m.SurchargeMPSFlux(flux,verbose);
01292 }
01293 
01294 /*-----------------------------------------------------------------------------------------------*/
01299 Constraint Model::GetConstraint(VarId id) const
01300 {
01301     map<VarId,InternalConstraint>::const_iterator constraint;
01302     constraint = constraintMap.find(id);
01303     //on cherche la contraint
01304     if(constraint != constraintMap.end())
01305     {
01306         return Constraint(*this,id);
01307     }
01308     else
01309         cerr << "Warning in Model::GetConstraint : undefined id " << id << endl;
01310     return Constraint();
01311 }
01312 
01318 bool Model::RelaxConstraint( VarId id, float lagrangianValue )
01319 {
01320     map<VarId,InternalConstraint>::iterator constraint;
01321     //on va chercher la contrainte d'identifiant id
01322     constraint = constraintMap.find(id);
01323     //si on la trouve
01324     if(constraint != constraintMap.end())
01325     {
01326         isRelaxed = true;
01327         //on indique au modele qu'il est relaxee
01328         constraint->second.lagrangianValue = lagrangianValue;
01329         //on attribue la valeur du lagrangien
01330         //si elle n'est pas -infini
01331         if(lagrangianValue != -Infinity)
01332            constraint->second.isLagrangianParamDefined = true ;
01333            //le multiplicateur de lagrange est defini
01334         constraint->second.isLagrangianParamActive = true;
01335         //le multiplicateur de lagrange devient actif
01336         objectif-=GetRelaxedConstraintExpr(id);
01337         //on modifie la fonction objectif
01338         objectif.isParametric = true;
01339         //on lui indique qu'elle depend maintenant d'un multiplicateur de lagrange
01340         objectif.sansConstantes = true;
01341         //on lui indique de ne pas tenir compte des constantes qu'elle contient
01342         return true;
01343     }
01344     else
01345        cerr << "Warning in Model::RelaxConstraint: undefined constraint id " << id << endl;
01346     return false;
01347 }
01348 
01355 float Model::EvalConstraint(VarId id ) const
01356 {
01357   float ret = 0.0f;
01358 
01359   unsigned p = id;
01360   std::map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
01361   while(iter != A.matrix.end())
01362   {
01363      unsigned i = iter->first.i; //indice de colonne
01364      unsigned j = iter->first.j; //indice de ligne
01365 
01366      //si on est sur la ligne de la contrainte
01367      if(j == p)
01368      {
01369          ret += iter->second*GetMuteVar(i).GetValue();
01370          //on ajoute le produit du coefficient et de la valeur
01371          //de la variable au reel de retour
01372      }
01373      else
01374      if(j>p)
01375        break;
01376        //si on depasse la contrainte on quitte
01377 
01378      ++iter;
01379   }
01380   return ret;
01381 }
01382 
01388 Expr Model::GetRelaxedConstraintExpr( VarId id , bool relaxed)
01389 {
01390 
01391   Expr ret;
01392   //expression de retour
01393 
01394   LagrangianParam mult(*this, id);
01395 
01396   if(!relaxed)
01397     mult = LagrangianParam();
01398 
01399   //multiplicateur de lagrange
01400   std::map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
01401   //on parcourt la matrice creuse
01402   while(iter != A.matrix.end())
01403   {
01404      unsigned i = iter->first.i; //indice de colonne
01405      unsigned j = iter->first.j; //indice de ligne
01406 
01407      //si on est sur la bonne ligne
01408      if(j == id)
01409      {
01410          ret.ASS( iter->second, NumVar(this,i), mult);
01411          //on ajoute le produit du coefficient et de la variable à l'expression
01412      }
01413      else
01414      if(j>id)
01415        break;
01416        //si on depasse la ligne de la contrainte on quitte la boucle
01417      ++iter;
01418   }
01419   float b = 0;
01420   if( ret.Size() != 0)
01421      b = constraintMap.find(id)->second.b;
01422   ret.ASS( - b,NumVar(),mult);
01423   ret.isParametric = true;
01424   return ret;
01425 }
01426 
01434 bool Model::Relax(const std::string & name, float lagrangianValue )
01435 {
01436    VarId id;
01437    //si on arrive a recuperer l'identifiant de la contrainte
01438    if((id=GetConstraintId(name)))
01439      return RelaxConstraint(id,lagrangianValue);
01440      //on la relaxe
01441    else
01442      return false;
01443 }
01444 
01445 
01446 /*-----------------------------------------------------------------------------------------------*/
01454 bool Model::RelaxInt2Float( NumVar numVar )
01455 {
01456   VarId id = numVar.GetVarId();
01457   //on recupere l'identifiant de la variable
01458 
01459   //si l'identifiant n'est pas nul
01460   if(id)
01461      unknowMap.find(id)->second.variable.SetRelaxed();
01462      //on relaxe la variable correspondante
01463   else
01464     //sinon pour chaque variables
01465     for(map<VarId,Paire>::iterator variable  = unknowMap.begin();
01466                                         variable != unknowMap.end();
01467                                       ++variable)
01468     {
01469         //on regarde si elle est de type entier
01470         if(variable->second.variable.GetType()==MuteVar::INT)
01471         {
01472             variable->second.variable.SetRelaxed();
01473             //si oui on la relaxe
01474         }
01475     }
01476   return true;
01477 }
01478 
01486 bool Model::RelaxBool2Float( NumVar numVar )
01487 {
01488   VarId id = numVar.GetVarId();
01489   //On recupere l'identifiant de la variable
01490 
01491   //si l'identifiant n'est pas nul
01492   if(id)
01493      unknowMap.find(id)->second.variable.SetRelaxed();
01494      //on relaxe la varaiable
01495   else
01496     //sinon pour chaque variable
01497     for(map<VarId,Paire>::iterator variable  = unknowMap.begin();
01498                                         variable != unknowMap.end();
01499                                       ++variable)
01500     {
01501         //si elle est du type booleen
01502         if(variable->second.variable.GetType()==MuteVar::BOOL)
01503         {
01504             variable->second.variable.SetRelaxed();
01505             //on la relaxe
01506         }
01507     }
01508   return true;
01509 }
01510 
01511 
01515 void Model::UnrelaxModel()
01516 {
01517    objectif.Simplify(false);
01518    objectif.isParametric = false;
01519    objectif.sansConstantes = false;
01520    //on reinitialise la fonction objectif
01521 
01522    //Pour toutes les variables
01523    for(map<VarId,Paire>::iterator variable  = unknowMap.begin();
01524                                   variable != unknowMap.end();
01525                                 ++variable)
01526         variable->second.variable.SetRelaxed(false);
01527         //on leur enleve le caractere relachee
01528 
01529    //pour toutes les contraintes
01530    for(map<VarId,InternalConstraint>::iterator constraint  = constraintMap.begin();
01531                                                constraint != constraintMap.end();
01532                                              ++constraint)
01533    {
01534       constraint->second.isLagrangianParamActive = false;
01535       //on desactive leur multiplicateur de lagrange
01536    }
01537    isRelaxed=false;
01538 }
01539 
01540 
01541 //-------------------------
01542 // Interface des Solvers
01543 //-------------------------
01544 
01546 void  Model::SetAPI(API _API)
01547 {
01548     solverAPI.SetAPI(_API);
01549 }
01550 
01552 float Model::Solve()
01553 {
01554     float val;
01555 
01556     ofstream out(solverAPI.GetfLP());
01557     if(!out.is_open())
01558        throw runtime_error("Model::Solve() : I/O Error");
01559     //on declare un fichier .lp temporaire de sortie
01560     out << (*this);
01561     //on met le modele dans ce fichier sous la bonne forme
01562     out.close();
01563     //on ferme ce fichier pour eviter des problemes de lecture
01564 
01565     solverAPI.SetMIP( MIPVar == 0);
01566 
01567     val = solverAPI.Solve();
01568     isSolved = solverAPI.IsSolved();
01569     isOptimal = solverAPI.IsOptimal();
01570     //On appelle le solveur sur le fichier LP
01571 
01572     // appel de SetNumVarValues
01573     // pour stocker les résultat des varialbes
01574     SetNumVarValues(solverAPI.GetNumVarNoms(), solverAPI.OutNumVarValues());
01575     // appel de SetConstraintValues
01576     // pour stocker les résultat des contraintes
01577     SetConstraintValues( solverAPI.GetConstraintNoms(), solverAPI.OutConstraintValues() );
01578     //on sauve la valeur de la fonction objecitf
01579     objectifActivity = val + objectif.GetConstant();
01580     return objectifActivity;
01581 }
01582 
01588 void Model::GetInfluentLagrangianParam( list<LagrangianParam> & listViolated, list<LagrangianParam> & listSlacked)
01589 {
01590      map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01591      //Pour toutes les contraintes
01592      for(;constraint != constraintMap.end(); ++constraint)
01593      {
01594           float ecart = constraint->second.b - constraint->second.activity;
01595           //on calcule la variable d'écart
01596           if( ecart < 0 )
01597              listViolated.push_back( LagrangianParam(*this,constraint->first) );
01598              //la contrainte est violée
01599           if( ecart > 0 )
01600              listSlacked.push_back( LagrangianParam(*this,constraint->first) );
01601              //la contrainte est lache
01602      }
01603 }
01604 
01608 std::vector<LagrangianParam> Model::GetAllLagrangianParams( )
01609 {
01610     vector<LagrangianParam> retour;
01611     //le vecteur de retour
01612     map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01613     //on parcourt le map des contraintes
01614     for(;constraint != constraintMap.end(); ++constraint)
01615     {
01616         retour.push_back( LagrangianParam(*this,constraint->first) );
01617         //on ajoute le lagrangien de chaque contrainte au vecteur
01618     }
01619     return retour; 
01620 }
01621 
01627 void Model::SetNumVarValues(const list<string> & noms, const list<float> & values)
01628 {
01629    map<string,float> resultats;
01630    //ce map permet de gagner du temps dans la recherche sur la liste de noms
01631    //il permet de passer d'une complexite en O(n*n) à O(n*Log(n))
01632    //il fait correspondre une valeur à un nom de contrainte
01633 
01634    //si le nombre de noms correspond au nombre de valeurs
01635    if(noms.size() == values.size())
01636    {
01637        //on construit le map des résultats d'execution
01638        list<string>::const_iterator iterNoms = noms.begin();
01639        //iterateur sur la liste de noms
01640        list<float>::const_iterator iterValues = values.begin();
01641        //iterateur sur la liste de valeurs
01642 
01643        //on parcout les deux listes en meme temps
01644        //sachant qu'on est sur qu'elle font la même taille
01645        while( iterNoms != noms.end() )
01646        {
01647           resultats[*iterNoms] = *iterValues;
01648           //on cree le couple ( nom, valeur )
01649           ++iterNoms;
01650           ++iterValues;
01651           //on avance dans les deux listes
01652        }
01653 
01654        map<string,float>::const_iterator iter;
01655        //on parcourt le map de variables
01656        for(map<VarId,Paire>::iterator variable  = unknowMap.begin();
01657                                       variable != unknowMap.end();
01658                                     ++variable)
01659        {
01660          iter = resultats.find(variable->second.nom);
01661          //on cherche si le nom de la variable est dans le map de resultat
01662          if( iter != resultats.end() )
01663             variable->second.variable = iter->second;
01664             //si oui on attribue la valeur
01665          else
01666             variable->second.variable = 0;
01667             //sinon on la met à nul
01668        }
01669    }
01670 }
01671 
01677 void Model::SetConstraintValues(const std::list<std::string> & noms, const std::list<float> & values)
01678 {
01679    map<string,float> resultats;
01680    //ce map permet de gagner du temps dans la recherche sur la liste de noms
01681    //il permet de passer d'une complexite en O(n*n) à O(n*Log(n))
01682    //il fait correspondre une valeur à un nom de contrainte
01683 
01684    //si le nombre de noms correspond au nombre de valeurs
01685    if(noms.size() == values.size())
01686    {
01687        //on construit le map des résultats d'execution
01688        list<string>::const_iterator iterNoms = noms.begin();
01689        //iterateur sur la liste de noms
01690        list<float>::const_iterator iterValues = values.begin();
01691        //iterateur sur la liste de valeurs
01692 
01693        //on parcout les deux listes en meme temps
01694        //sachant qu'on est sur qu'elle font la même taille
01695        while( iterNoms != noms.end() )
01696        {
01697           resultats[*iterNoms] = *iterValues;
01698           //on cree le couple ( nom, valeur )
01699           ++iterNoms;
01700           ++iterValues;
01701           //on avance dans les deux listes
01702        }
01703 
01704        map<string,float>::iterator trouve;
01705        map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01706        //on parcourt le map des contraintes
01707        for(;constraint != constraintMap.end(); ++constraint)
01708        {
01709             trouve = resultats.find(constraint->second.name);
01710             //si on trouve le nom de la contrainte dans le map de resultats
01711             if( trouve != resultats.end())
01712                 constraint->second.activity = trouve->second;
01713                 //on lui attribue sa valeur
01714             else
01715                 constraint->second.activity = EvalConstraint(constraint->first);
01716                 //sinon on la calcule
01717        }
01718    }
01719    else
01720    {
01721       cerr << "Warning in Model::SetConstraintValues : list dimension problem, ";
01722       if( noms.size() <= values.size() )
01723           cerr << "the first param is too large" << endl;
01724       else
01725           cerr << "the second param is too large" << endl;
01726    }
01727 
01728 }
01729 
01733 std::ostream & Model::OutNumVarValues( bool withoutNullValue,std::ostream & flux, const std::string & newline) const
01734 {
01735     float t=0.0;
01736     string strInf = "Infinity";
01737     if( newline == "<br/>")
01738       strInf = "<em>oo</em>";
01739     else if( newline == "\\\\")
01740            strInf = "$\\infty$";
01741 
01742 
01743     flux << "Valeurs des variables (type et domaine de définition):" << newline << endl;
01744     //on parcourt le map des variables et on affiche celles qui sont non nulles
01745     //s'il y a l'option withoutNullValue
01746     for(map<VarId,Paire>::const_iterator variable  = unknowMap.begin();
01747                                           variable != unknowMap.end();
01748                                         ++variable)
01749     {
01750         if ( (t = (variable->second.variable.GetValue())) || !withoutNullValue)
01751         {
01752             int n=1,s=1;
01753             float e=0;
01754             float residu=0.0;
01755             unsigned d=1;
01756             bool aviableResidu = false;
01757 
01758             if (isFract==true)
01759             {
01760                s = (t<0.0?-1:1);
01761                e = floor(t);
01762                residu = t - e;
01763                aviableResidu = _fract.Approx(residu,n,d);
01764             }
01765             flux << variable->second.nom << " = ";
01766              if (isFract==true && aviableResidu==true)
01767              {
01768                if (s<0)
01769                   flux << '-' << (e!=0?e:' ') << '-' << n<<'/'<<d;
01770                else
01771                   flux << (e!=0?e:' ') << '+' << n << '/' << d;
01772              }
01773              else
01774                flux << t;
01775             // Affichage des bornes
01776             float uB = variable->second.variable.GetUpperBound();
01777             float lB = variable->second.variable.GetLowerBound();
01778             ostringstream sstr_lB; sstr_lB << lB;
01779             ostringstream sstr_uB; sstr_uB << uB;
01780             string type;
01781 
01782             switch(variable->second.variable.GetType())
01783             {
01784               case MuteVar::INT:   type = "INT";   break;
01785               case MuteVar::FLOAT: type = "FLOAT"; break;
01786               case MuteVar::BOOL:  type = "BOOL";  break;
01787               default:
01788                     cerr << "Warning in Model::OutNumVarValues : Error type of variable in switch statement " << endl;
01789                 break;
01790             }
01791 
01792             flux << "  ........ "<< type <<" ....... [" << (lB==-Infinity?"-"+strInf : sstr_lB.str()) << ',' << (uB==Infinity ? "+"+strInf : sstr_uB.str()) << ']';
01793             flux << newline << endl;
01794         }
01795     }
01796     return flux;
01797 }
01798 
01800 std::ostream & Model::OutConstraintValues(std::ostream & flux, const std::string & newline ) const
01801 {
01802      flux << "Caracteristiques des constraintes (si non toutes saturées): " << newline << endl;
01803      map<VarId,InternalConstraint>::const_iterator constraint = constraintMap.begin();
01804      //on parcourt le map de contraintes
01805      string op[]  = { "<=",">=","=",">","<"};
01806 
01807      for(;constraint != constraintMap.end(); ++constraint)
01808      {
01809             //on affiche la valeur de la contrainte apres execution
01810 
01811             float ecart = constraint->second.b - constraint->second.activity;
01812             if(  constraint->second.type == InternalConstraint::SUP
01813               || constraint->second.type == InternalConstraint::SUPSTRICT )
01814                 ecart = -ecart;
01815 
01816 
01817             // Conversion en fraction
01818             int n=1,s=1;
01819             float e=0;
01820             float residu=0.0;
01821             unsigned d=1;
01822             bool aviableResidu = false;
01823 
01824             if (isFract==true) 
01825             {
01826                s = (ecart<0.0?-1:1);
01827                e = floor(ecart);
01828                residu = (s<0 ? (-ecart)-e : ecart-e);
01829                aviableResidu = _fract.Approx(residu,n,d);
01830             }
01831             //on regarde la variable d'écart et on étudie les trois cas qui se présentent
01832             if ( -1e-10 >= ecart || ecart >= 1e-10)
01833             {
01834                 flux << constraint->second.name << " = " << constraint->second.activity;
01835 
01836                 if( ecart > 0 ) {
01837                    if (isFract==true && aviableResidu==true)
01838                    {
01839                      if (s<0)
01840                         flux << (e!=0.0?'-'<<int(e):' ') << '-' << n<<'/'<<d;
01841                      else
01842                         flux << (e!=0.0?e:' ') << '+' << n << '/' << d;
01843                    }
01844                    else
01845                      flux << " " <<op[constraint->second.type] << " "
01846                      << constraint->second.b << " ... non saturee ecart : " << ecart
01847                      << newline << endl;
01848                 }
01849                 else {
01850                    if (isFract==true && aviableResidu==true)
01851                    {
01852                      flux << "contrainte ecart: ";
01853                      if (s<0)
01854                         flux << (e!=0.0?'-'<<int(e):' ') << '-' << n<<'/'<<d;
01855                      else
01856                         flux << (e!=0.0?e:' ') << '+' << n << '/' << d;
01857                    }
01858                    else
01859                      flux << " " <<op[constraint->second.type] << " "
01860                      << constraint->second.b << " ... violee ecart : " << ecart
01861                      << newline << endl;
01862                 }
01863                 
01864             }
01865      }
01866      return flux;
01867 }
01868 
01874 bool Model::LoadLP(const std::string& _name, bool verbose)
01875 {
01876     FichierLP file;
01877     //on déclare un fichier LP source
01878 
01879     //si on ne reussi pas à charger le fichier LP
01880     if(!file.Open(_name.c_str()))
01881     {
01882         cerr << "Warning in Model::LoadLP : I/O error in the opening of " << _name << endl;
01883         return false;
01884         //on quitte
01885     }
01886     
01887     //sinon on charge le modèle à partir du fichier LP
01888     if( file >> (*this) )
01889     {
01890         //si le flag d'affichage est vrai
01891         if(verbose == true)
01892         {
01893             cout << file << endl;
01894             //on affiche
01895         }
01896         return true;
01897     }
01898     return false;
01899 }
01900 
01906 bool Model::LoadMPS(const std::string& _name, bool verbose)
01907 {
01908     FichierMPS file;
01909     //on déclare un fichier LP source
01910 
01911     //si on ne reussi pas à charger le fichier LP
01912     if(!file.Open(_name.c_str()))
01913     {
01914         cerr << "Warning in Model::LoadLP : I/O error in the opening of " << _name << endl;
01915         return false;
01916         //on quitte
01917     }
01918     
01919     //sinon on charge le modèle à partir du fichier LP
01920     if( file >> (*this) )
01921     {
01922         //si le flag d'affichage est vrai
01923         if(verbose == true)
01924         {
01925             cout << file << endl;
01926             //on affiche
01927         }
01928         return true;
01929     }
01930     return false;
01931 }
01932 
01936 void Model::ShowMe( bool withoutNullValue)
01937 {
01938      OutNumVarValues(withoutNullValue);
01939      OutConstraintValues();
01940 }
01941 
01945 void Model::RemoveVariable(VarId varId)
01946 {
01947    map<VarId,Paire>::iterator variable = unknowMap.find(varId);
01948    //on regarde si l'identifiant existe
01949    if( variable != unknowMap.end() )
01950    {
01951      unknowMap.erase( variable );
01952      //on efface la variable associée puis on nettoie la matrice creuse
01953 
01954      std::map< Id,float,Compare<float> >::iterator iter  = A.matrix.begin();
01955      std::map< Id,float,Compare<float> >::iterator tmp;
01956 
01957      //on parcourt la matrice
01958      while(iter != A.matrix.end())
01959      {
01960        unsigned i = iter->first.i; //indice de colonne
01961 
01962        //si l'on se trouve sur la colonne de la matrice creuse
01963        if(i == varId)
01964        {
01965         //dans de ca on supprime l'element
01966         tmp = iter;
01967         //mais pas directement car erase ne retourne la position du prochain élément
01968         ++iter;
01969         //donc on avance
01970         A.matrix.erase( tmp );
01971         //et ensuite on supprime
01972        }
01973        else
01974           ++iter;
01975           //sinon on se contente d'avancer
01976      }
01977    }
01978    else
01979      cerr << "Warning in Model::RemoveVariable : undefined id " << varId << endl;
01980 
01981 }
01982 
01986 void Model::RemoveConstraint(VarId id)
01987 {
01988 
01989   std::map< Id,float,Compare<float> >::iterator iter  = A.matrix.begin();
01990   //iterateur principal qui va parcourir le map matrix de A
01991   std::map< Id,float,Compare<float> >::iterator tmp;
01992   //iterateur secondaire qui sert à sauvegarder les positions à supprimer
01993   //tant que l'on a pas fini de percourir le map
01994   while(iter != A.matrix.end())
01995   {
01996      unsigned j = iter->first.j;
01997      //on recupere l'indice horizontale de l'élément courant
01998      //on le compare avec l'identifiant de la contrainte
01999      if(j == id)
02000      {
02001         //dans de ca on supprime l'element
02002         tmp = iter;
02003         //mais pas directement car erase ne retourne la position du prochain élément
02004         ++iter;
02005         //donc on avance
02006         A.matrix.erase( tmp );
02007         //et ensuite on supprime
02008      }
02009      else
02010      {
02011        //sinon on n'est pas sur la bonne contrainte
02012        ++iter;
02013        //on avance
02014        //sauf si on a passé la contrainte
02015        if(j>id)
02016          //dans ce cas on quitte la boucle
02017          break;
02018      }
02019   }
02020 }
02021 
02026 void Model::AddToConstraint(VarId id ,const Expr & expr)
02027 {
02028    std::list<ExprNode>::const_iterator iter;
02029    //itérateur constant sur l'expression expr constante
02030    //si la contrainte existe
02031    if( constraintMap.find(id) != constraintMap.end() )
02032    {
02033      //on parcourt l'expression
02034      for( iter = expr.nodeList.begin(); iter != expr.nodeList.end(); ++iter)
02035      {
02036         float coef = iter->GetCoefficient().GetValue();
02037         NumVar varTmp = iter->GetVariable();
02038         VarId varId = (varTmp.GetModel()?varTmp.GetVarId():0);
02039         //on récupere l'identifiant de la variable
02040         //si il est non nul et que la variable est définie
02041         if(varId && unknowMap.find(varId) != unknowMap.end() )
02042         {
02043           float acoef = A.Get(varId,id);
02044           //on récupère le coeffictient dans la matrice
02045           //si il est différent de l'opposé du nouveau coefficient
02046           if(acoef != -coef)
02047             A.Set(varId,id,coef+acoef);
02048             //coef <- coef + nouveau coef
02049           else
02050             A.matrix.erase(A.matrix.find(Id(varId,id)));
02051             //sinon le coef devient nul et donc on le supprime
02052         }
02053         else
02054         {
02055            if( varId )
02056               cerr << "Warning in Model::AddToConstraint : undefined varId " << varId << endl;
02057         }
02058       }
02059    }
02060    else
02061      cerr << "Warning in Model::AddToConstraint : undefined constraint id " << id << endl;
02062 }
02063 
02068 Constraint Model::GetConstraint(const string & name)
02069 {
02070   //on cherche son identifiant puis on renvoie la contrainte
02071   return GetConstraint(GetConstraintId(name));
02072 }
02073 
02081 VarId Model::GetConstraintId(const string & name)
02082 {
02083     bool trouve = false; //booléen servant de "break" à la boucle de recherche
02084 
02085     VarId id = 0; //l'identifiant est nul si on ne trouve pas de contrainte
02086 
02087     map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
02088     //iterateur de map initialisé au début
02089     //tant que l'on a pas trouvé ou qu'il reste des contraintes à tester
02090     while(!trouve && constraint != constraintMap.end() )
02091     {
02092         //on verifie si l'on a trouvé la contrainte suivante
02093         if( ( constraint->second.name == name) )
02094         {
02095           id = constraint->first;
02096           //on récupère l'identifiant de la contrainte qui est la clé dans le constraintMap
02097           trouve = true;
02098           //on quitte la boucle a la fin de cette itération
02099         }
02100         ++constraint;
02101         //on passe à la contrainte suivante
02102     }
02103     return id;
02104 }
02105 
02110 void Model::RenameConstraint( VarId id, const string & name)
02111 {
02112     map<VarId,InternalConstraint>::iterator constraint = constraintMap.find(id);
02113     //on regarde si la contrainte existe
02114     if( constraint != constraintMap.end())
02115         //si oui on reattribue le nom
02116         constraint->second.name = name;
02117     else
02118         cerr << "Warning in Model::RenameConstraint : undefined id " << id << endl;
02119 }
02120 
02125 void Model::SetSecondMember(VarId id ,float bid)
02126 {
02127     map<VarId,InternalConstraint>::iterator constraint = constraintMap.find(id);
02128     //on regarde si la contrainte existe
02129     if( constraint != constraintMap.end())
02130         //si oui on change le coefficient
02131         constraint->second.b = bid;
02132     else
02133         cerr << "Warning in Model::RenameConstraint : undefined id " << id << endl;
02134 }
02135 
02140 float Model::GetSecondMember(VarId id) const
02141 {    
02142     map<VarId,InternalConstraint>::const_iterator constraint = constraintMap.find(id);
02143     //on regarde si la contrainte existe
02144     if( constraint != constraintMap.end())
02145         //si oui on change le coefficient
02146         return constraint->second.b;
02147     else
02148         cerr << "Warning in Model::RenameConstraint : undefined id " << id << endl;
02149     return Infinity;
02150 }
02151 
02153 void Model::Clear()
02154 {
02155     hacheVarId=1;
02156     hacheConstraintId=1;
02157     unknowMap.clear();
02158     A.matrix.clear();
02159     A.nbLignes = A.nbCols = 0;
02160     constraintMap.clear();
02161     comments.clear();
02162 
02163     isMax = true;
02164     isRelaxed = false;
02165     isFract = false;
02166     isOptimal = false;
02167     isSolved = false;
02168     isNormalized = false;
02169     MIPVar = 0;
02170 
02171     objectif = Expr();
02172     objectifActivity = 0.0f;
02173     objectifName = "";
02174     problemName = "";
02175 }
02176 
02177 void Model::Normalize(bool withoutStrict)
02178 {
02179     unsigned p = A.GetNbLignes()+1;
02180     float coef = 1.0f;
02181     
02182     if(isMax==true)
02183     {
02184         objectif*=-1;
02185         isMax=false;
02186     }
02187 
02188 
02189     map<VarId,InternalConstraint>::iterator constraint;
02190     for(map< Id,float,Compare<float> >::iterator iter  = A.matrix.begin();
02191                                                  iter != A.matrix.end();
02192                                                ++iter)
02193     {
02194         unsigned i = iter->first.i; //indice de colonne
02195         unsigned j = iter->first.j; //indice de ligne
02196         if( p != j)
02197         {
02198             constraint = constraintMap.find(j);
02199             switch( constraint->second.type )
02200             {
02201                 case InternalConstraint::SUP :
02202                     coef = 1.0f;
02203                 break;
02204 
02205                 case InternalConstraint::SUPSTRICT :
02206                     coef = 1.0f;
02207                     constraint->second.type = InternalConstraint::SUP;
02208                 break;
02209 
02210                 case InternalConstraint::INF :
02211                     coef = -1.0f;
02212                     constraint->second.type = InternalConstraint::SUP;
02213                 break;
02214 
02215                 case InternalConstraint::INFSTRICT :
02216                     coef = -1.0f;
02217                     constraint->second.type = InternalConstraint::SUP;
02218                 break;
02219                 case InternalConstraint::EGAL :
02220                     coef = 1.0;
02221                 break;
02222                 default:
02223                 break;
02224              }
02225              constraint->second.b*=coef;
02226              p = j;
02227         }
02228         map<VarId,Paire>::iterator variable =  unknowMap.find(i);
02229         if( variable->second.variable.GetLowerBound() >=0 )
02230             iter->second*=coef;
02231         else
02232             iter->second*=-coef;
02233     }
02234      map<VarId,Paire>::iterator variable;
02235      for(variable = unknowMap.begin();variable != unknowMap.end();++variable)
02236      {
02237         if( !(variable->second.variable.GetLowerBound() >=0 ))
02238         {
02239            float lb = variable->second.variable.GetLowerBound();
02240            float ub = variable->second.variable.GetUpperBound();
02241            variable->second.variable.SetLowerBound(-ub);
02242            variable->second.variable.SetUpperBound(-lb);
02243         }
02244      }
02245 
02246 }
02247 
02248 
02249 
02250 
02254 Model Model::GetDual() const
02255 {
02256     Model ret;
02257     map<VarId,Paire>::const_iterator variable;
02258     map<VarId,InternalConstraint>::const_iterator constraint;
02259 
02260     ret.isMax = !isMax;
02261     ret.solverAPI = solverAPI;
02262     ret.objectifName = objectifName + "dual";
02263     ret.problemName = problemName + "dual";
02264 
02265     for(map< Id,float,Compare<float> >::const_iterator iter  = A.matrix.begin();
02266                                                          iter != A.matrix.end();
02267                                                        ++iter)
02268     {
02269 
02270         unsigned i = iter->first.i; //indice de colonne
02271         unsigned j = iter->first.j; //indice de ligne
02272         float coef = iter->second;
02273         ret.A.Set(j,i,coef);
02274     }
02275     
02276     for(constraint = constraintMap.begin(); constraint != constraintMap.end(); ++constraint)
02277     {
02278        unsigned id = constraint->first;
02279        Paire var;
02280        InternalConstraint ic = constraint->second;
02281        var.nom = ic.name;
02282        float lb=0,ub=Infinity;
02283        var.variable = MuteVar( MuteVar::FLOAT,ic.activity,lb,ub);
02284        ret.unknowMap[id] = var;
02285        ret.objectif += ic.b * NumVar( const_cast<const Model *>(&ret), id);
02286      }
02287 
02288     for(variable = unknowMap.begin(); variable != unknowMap.end(); ++variable)
02289     {
02290        unsigned id = variable->first;
02291        ret.constraintMap[id] = InternalConstraint( InternalConstraint::INF,
02292                                                    0.0,
02293                                                    variable->second.variable.GetValue(),
02294                                                    0.0,
02295                                                    variable->second.nom);
02296 
02297     }
02298 
02299     for( list<ExprNode>::const_iterator iter = objectif.nodeList.begin();
02300                                         iter != objectif.nodeList.end();
02301                                       ++iter)
02302     {
02303         float b = iter->GetCoefficient().GetValue();
02304         unsigned id = iter->GetVariable().GetVarId();
02305         ret.SetSecondMember(id,b);
02306     }
02307 
02308     return ret;
02309 }
02310 
02314 void Model::PrintDual(const std::string& fileName) const
02315 {
02316     ofstream file( fileName.c_str() );
02317     if(!file.is_open())
02318         throw runtime_error("Model::PrintDual : I/O Error");
02319     file << GetDual();
02320     file.close();
02321 }
02322 
02323 
02330 std::string Model::AddComment( const std::string & comment )
02331 {
02332   std::map<VarId,std::string>::iterator trouve = comments.find(hacheConstraintId);
02333   std::string retour;
02334   if(trouve!=comments.end())
02335   {
02336     retour = trouve->second;
02337     trouve->second = comment;
02338   }
02339   else
02340     comments[hacheConstraintId] = comment;
02341   return retour;
02342 }
02343 
02349 void Model::SetComment( VarId id, const std::string &  comment)
02350 {
02351   std::map<VarId,std::string>::iterator trouve = comments.find(id);
02352   if(trouve!=comments.end())
02353      trouve->second = comment;
02354   else
02355      comments[id] = comment;
02356 }
02357 
02358 std::string Model::GetComment( VarId id ) const
02359 {
02360   std::map<VarId,std::string>::const_iterator trouve = comments.find(id);
02361   if(trouve!=comments.end())
02362      return trouve->second;
02363   else
02364      return std::string();
02365 }
02366 
02367 
02368 #ifdef USE_HTML_FORMAT
02369 
02372 void Model::SortieHTML( const std::string & fileName, const std::string& matrixPNG)
02373 {
02374     HTMLFile html(fileName);
02375     std::ostream & out = html.getStream();
02376     string s1,s2;
02377     SolveInfos(s1,s2);
02378     
02379     // Si ce n'est pas résolu, on l'affiche en gros et en haut
02380     if (isSolved == false)
02381     {
02382         html << "<h3>Problème non résolu</h3>";
02383         html.NewLine();
02384     }
02385 
02386     // Entete html/liens
02387     html << "<h1>Sortie du Modèle du Programme linéaire</h1>";
02388     html << "<ul>";
02389     html << "<li><a href=\"#caracteristique_probleme\">Caractéristiques du problème</a></li>";
02390     html << "<li><a href=\"#dimension_probleme\">Dimensions du problème</a></li>";
02391     if( A.GetNbLignes() < 20 && A.GetNbCols() < 20)
02392       html << "<li><a href=\"#pl\">Programme linéaire</a></li>";
02393     if( isSolved )
02394       html << "<li><a href=\"#resolution\">Résolution du problème</a></li>";
02395     if (matrixPNG != "")
02396       html << "<li><a href=\"#matrice_creuse\">Affichage de la matrice creuse</a></li>";
02397 
02398     html << "</ul>";
02399     html.NewLine();
02400     html << "<h2><a name=\"caracteristique_probleme\">Caractéristiques du problème</a></h2>";
02401 
02402     html << "Problème de <b>" << s1 << "</b>";
02403     html.NewLine();
02404     if( problemName != "" )
02405     {
02406         html << "Nom du problème: \"" << problemName << "\"";
02407         html.NewLine();
02408     }
02409     if( objectifName != "" )
02410     {
02411       html << "Nom de la fonction objectif: <b>" << objectifName << "</b>";
02412       html.NewLine();
02413     }
02414     html << "<br />";
02415     html << "<h2><a name=\"dimension_probleme\">Dimensions du problème</a></h2>";
02416     html.NewLine();
02417     OutDimensions(out,"<br/>");
02418     html << "<br />";
02419     // Sortie du LP dans le fichier HTML
02420     if( A.GetNbLignes() < 20 && A.GetNbCols() < 20)
02421     {
02422         html << "<h2><a name=\"pl\">Programme linéaire</a></h2>";
02423         html << *this;
02424         html << "<br />";
02425     }
02426     if( isSolved )
02427     {
02428         html << "<h2><a name=\"resolution\">Résolution du problème</a></h2>";
02429         html.NewLine();
02430         html << "Le problème a été résolu avec " << (solverAPI.GetAPI()==1?"GLPSOL" : "CPLEX");
02431         html.NewLine();
02432         html.NewLine();
02433         if (isRelaxed) {
02434            html << "Le problème est relaxé";
02435            html.NewLine();
02436         }
02437         if( isOptimal )
02438             html << "Solution <b>OPTIMALE</b>: " << objectifActivity;
02439         else
02440             html << "Solution NON OPTIMALE: " << objectifActivity;
02441         html.NewLine();
02442         html << "Sortie solveur: " << s2;
02443 
02444         html.NewLine();
02445         html.NewLine();
02446         OutNumVarValues(true,out,"<br/>");
02447         html.NewLine();
02448         OutConstraintValues(out,"<br/>");
02449         html.NewLine();
02450 
02451         // Si on a sorti un matrice creuse, on peut la mettre dans le fichier HTML
02452         #ifdef EXPORT_SPARSE_MATRIX_PNG
02453         if (matrixPNG != "")
02454         {
02455             html << "<h2><a name=\"matrice_creuse\">Affichage de la matrice creuse</a></h2>";
02456             html << "<div align='center'>";
02457             html << "<img src='./" << matrixPNG << "' alt\"MatriceCreuse\"/>";
02458             html << "</div>";
02459             html.NewLine();
02460         }
02461         #endif
02462     }
02463     html.Close();
02464 }
02465 #endif
02466 
02467 #ifdef USE_LATEX_FORMAT
02468 
02471 void Model::SortieLATEX( const std::string & fileName)
02472 {
02473     LATEXFile latex(fileName,"Programme linéaire",false);
02474     std::ostream & out = latex.getStream();
02475     latex << "Sortie du Modele du Programme linéaire";
02476     latex.MakeSection("Caractéristiques du problème");
02477 
02478     if( problemName != "" )
02479     {
02480         latex.MakeSection("Nom du problème:");
02481         latex << "  Le nom du probleme est" << problemName;
02482         latex.EndSection();
02483     }
02484     latex.MakeSection( "Dimensions du problème:");
02485     OutDimensions(out,"\\\\");
02486     latex.EndSection();
02487     latex.EndSection();
02488     if( A.GetNbLignes() < 20 && A.GetNbCols() < 20)
02489     {
02490         latex.MakeSection( "Programme linéaire");
02491         latex << *this;
02492         latex.EndSection();
02493     }
02494     if( isSolved )
02495     {
02496         latex.MakeSection( "Résolution du problème");
02497         latex.MakeSection( "Fonction Objectif");
02498         if( isOptimal )
02499             latex << "Solution OPTIMALE: " << objectifActivity;
02500         else
02501             latex << "Solution NON OPTIMALE: " << objectifActivity;
02502         latex.EndSection();
02503 
02504         latex.MakeSection( "Variables");
02505         OutNumVarValues(true,out,"\\\\");
02506         latex.EndSection();
02507         latex.MakeSection( "Contraintes");
02508         OutConstraintValues(out,"\\\\");
02509         latex.EndSection();
02510     }
02511     else
02512     {
02513         latex << "Problème non résolu";
02514     }
02515     latex.Close();
02516 }
02517 #endif
02518 
02519 #ifdef EXPORT_SPARSE_MATRIX_PNG
02520 
02521   #include "Png.h"
02522 
02523   void Model::ExportSparseMatrixPNG(const std::string& _nom) const
02524   {
02525     // Obtenir la dimension de la matrice
02526     unsigned w=A.GetNbCols(),h=A.GetNbLignes();
02527     // définir une quantité de Zoom sur l'image p-ê
02528     unsigned zoom=1;
02529 
02530     PNGImage image(_nom.c_str(), w, h);
02531     image.openFileWrite();
02532     image.initWriteStructs();
02533     image.writeHeader();
02534     png_byte **Buff = image.writeImage_Start();
02535     unsigned char col1=255,col2=255,col3=255;
02536 
02537     for (unsigned y=0;y<h;y+=zoom)
02538         for (unsigned x=0;x<w;x+=zoom)
02539         {
02540           float val = A(x,y);
02541             col2 = 65;
02542             //cout << scaled << " <-> " << val << " | ";
02543             if (val < -epsylon)    {col1 = 255; col3=0;} // rouge = négatif
02544             else if(val > epsylon) {col1=0; col3 = 255;} // bleu  = positif
02545             else
02546             {
02547               col1=col2=col3=255;
02548             }
02549           Buff[y][x*3+0] = col1;
02550           Buff[y][x*3+1] = col2;
02551           Buff[y][x*3+2] = col3;
02552         }
02553 
02554     image.writeImage_End();
02555     image.writeEnd();
02556   }
02557 
02558 #endif
02559 
02560 #ifdef COMPILE_FOR_PYTHON
02561     #include "py_Model.cxx"
02562 #endif
02563 
02564 
02565 }

Généré le Sun Oct 2 19:13:12 2005 pour Modelib par  doxygen 1.4.4