Modelib: Fichier source de Expr.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

# Expr.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 "Expr.h"
    00033 #include "Num.h"
    00034 #include "NumArray.h"
    00035 #include "NumVar.h"
    00036 #include "NumVarArray.h"
    00037 #include "Model.h"
    00038 #include <map>
    00039
    00040 namespace Modelib {
    00041
    00042 using namespace std;
    00043
    00045 struct Comparaison
    00046 {
    00047   Comparaison() {};
    00053   bool operator()(const NumVar& x, const NumVar& y) const
    00054   {
    00055       return (x.GetVarId() < y.GetVarId());
    00056   }
    00057 };
    00058
    00059 /*----------------------------------------------------------------------------*/
    00060
    00061 // Constructeurs specifique
    00062
    00067 Expr::Expr( const NumVar & numVar)
    00068 :isSimplified(false),isParametric(false),sansConstantes(false)
    00069 {
    00070   nodeList.push_back(ExprNode( Num(numVar.GetType(), 1.0), numVar));
    00071 }
    00072
    00077 Expr::Expr( float f )
    00078 :isSimplified(false),isParametric(false),sansConstantes(false)
    00079 {
    00080   nodeList.push_back( ExprNode(  Float(f), NumVar() ) );
    00081 }
    00082
    00087 Expr::Expr( double f )
    00088 :isSimplified(false),isParametric(false),sansConstantes(false)
    00089 {
    00090   nodeList.push_back( ExprNode(  Float((float)f), NumVar() ) );
    00091 }
    00092
    00097 Expr::Expr( int i )
    00098 :isSimplified(false),isParametric(false),sansConstantes(false)
    00099 {
    00100   nodeList.push_back( ExprNode(  Int(i), NumVar() ) );
    00101 }
    00102
    00107 Expr::Expr( unsigned i )
    00108 :isSimplified(false),isParametric(false),sansConstantes(false)
    00109 {
    00110   nodeList.push_back( ExprNode(  Int(i), NumVar() ) );
    00111 }
    00112
    00117 Expr::Expr( const Num & num)
    00118 :isSimplified(false),isParametric(false),sansConstantes(false)
    00119 {
    00120   nodeList.push_back( ExprNode(  num, NumVar() ) );
    00121 }
    00122
    00129 Expr::Expr( const Num & num, const NumVar & numVar)
    00130 :isSimplified(false),isParametric(false),sansConstantes(false)
    00131 {
    00132     nodeList.push_back(ExprNode( num, numVar));
    00133 }
    00134
    00142 Expr::Expr( const Num & num, const NumVar & numVar, const LagrangianParam & mult)
    00143 :isSimplified(false),isParametric(true),sansConstantes(false)
    00144 {
    00145     nodeList.push_back(ExprNode(num,numVar,mult));
    00146 }
    00147
    00148
    00149 /*----------------------------------------------------------------------------*/
    00150
    00156 Expr & Expr::ASS( const Num & num, const NumVar & numVar )
    00157 {
    00158     nodeList.push_back( ExprNode( num, numVar) );
    00159     isSimplified = false;
    00160     return *this;
    00161 }
    00162
    00168 Expr & Expr::ASS( const Num & num, const NumVar & numVar, const LagrangianParam & mult )
    00169 {
    00170     nodeList.push_back( ExprNode( num, numVar, mult ) );
    00171     isSimplified = false;
    00172     isParametric = true;
    00173     return *this;
    00174 }
    00175
    00176 /*----------------------------------------------------------------------------*/
    00177
    00183 Expr & Expr::operator+=( const Expr & _expr)
    00184 {
    00185   list<ExprNode>::const_iterator src = _expr.nodeList.begin();
    00186
    00187   for(;src!=_expr.nodeList.end();++src)
    00188   {
    00189     nodeList.push_back( *src );
    00190   }
    00191   isSimplified = false;
    00192
    00193   return *this;
    00194 }
    00195
    00196 /*----------------------------------------------------------------------------*/
    00197
    00203 Expr & Expr::operator-=( const Expr & _expr)
    00204 {
    00205   list<ExprNode>::const_iterator src = _expr.nodeList.begin();
    00206
    00207   for(;src!=_expr.nodeList.end();++src)
    00208   {
    00209     nodeList.push_back( ExprNode( Num(-src->GetCoefficient().GetValue()),
    00210                                   src->GetVariable(),
    00211                                   src->GetLagrangianParam()  ) );
    00212   }
    00213   isSimplified = false;
    00214
    00215   return *this;
    00216 }
    00217
    00218
    00219 /*----------------------------------------------------------------------------*/
    00220
    00226 Expr & Expr::operator*=( const Num & a)
    00227 {
    00228   list<ExprNode>::iterator src = nodeList.begin();
    00229
    00230   for(;src!=nodeList.end();++src)
    00231   {
    00232     src->SetCoefficient( a.GetValue() * src->GetCoefficient().GetValue() );
    00233   }
    00234   isSimplified = false;
    00235
    00236   return *this;
    00237 }
    00238
    00239 /*----------------------------------------------------------------------------*/
    00240
    00248 void Expr::Simplify( bool avecLagrangianParam, bool sansConstante  )
    00249 {
    00250   // si l'expression est déjà simplifiée et que l'on travaille sans les lagrangiens
    00251   if(isSimplified && !avecLagrangianParam)
    00252       return;
    00253       //on quitte
    00254
    00255     map<NumVar,float,Comparaison> tmp;
    00256     //table temporaire permettant d'associer un coefficient pour chaque variable
    00257     map<NumVar,float,Comparaison>::iterator trouve;
    00258     //iterateur sur cette table
    00259
    00260     list<ExprNode>::iterator pos = nodeList.begin();
    00261     //iterateur de liste de bloc coefficient*Variable initialisé au début de la liste
    00262
    00263     list<ExprNode> tmpList;
    00264     //liste temporaire de bloc coefficient*Variable
    00265
    00266     while( pos != nodeList.end() )
    00267     {
    00268       float coef = pos->GetCoefficient().GetValue();
    00269       NumVar var = pos->GetVariable();
    00270       LagrangianParam mult = pos->GetLagrangianParam();
    00271
    00272       if( avecLagrangianParam )
    00273       {
    00274           if(mult.GetModel())
    00275              coef = coef*mult.GetValue();
    00276           trouve = tmp.find(var);
    00277           if(trouve != tmp.end())
    00278              trouve->second+=coef;
    00279           else
    00280              tmp[var] = coef;
    00281       }
    00282       else
    00283       {
    00284         if(mult.GetModel() == 0)
    00285         {
    00286             trouve = tmp.find(var);
    00287             if(trouve != tmp.end())
    00288                trouve->second+=coef;
    00289             else
    00290                tmp[var] = coef;
    00291         }
    00292       }
    00293       pos = nodeList.erase(pos);
    00294     }
    00295
    00296     for(trouve = tmp.begin(); trouve != tmp.end(); ++trouve)
    00297     {
    00298       float coef = trouve->second;
    00299       NumVar var = trouve->first;
    00300       if( coef  != 0.0f )
    00301       {
    00302         if( var.GetModel() )
    00303         {
    00304               MuteVar::VarType type = var.GetType();
    00305             tmpList.push_back(ExprNode(Num(type,coef),var));
    00306         }
    00307         else
    00308            if( !sansConstante)
    00309              tmpList.push_front(ExprNode(Num(MuteVar::FLOAT,coef),var));
    00310       }
    00311     }
    00312     nodeList.splice(nodeList.begin(),tmpList);
    00313
    00314   isSimplified = true;
    00315
    00316   return;
    00317 }
    00318
    00319
    00325 bool Expr::IsNum()
    00326 {
    00327   return ( Size()==1 && (nodeList.front().GetVariable().GetModel() == 0) );
    00328 }
    00329
    00330
    00337 bool Expr::IsVar()
    00338 {
    00339    return ( Size()==1 && (nodeList.front().GetVariable().GetModel() != 0)
    00340                       && nodeList.front().GetCoefficient().GetValue() == 1.0f);
    00341 }
    00342
    00348 float Expr::GetConstant(bool avecLagrangianParam ) const
    00349 {
    00350   list<ExprNode>::const_iterator src = nodeList.begin();
    00351   float retour=0;
    00352   while( !( src==nodeList.end() || ( isSimplified && src->GetVariable().GetModel()!=0) ) )
    00353   {
    00354     if( avecLagrangianParam && src->GetVariable().GetModel()==0 )
    00355       if( src->GetLagrangianParam().GetModel() )
    00356         retour += src->GetCoefficient().GetValue()*src->GetLagrangianParam().GetValue();
    00357       else
    00358         retour += src->GetCoefficient().GetValue();
    00359     else
    00360       if(!src->GetLagrangianParam().GetModel() && src->GetVariable().GetModel()==0 )
    00361         retour += src->GetCoefficient().GetValue();
    00362     ++src;
    00363   }
    00364   return retour;
    00365 }
    00366
    00372 float Expr::Evalue( bool avecLagrangianParam ) const
    00373 {
    00374   float retour = 0.0f;
    00375   list<ExprNode>::const_iterator src = nodeList.begin();
    00376
    00377   for( ; src != nodeList.end(); ++src)
    00378   {
    00379     if( avecLagrangianParam )
    00380     {
    00381         if( src->GetVariable().GetModel() )
    00382       {
    00383         if( src->GetLagrangianParam().GetModel() )
    00384           retour += src->GetCoefficient().GetValue()
    00385                     *src->GetLagrangianParam().GetValue()
    00386                     *src->GetVariable().GetValue();
    00387         else
    00388           retour += src->GetCoefficient().GetValue()
    00389                     *src->GetVariable().GetValue();
    00390       }
    00391       else
    00392       {
    00393         if( src->GetLagrangianParam().GetModel() )
    00394           retour += src->GetCoefficient().GetValue()
    00395                     *src->GetLagrangianParam().GetValue();
    00396         else
    00397           retour += src->GetCoefficient().GetValue();
    00398       }
    00399     }
    00400     else
    00401     {
    00402         if( src->GetVariable().GetModel() )
    00403           retour += src->GetCoefficient().GetValue()
    00404                     *src->GetVariable().GetValue();
    00405       else
    00406           retour += src->GetCoefficient().GetValue();
    00407     }
    00408   }
    00409   return retour;
    00410 }
    00411
    00412 /*----------------------------------------------------------------------------*/
    00413
    00420 Expr operator+( const Expr & expr1, const Expr & expr2)
    00421 {
    00422   Expr retour = expr1;
    00423   retour+=expr2;
    00424   return retour;
    00425 }
    00426
    00427
    00434 Expr operator-( const Expr & expr1, const Expr & expr2)
    00435 {
    00436   Expr retour = expr1;
    00437   retour-=expr2;
    00438   return retour;
    00439 }
    00440
    00441
    00448 Expr operator*( const Expr & expr, const Num & a)
    00449 {
    00450   Expr retour = expr;
    00451   retour*=a;
    00452   return retour;
    00453 }
    00454
    00455
    00462 Expr operator*( const Num & a , const Expr & expr)
    00463 {
    00464   Expr retour = expr;
    00465   retour*=a;
    00466   return retour;
    00467 }
    00468
    00469
    00476 Expr operator*( const Num & num, const NumVar & numVar)
    00477 {
    00478   return Expr(num,numVar);
    00479 }
    00480
    00481
    00488 Expr operator*( const NumVar & numVar, const Num & num)
    00489 {
    00490   return Expr(num,numVar);
    00491 }
    00492
    00493
    00501 Expr operator*( const NumVarArray & nva, const NumArray & na)
    00502 {
    00503   Expr retour;
    00504   unsigned minSize = nva.Size() < na.Size() ? nva.Size() : na.Size();
    00505   for(unsigned i = 0; i < minSize; ++i)
    00506     retour+=(nva[i])*(na[i]);
    00507   return retour;
    00508 }
    00509
    00510
    00518 Expr operator*( const NumArray & numArray , const NumVarArray & numVarArray)
    00519 {
    00520   return numVarArray * numArray;
    00521 }
    00522
    00523 /*----------------------------------------------------------------------------*/
    00524
    00533 std::ostream & operator<< (std::ostream & flux, const Expr & expr )
    00534 {
    00535   if(!expr.isSimplified)  //si l'expression n'est pas simplifiée
    00536   {
    00537    Expr e = expr; //on la duplique
    00538    e.Simplify(expr.isParametric,expr.sansConstantes);  //On la simplifie
    00539    flux << e;     //et on l'affiche avec le meme operateur
    00540    return flux;
    00541   }
    00542   else
    00543   {
    00544     list<ExprNode>::const_iterator i = expr.nodeList.begin();
    00545
    00546     if(i!=expr.nodeList.end())   //Pour les expressions vides
    00547     {
    00548       bool affSigne = true;  //sert pour ne pas afficher le premier signe +
    00549       for( ;i!= expr.nodeList.end(); ++i) //On parcourt la liste de couple Num*NumVar
    00550       {
    00551         float coef = i->GetCoefficient().GetValue(); //On recupere coefficient
    00552         string name;
    00553         if(i->GetVariable().GetModel())
    00554               name = i->GetVariable().GetName(); //On recupere le nom
    00555
    00556         if( name != defaultGetName)
    00557         {
    00558           if(affSigne) //si on est au début de l'expression, on n'affiche pas de '+'
    00559           {
    00560               //si la variable est définie et le coef différent de 1
    00561               if( coef != 1.0f &&  coef != -1.0f && name != noModel)
    00562                 flux << coef << name;
    00563               else
    00564                 if( name != noModel )
    00565                   flux << (coef == 1.0f?"":"-") << name;
    00566                 else
    00567                   flux << coef;
    00568               affSigne = !affSigne;
    00569           }
    00570           else
    00571           //idem mais avec l'affichage du signe.
    00572           if( coef != 1.0f &&  coef != -1.0f && name != noModel )
    00573              flux << (coef > 0?"+":"") << coef << name;
    00574           else
    00575              if( name != noModel )
    00576                flux << (coef == 1.0f?"+":"-") << name;
    00577              else
    00578                if( coef != 0.0 )
    00579                  flux << '+' << coef;
    00580         }
    00581       }
    00582     }
    00583     return flux;
    00584   }
    00585 }
    00586
    00587
    00588 /*----------------------------------------------------------------------------*/
    00589
    00596 Expr Sum(const NumVarArray & _x)
    00597 {
    00598   Expr retour;
    00599   for(unsigned i=0;i < _x.Size();++i)
    00600      retour+=Expr(_x[i]);
    00601   return retour;
    00602 }
    00603
    00604
    00605 }