00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
00251 if(isSimplified && !avecLagrangianParam)
00252 return;
00253
00254
00255 map<NumVar,float,Comparaison> tmp;
00256
00257 map<NumVar,float,Comparaison>::iterator trouve;
00258
00259
00260 list<ExprNode>::iterator pos = nodeList.begin();
00261
00262
00263 list<ExprNode> tmpList;
00264
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)
00536 {
00537 Expr e = expr;
00538 e.Simplify(expr.isParametric,expr.sansConstantes);
00539 flux << e;
00540 return flux;
00541 }
00542 else
00543 {
00544 list<ExprNode>::const_iterator i = expr.nodeList.begin();
00545
00546 if(i!=expr.nodeList.end())
00547 {
00548 bool affSigne = true;
00549 for( ;i!= expr.nodeList.end(); ++i)
00550 {
00551 float coef = i->GetCoefficient().GetValue();
00552 string name;
00553 if(i->GetVariable().GetModel())
00554 name = i->GetVariable().GetName();
00555
00556 if( name != defaultGetName)
00557 {
00558 if(affSigne)
00559 {
00560
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
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 }