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 "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
00104 switch(trouve->second.type)
00105 {
00106 case InternalConstraint::INFSTRICT :
00107 case InternalConstraint::INF :
00108
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
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
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
00155
00156 if( _nom == "unknow" )
00157 {
00158 char * nomId = new char[30];
00159
00160 sprintf(nomId,"%d",hacheVarId);
00161 tmpnom = _nom + nomId ;
00162
00163 delete [] nomId;
00164
00165 }
00166 else
00167 tmpnom = _nom;
00168
00169 unknowMap[hacheVarId]=Paire(muteVar,tmpnom);
00170
00171 if( muteVar.GetType() != MuteVar::FLOAT)
00172 MIPVar++;
00173
00174 return hacheVarId++;
00175
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
00239 for(;trouve!=unknowMap.end();++trouve)
00240
00241 if(trouve->second.nom == name)
00242 {
00243 retour = trouve->first;
00244
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
00453 Constraint Model::Add( const ConstraintBuilder & c , const std::string & nom)
00454 {
00455 Constraint retour;
00456 if( c.IsBound() )
00457 {
00458 NumVar var = (++c.expressions.begin())->nodeList.front().GetVariable();
00459
00460
00461 if(c.operateurs.size()==1)
00462 {
00463
00464 float bound;
00465 bool prems = ( c.expressions.back().nodeList.front().GetVariable().GetModel() == 0 );
00466
00467
00468 if(prems)
00469 bound = c.expressions.back().nodeList.front().GetCoefficient().GetValue();
00470
00471 else
00472 bound = c.expressions.front().nodeList.front().GetCoefficient().GetValue();
00473
00474 list<ConstraintBuilder::Operateur>::const_iterator op = c.operateurs.begin();
00475
00476
00477 switch( *op )
00478 {
00479 case ConstraintBuilder::INFSTRICT:
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:
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
00508 if(c.operateurs.size()==2)
00509 {
00510 float lrB = c.expressions.front().nodeList.front().GetCoefficient().GetValue();
00511
00512 float urB = c.expressions.back().nodeList.front().GetCoefficient().GetValue();
00513
00514 list<ConstraintBuilder::Operateur>::const_iterator op = c.operateurs.begin();
00515
00516 float swap;
00517
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
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
00547 else
00548 {
00549 if( c.operateurs.size() >=1 && c.operateurs.size() + 1 == c.expressions.size() )
00550 {
00551
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
00557 while( exp2!=c.expressions.end() )
00558 {
00559 Expr tmp;
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
00572 tmp.Simplify();
00573
00574
00575 VarId p;
00576 float coef = -(tmp.nodeList.front().GetVariable().GetModel()?0.0f:tmp.nodeList.front().GetCoefficient().GetValue());
00577
00578
00579
00580
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
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;
00677 unsigned j = iter->first.j;
00678
00679 variable = unknowMap.find(VarId(i));
00680
00681 if(j != p)
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
00856
00857
00858
00859
00860
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;
00885 unsigned j = iter->first.j;
00886
00887 variable = unknowMap.find(VarId(i));
00888
00889 if(j != p)
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;
01148 unsigned j = iter->first.j;
01149
01150 if(j != p)
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
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
01322 constraint = constraintMap.find(id);
01323
01324 if(constraint != constraintMap.end())
01325 {
01326 isRelaxed = true;
01327
01328 constraint->second.lagrangianValue = lagrangianValue;
01329
01330
01331 if(lagrangianValue != -Infinity)
01332 constraint->second.isLagrangianParamDefined = true ;
01333
01334 constraint->second.isLagrangianParamActive = true;
01335
01336 objectif-=GetRelaxedConstraintExpr(id);
01337
01338 objectif.isParametric = true;
01339
01340 objectif.sansConstantes = true;
01341
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;
01364 unsigned j = iter->first.j;
01365
01366
01367 if(j == p)
01368 {
01369 ret += iter->second*GetMuteVar(i).GetValue();
01370
01371
01372 }
01373 else
01374 if(j>p)
01375 break;
01376
01377
01378 ++iter;
01379 }
01380 return ret;
01381 }
01382
01388 Expr Model::GetRelaxedConstraintExpr( VarId id , bool relaxed)
01389 {
01390
01391 Expr ret;
01392
01393
01394 LagrangianParam mult(*this, id);
01395
01396 if(!relaxed)
01397 mult = LagrangianParam();
01398
01399
01400 std::map< Id,float,Compare<float> >::const_iterator iter = A.matrix.begin();
01401
01402 while(iter != A.matrix.end())
01403 {
01404 unsigned i = iter->first.i;
01405 unsigned j = iter->first.j;
01406
01407
01408 if(j == id)
01409 {
01410 ret.ASS( iter->second, NumVar(this,i), mult);
01411
01412 }
01413 else
01414 if(j>id)
01415 break;
01416
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
01438 if((id=GetConstraintId(name)))
01439 return RelaxConstraint(id,lagrangianValue);
01440
01441 else
01442 return false;
01443 }
01444
01445
01446
01454 bool Model::RelaxInt2Float( NumVar numVar )
01455 {
01456 VarId id = numVar.GetVarId();
01457
01458
01459
01460 if(id)
01461 unknowMap.find(id)->second.variable.SetRelaxed();
01462
01463 else
01464
01465 for(map<VarId,Paire>::iterator variable = unknowMap.begin();
01466 variable != unknowMap.end();
01467 ++variable)
01468 {
01469
01470 if(variable->second.variable.GetType()==MuteVar::INT)
01471 {
01472 variable->second.variable.SetRelaxed();
01473
01474 }
01475 }
01476 return true;
01477 }
01478
01486 bool Model::RelaxBool2Float( NumVar numVar )
01487 {
01488 VarId id = numVar.GetVarId();
01489
01490
01491
01492 if(id)
01493 unknowMap.find(id)->second.variable.SetRelaxed();
01494
01495 else
01496
01497 for(map<VarId,Paire>::iterator variable = unknowMap.begin();
01498 variable != unknowMap.end();
01499 ++variable)
01500 {
01501
01502 if(variable->second.variable.GetType()==MuteVar::BOOL)
01503 {
01504 variable->second.variable.SetRelaxed();
01505
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
01521
01522
01523 for(map<VarId,Paire>::iterator variable = unknowMap.begin();
01524 variable != unknowMap.end();
01525 ++variable)
01526 variable->second.variable.SetRelaxed(false);
01527
01528
01529
01530 for(map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01531 constraint != constraintMap.end();
01532 ++constraint)
01533 {
01534 constraint->second.isLagrangianParamActive = false;
01535
01536 }
01537 isRelaxed=false;
01538 }
01539
01540
01541
01542
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
01560 out << (*this);
01561
01562 out.close();
01563
01564
01565 solverAPI.SetMIP( MIPVar == 0);
01566
01567 val = solverAPI.Solve();
01568 isSolved = solverAPI.IsSolved();
01569 isOptimal = solverAPI.IsOptimal();
01570
01571
01572
01573
01574 SetNumVarValues(solverAPI.GetNumVarNoms(), solverAPI.OutNumVarValues());
01575
01576
01577 SetConstraintValues( solverAPI.GetConstraintNoms(), solverAPI.OutConstraintValues() );
01578
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
01592 for(;constraint != constraintMap.end(); ++constraint)
01593 {
01594 float ecart = constraint->second.b - constraint->second.activity;
01595
01596 if( ecart < 0 )
01597 listViolated.push_back( LagrangianParam(*this,constraint->first) );
01598
01599 if( ecart > 0 )
01600 listSlacked.push_back( LagrangianParam(*this,constraint->first) );
01601
01602 }
01603 }
01604
01608 std::vector<LagrangianParam> Model::GetAllLagrangianParams( )
01609 {
01610 vector<LagrangianParam> retour;
01611
01612 map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01613
01614 for(;constraint != constraintMap.end(); ++constraint)
01615 {
01616 retour.push_back( LagrangianParam(*this,constraint->first) );
01617
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
01631
01632
01633
01634
01635 if(noms.size() == values.size())
01636 {
01637
01638 list<string>::const_iterator iterNoms = noms.begin();
01639
01640 list<float>::const_iterator iterValues = values.begin();
01641
01642
01643
01644
01645 while( iterNoms != noms.end() )
01646 {
01647 resultats[*iterNoms] = *iterValues;
01648
01649 ++iterNoms;
01650 ++iterValues;
01651
01652 }
01653
01654 map<string,float>::const_iterator iter;
01655
01656 for(map<VarId,Paire>::iterator variable = unknowMap.begin();
01657 variable != unknowMap.end();
01658 ++variable)
01659 {
01660 iter = resultats.find(variable->second.nom);
01661
01662 if( iter != resultats.end() )
01663 variable->second.variable = iter->second;
01664
01665 else
01666 variable->second.variable = 0;
01667
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
01681
01682
01683
01684
01685 if(noms.size() == values.size())
01686 {
01687
01688 list<string>::const_iterator iterNoms = noms.begin();
01689
01690 list<float>::const_iterator iterValues = values.begin();
01691
01692
01693
01694
01695 while( iterNoms != noms.end() )
01696 {
01697 resultats[*iterNoms] = *iterValues;
01698
01699 ++iterNoms;
01700 ++iterValues;
01701
01702 }
01703
01704 map<string,float>::iterator trouve;
01705 map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
01706
01707 for(;constraint != constraintMap.end(); ++constraint)
01708 {
01709 trouve = resultats.find(constraint->second.name);
01710
01711 if( trouve != resultats.end())
01712 constraint->second.activity = trouve->second;
01713
01714 else
01715 constraint->second.activity = EvalConstraint(constraint->first);
01716
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
01745
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
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
01805 string op[] = { "<=",">=","=",">","<"};
01806
01807 for(;constraint != constraintMap.end(); ++constraint)
01808 {
01809
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
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
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
01878
01879
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
01885 }
01886
01887
01888 if( file >> (*this) )
01889 {
01890
01891 if(verbose == true)
01892 {
01893 cout << file << endl;
01894
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
01910
01911
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
01917 }
01918
01919
01920 if( file >> (*this) )
01921 {
01922
01923 if(verbose == true)
01924 {
01925 cout << file << endl;
01926
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
01949 if( variable != unknowMap.end() )
01950 {
01951 unknowMap.erase( variable );
01952
01953
01954 std::map< Id,float,Compare<float> >::iterator iter = A.matrix.begin();
01955 std::map< Id,float,Compare<float> >::iterator tmp;
01956
01957
01958 while(iter != A.matrix.end())
01959 {
01960 unsigned i = iter->first.i;
01961
01962
01963 if(i == varId)
01964 {
01965
01966 tmp = iter;
01967
01968 ++iter;
01969
01970 A.matrix.erase( tmp );
01971
01972 }
01973 else
01974 ++iter;
01975
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
01991 std::map< Id,float,Compare<float> >::iterator tmp;
01992
01993
01994 while(iter != A.matrix.end())
01995 {
01996 unsigned j = iter->first.j;
01997
01998
01999 if(j == id)
02000 {
02001
02002 tmp = iter;
02003
02004 ++iter;
02005
02006 A.matrix.erase( tmp );
02007
02008 }
02009 else
02010 {
02011
02012 ++iter;
02013
02014
02015 if(j>id)
02016
02017 break;
02018 }
02019 }
02020 }
02021
02026 void Model::AddToConstraint(VarId id ,const Expr & expr)
02027 {
02028 std::list<ExprNode>::const_iterator iter;
02029
02030
02031 if( constraintMap.find(id) != constraintMap.end() )
02032 {
02033
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
02040
02041 if(varId && unknowMap.find(varId) != unknowMap.end() )
02042 {
02043 float acoef = A.Get(varId,id);
02044
02045
02046 if(acoef != -coef)
02047 A.Set(varId,id,coef+acoef);
02048
02049 else
02050 A.matrix.erase(A.matrix.find(Id(varId,id)));
02051
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
02071 return GetConstraint(GetConstraintId(name));
02072 }
02073
02081 VarId Model::GetConstraintId(const string & name)
02082 {
02083 bool trouve = false;
02084
02085 VarId id = 0;
02086
02087 map<VarId,InternalConstraint>::iterator constraint = constraintMap.begin();
02088
02089
02090 while(!trouve && constraint != constraintMap.end() )
02091 {
02092
02093 if( ( constraint->second.name == name) )
02094 {
02095 id = constraint->first;
02096
02097 trouve = true;
02098
02099 }
02100 ++constraint;
02101
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
02114 if( constraint != constraintMap.end())
02115
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
02129 if( constraint != constraintMap.end())
02130
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
02144 if( constraint != constraintMap.end())
02145
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;
02195 unsigned j = iter->first.j;
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;
02271 unsigned j = iter->first.j;
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
02380 if (isSolved == false)
02381 {
02382 html << "<h3>Problème non résolu</h3>";
02383 html.NewLine();
02384 }
02385
02386
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
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
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
02526 unsigned w=A.GetNbCols(),h=A.GetNbLignes();
02527
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
02543 if (val < -epsylon) {col1 = 255; col3=0;}
02544 else if(val > epsylon) {col1=0; col3 = 255;}
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 }