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 }

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