- Main Page
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# /home/coin/SVN-release/OS-2.3.5/OS/src/OSSolverInterfaces/OSCouenneSolver.cpp

Go to the documentation of this file.

    00001 /* $Id: OSCouenneSolver.cpp 4120 2011-03-30 06:28:16Z kmartin $ */
    00019 #include <iostream>
    00020
    00021
    00022 //OS stuff
    00023 #include "OSDataStructures.h"
    00024 #include "OSParameters.h"
    00025 #include "OSMathUtil.h"
    00026 #include "OSCouenneSolver.h"
    00027 #include "BonBonminSetup.hpp"
    00028 # include <cppad/cppad.hpp>
    00029 //end OS stuff
    00030
    00031
    00032 // Couenne stuff
    00033
    00034 #include "CouenneTypes.hpp"
    00035 #include "CouenneJournalist.hpp"
    00036 #ifndef COUENNE_NEW
    00037 #include "exprClone.hpp"
    00038 #include "exprGroup.hpp"
    00039 #include "exprAbs.hpp"
    00040 #include "exprConst.hpp"
    00041 #include "exprCos.hpp"
    00042 #include "exprDiv.hpp"
    00043 #include "exprExp.hpp"
    00044 #include "exprInv.hpp"
    00045 #include "exprLog.hpp"
    00046 #include "exprMax.hpp"
    00047 #include "exprMin.hpp"
    00048 #include "exprMul.hpp"
    00049 #include "exprOpp.hpp"
    00050 #include "exprPow.hpp"
    00051 #include "exprSin.hpp"
    00052 #include "exprSub.hpp"
    00053 #include "exprSum.hpp"
    00054 #include "exprVar.hpp"
    00055 #else
    00056 #include "CouenneExprClone.hpp"
    00057 #include "CouenneExprGroup.hpp"
    00058 #include "CouenneExprAbs.hpp"
    00059 #include "CouenneExprConst.hpp"
    00060 #include "CouenneExprCos.hpp"
    00061 #include "CouenneExprDiv.hpp"
    00062 #include "CouenneExprExp.hpp"
    00063 #include "CouenneExprInv.hpp"
    00064 #include "CouenneExprLog.hpp"
    00065 #include "CouenneExprMax.hpp"
    00066 #include "CouenneExprMin.hpp"
    00067 #include "CouenneExprMul.hpp"
    00068 #include "CouenneExprOpp.hpp"
    00069 #include "CouenneExprPow.hpp"
    00070 #include "CouenneExprSin.hpp"
    00071 #include "CouenneExprSub.hpp"
    00072 #include "CouenneExprSum.hpp"
    00073 #include "CouenneExprVar.hpp"
    00074 using namespace Couenne;
    00075 #endif
    00076 // end Couenne stuff
    00077
    00078
    00079 //Bonmin stuff
    00080
    00081 #include "BonOsiTMINLPInterface.hpp"
    00082 #include "BonIpoptSolver.hpp"
    00083
    00084
    00085 #include "CoinTime.hpp"
    00086 #include "BonminConfig.h"
    00087 #include "BonCouenneInterface.hpp"
    00088
    00089
    00090 #include "BonCouenneSetup.hpp"
    00091
    00092
    00093 #ifdef COIN_HAS_FILTERSQP
    00094 #include "BonFilterSolver.hpp"
    00095 #endif
    00096
    00097 #include "CbcCutGenerator.hpp"
    00098 #include "CouenneProblem.hpp"
    00099 #include "CouenneCutGenerator.hpp"
    00100
    00101
    00102 # include <cstddef>
    00103 # include <cstdlib>
    00104 # include <cctype>
    00105 # include <cassert>
    00106 # include <stack>
    00107 #include <string>
    00108 #include<iostream>
    00109
    00110
    00111
    00112 using namespace Bonmin;
    00113 using std::cout;
    00114 using std::endl;
    00115 using std::ostringstream;
    00116
    00117
    00118 CouenneSolver::CouenneSolver() {
    00119 using namespace  Ipopt;
    00120         osrlwriter = new OSrLWriter();
    00121         osresult = new OSResult();
    00122         m_osilreader = NULL;
    00123         m_osolreader = NULL;
    00124         couenneErrorMsg = "";
    00125         couenne = NULL;
    00126         con_body = NULL;
    00127         obj_body = NULL;
    00128 }
    00129
    00130 CouenneSolver::~CouenneSolver() {
    00131         #ifdef DEBUG
    00132         cout << "inside CouenneSolver destructor" << endl;
    00133         #endif
    00134
    00135         if(couenne != NULL){
    00136                 //cout << "start delete of couenne problem" << endl;
    00138                 //cout << "finish delete of couenne problem" << endl;
    00139         }
    00140         if(con_body != NULL){
    00141                 //delete con_body;
    00142         }
    00143         if(obj_body != NULL){
    00144                 //delete obj_body;
    00145         }
    00146         if(m_osilreader != NULL) {
    00147                 //cout << "start delete of osinstance" << endl;
    00148                 delete m_osilreader;
    00149                 //cout << "end delete of osinstance" << endl;
    00150         }
    00151         m_osilreader = NULL;
    00152         if(m_osolreader != NULL) delete m_osolreader;
    00153         m_osolreader = NULL;
    00154         delete osresult;
    00155         osresult = NULL;
    00156         delete osrlwriter;
    00157         osrlwriter = NULL;
    00158         //delete osinstance;
    00159         //osinstance = NULL;
    00160         #ifdef DEBUG
    00161         cout << "leaving CouenneSolver destructor" << endl;
    00162         #endif
    00163
    00164 }
    00165
    00166
    00167 void CouenneSolver::buildSolverInstance() throw (ErrorClass) {
    00168         // Much of the following is taken from Stefan Vigerske
    00169         try{
    00170                 this->bCallbuildSolverInstance = true;
    00171                 // do some initialization
    00172
    00173
    00174
    00175
    00176                 int i, j;
    00177
    00178                 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
    00179                 if(osinstance == NULL){
    00180                         m_osilreader = new OSiLReader();
    00181                         osinstance = m_osilreader->readOSiL( osil);
    00182                 }
    00183
    00184
    00185
    00186                 //osinstance->initializeNonLinearStructures( );
    00187                 osinstance->initForAlgDiff( );
    00188                 //Ipopt::Journalist* jnlst = new Ipopt::Journalist();
    00189                 //jnlst->AddFileJournal("console", "stdout", J_STRONGWARNING);
    00190                 //couenne = new CouenneProblem(NULL, NULL, jnlst);
    00191                 couenne = new CouenneProblem(NULL, NULL, NULL);
    00192                 int n_allvars = osinstance->getVariableNumber();
    00193                 if( n_allvars < 0 )throw ErrorClass("Couenne solver Cannot have a negatiave number of Variables");
    00194                 #ifdef DEBUG
    00195                 std::cout << "NUMBER OF VARIABLES = " <<  n_allvars <<  std::endl;
    00196                 #endif
    00197                 if(n_allvars > 0){
    00198                         // create room for problem's variables and bounds
    00199                         CouNumber *x_ = (CouNumber *) malloc ((n_allvars) * sizeof (CouNumber));
    00200                         CouNumber       *lb = NULL, *ub = NULL;
    00201
    00202                         // now get variable upper and lower bounds
    00203                         ub = osinstance->getVariableUpperBounds();
    00204                         lb = osinstance->getVariableLowerBounds();
    00205
    00206                         //declare the variable types
    00207                         char *varType;
    00208                         varType = osinstance->getVariableTypes();
    00209                         for (i = 0; i < n_allvars; ++i) {
    00210                                 if( (varType[i] == 'B') || (varType[i]) == 'I' ) {
    00211                                         couenne->addVariable(true, couenne->domain() );
    00212                                 }
    00213                                 else{
    00214
    00215                                         couenne->addVariable(false, couenne->domain() );
    00216
    00217                                 }
    00218
    00219                                 x_[i] = 0.;     //HIG: This sets initial values?
    00220                         }
    00221
    00222                         couenne->domain()->push(n_allvars, x_, lb, ub);
    00223                         free(x_);
    00224                 }
    00225
    00226                 // now for the objective function -- assume just one for now
    00227                 //just worry about linear coefficients
    00228
    00229                 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Couenne NEEDS AN OBJECTIVE FUNCTION");
    00230
    00231
    00232                 //if(n_allvars > 0){
    00233                         SparseVector* sv = osinstance->getObjectiveCoefficients()[ 0];
    00234                         int nterms = sv->number;
    00235                         exprGroup::lincoeff lin( nterms);
    00236                         for ( i = 0; i < nterms; ++i){
    00237                                         lin[i].first = couenne->Var( sv->indexes[ i] );
    00238                                         if( osinstance->getObjectiveMaxOrMins()[0] == "min"){
    00239                                                 lin[i].second = sv->values[ i];
    00240                                         }else{
    00241                                                 lin[i].second = -sv->values[ i];
    00242
    00243                                         }
    00244                         }
    00245
    00246
    00247                         OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( -1);
    00248                         if (exptree != NULL) {
    00249                                 expression** nl = new expression*[1];
    00250                                 if( osinstance->getObjectiveMaxOrMins()[0] == "min"){
    00251                                         nl[0] = createCouenneExpression( exptree->m_treeRoot );
    00252                                 }else{
    00253                                         nl[ 0] = new exprOpp(createCouenneExpression( exptree->m_treeRoot) );
    00254
    00255                                 }
    00256                                 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, nl, 1);
    00257                         } else {
    00258                                 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, NULL, 0);
    00259                                 //std::cout << "THERE WERE NO NONLINEAR TERMS IN THE OBJECTIVE FUNCTION "  << std::endl;
    00260                         }
    00261
    00262                 //}
    00263                 couenne->addObjective(obj_body, "min");
    00264
    00265                 // get the constraints in row format
    00266
    00267                 SparseMatrix* sm =  osinstance->getLinearConstraintCoefficientsInRowMajor();
    00268
    00269                 int nconss = osinstance->getConstraintNumber();
    00270
    00271                 int row_nonz = 0;
    00272                 int kount = 0;
    00273                 //int row_nonz_actual = 0;
    00274                 double *rowlb = osinstance->getConstraintLowerBounds();
    00275                 double *rowub = osinstance->getConstraintUpperBounds();
    00276
    00277                 for (i = 0; i < nconss; ++i) {
    00278                 //std::cout << "WE ARE PROCESSING ROW " << i << std::endl;
    00279                         row_nonz = 0;
    00280                         if( sm) row_nonz = sm->starts[ i +1] - sm->starts[ i];
    00281                         exprGroup::lincoeff con_lin( row_nonz);
    00282                                 for (j = 0; j  <  row_nonz;  ++j){
    00283                                         con_lin[j].first = couenne->Var( sm->indexes[ kount] );
    00284                                         con_lin[j].second = sm->values[ kount];
    00285                                         kount++;
    00286                                 }
    00287                         //}
    00288                         OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( i);
    00289                         if (exptree != NULL) {
    00290                                 expression** nl = new expression*[1];
    00291                                 nl[0] = createCouenneExpression(exptree->m_treeRoot);
    00292                                 con_body = new exprGroup(0., con_lin, nl, 1);
    00293                         } else {
    00294                                 con_body = new exprGroup(0., con_lin, NULL, 0);
    00295                         }
    00296
    00297                         if (rowlb[ i] == rowub[ i])
    00298                         {
    00299                                 couenne->addEQConstraint(con_body, new exprConst( rowub[ i] ));
    00300                         }
    00301                         else if (rowlb[ i]  ==  -OSDBL_MAX)
    00302                         {
    00303                                 assert(rowub[ i]  !=  -OSDBL_MAX);
    00304                                 couenne->addLEConstraint(con_body, new exprConst( rowub[ i] ));
    00305                         }
    00306                         else if (rowub[ i] ==  OSDBL_MAX)
    00307                         {
    00308                                 assert(rowlb[ i]  != OSDBL_MAX);
    00309                                 couenne->addGEConstraint(con_body, new exprConst( rowlb[ i] ));
    00310                         }
    00311                         else
    00312                                 couenne->addRNGConstraint(con_body, new exprConst( rowlb[ i]), new
    00313                                         exprConst( rowub[ i] ));
    00314
    00315                 }
    00316         }
    00317         catch(const ErrorClass& eclass){
    00318                 std::cout << "THERE IS AN ERROR" << std::endl;
    00319                 osresult->setGeneralMessage( eclass.errormsg);
    00320                 osresult->setGeneralStatusType( "error");
    00321                 osrl = osrlwriter->writeOSrL( osresult);
    00322                 throw ErrorClass( osrl) ;
    00323         }
    00324 }//end buildSolverInstance()
    00325
    00326
    00327 expression* CouenneSolver::createCouenneExpression(OSnLNode* node) {
    00328         //std::cout << "NODE NUMBER =  " << node->inodeInt  << std::endl;
    00329         unsigned int i;
    00330         switch (node->inodeInt) {
    00331                 case OS_PLUS :
    00332                         return new exprSum(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
    00333                 case OS_SUM :
    00334                 //std::cout << "I AM INSIDE A SUM NODE  "   << std::endl;
    00335                 //std::cout << "I HAVE THE FOLLOWING NUMBER OF CHILDREN  " <<   node->inumberOfChildren << std::endl;
    00336          //switch ( node->inumberOfChildren==0 ) { // Stefan's coding
    00337                  switch ( node->inumberOfChildren ) {  //kipp modification
    00338                  case 0:
    00339                                         //std::cout << "I IN SUM CASE 0  "   << std::endl;
    00340                          return new exprConst(0.);
    00341                  case 1:
    00342                                 //std::cout << "I IN SUM CASE 1  "   << std::endl;
    00343                          return createCouenneExpression(node->m_mChildren[0]);
    00344                  default:
    00345                                 //std::cout << "I IN SUM CASE DEFAULT  "   << std::endl;
    00346                          expression** sumargs = new expression*[node->inumberOfChildren];
    00347            for(i = 0;  i<  node->inumberOfChildren;  i++)
    00348                  sumargs[i] = createCouenneExpression(node->m_mChildren[i]);
    00349                         //expression* base = new exprSum(args, node->inumberOfChildren);  //Stefan
    00350            //delete[] args;  //delete Stefan's code -- causes a seg fault
    00351            //return base; stefan
    00352                    return new exprSum(sumargs, node->inumberOfChildren);
    00353         }
    00354      case OS_MINUS :
    00355          return new exprSub(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
    00356      case OS_NEGATE :
    00357          return new exprOpp(createCouenneExpression(node->m_mChildren[0]));
    00358      case OS_TIMES :
    00359          return new exprMul(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
    00360      case OS_DIVIDE :
    00361          // couenne does not like expressions of the form exp1/exp2 with exp1 a constant, so we write them as exp1 * 1/exp2
    00362          if (node->m_mChildren[0]->inodeInt == OS_NUMBER)
    00363          return new exprMul(createCouenneExpression(node->m_mChildren[0]), new exprInv(createCouenneExpression(node->m_mChildren[1])));
    00364          else
    00365                  return new exprDiv(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
    00366      case OS_POWER :
    00367          // couenne does not like expressions of the form exp1 ^ exp2 with exp2 not a constant, so we write them as exp(log(exp1)*exp2)
    00368          if (node->m_mChildren[1]->inodeInt != OS_NUMBER)
    00369                  return new exprExp(new exprMul(new exprLog(createCouenneExpression(node->m_mChildren[0])), createCouenneExpression(node->m_mChildren[1])));
    00370          else
    00371                  return new exprPow(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
    00372      case OS_PRODUCT:
    00373          switch ( node->inumberOfChildren ) {
    00374                  case 0:
    00375                          return new exprConst(1.);
    00376                  case 1:
    00377                          return createCouenneExpression(node->m_mChildren[0]);
    00378                  default:
    00379                                 expression** args = new expression*[node->inumberOfChildren];
    00380                                 for( i = 0; i < node->inumberOfChildren;i++)
    00381                                         args[i] = createCouenneExpression(node->m_mChildren[i]);
    00382                                 expression* base = new exprMul(args, node->inumberOfChildren);
    00383            //delete[] args;
    00384                         return base;
    00385         }
    00386      case OS_ABS :
    00387          return new exprAbs(createCouenneExpression(node->m_mChildren[0]));
    00388      case OS_SQUARE :
    00389          return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(2.));
    00390      case OS_SQRT :
    00391          return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(0.5));
    00392      case OS_LN :
    00393          return new exprLog(createCouenneExpression(node->m_mChildren[0]));
    00394      case OS_EXP :
    00395          return new exprExp(createCouenneExpression(node->m_mChildren[0]));
    00396      case OS_SIN :
    00397          return new exprSin(createCouenneExpression(node->m_mChildren[0]));
    00398      case OS_COS :
    00399          return new exprCos(createCouenneExpression(node->m_mChildren[0]));
    00400      case OS_MIN :
    00401          switch (node->inumberOfChildren==0) {
    00402                  case 0:
    00403                          return new exprConst(0.);
    00404                  case 1:
    00405                          return createCouenneExpression(node->m_mChildren[0]);
    00406                  default:
    00407                          expression** args = new expression*[node->inumberOfChildren];
    00408            for( i = 0; i <node->inumberOfChildren;i++)
    00409                  args[i] = createCouenneExpression(node->m_mChildren[i]);
    00410            expression* base = new exprMin(args, node->inumberOfChildren);
    00411            //delete[] args;
    00412            return base;
    00413         }
    00414      case OS_MAX :
    00415          switch (node->inumberOfChildren==0) {
    00416                  case 0:
    00417                          return new exprConst(0.);
    00418                  case 1:
    00419                          return createCouenneExpression(node->m_mChildren[0]);
    00420                  default:
    00421                          expression** args = new expression*[node->inumberOfChildren];
    00422            for(i = 0; i < node->inumberOfChildren;i++)
    00423                  args[i] = createCouenneExpression(node->m_mChildren[i]);
    00424            expression* base = new exprMax(args, node->inumberOfChildren);
    00425            //delete[] args;
    00426            return base;
    00427         }
    00428      case OS_NUMBER :
    00429          return new exprConst(((OSnLNodeNumber*)node)->value);
    00430      case OS_PI :
    00431          assert(false);
    00432          //TODO
    00433 //       return new exprConst(PI);
    00434      case OS_VARIABLE : {
    00435         OSnLNodeVariable* varnode = (OSnLNodeVariable*)node;
    00436         if (varnode->coef == 0.)
    00437                 return new exprConst(0.);
    00438         if (varnode->coef == 1.)
    00439                 return new exprClone(couenne->Variables()[varnode->idx]);
    00440         if (varnode->coef == -1.)
    00441                 return new exprOpp(new exprClone(couenne->Variables()[varnode->idx]));
    00442                 return new exprMul(new exprConst(varnode->coef), new exprClone(couenne->Variables()[varnode->idx]));
    00443      }
    00444      default:
    00445         cout << node->getTokenName() << " NOT IMPLEMENTED!!" << endl;
    00446         break;
    00447   }
    00448
    00449         return NULL;
    00450 }
    00451
    00452
    00453 void CouenneSolver::setSolverOptions() throw (ErrorClass) {
    00454         try{
    00455
    00456                 char *pEnd;
    00457                 bSetSolverOptions = true;
    00458                 couenneSetup.initializeOptionsAndJournalist();
    00459                 //turn off a lot of output -- this can be overridden by using OSOptions
    00460                 couenneSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0);
    00461                 couenneSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
    00462                 if(osoption == NULL && osol.length() > 0)
    00463                 {
    00464                         m_osolreader = new OSoLReader();
    00465                         osoption = m_osolreader->readOSoL( osol);
    00466                 }
    00467
    00468                 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 ){
    00469
    00470                         int i;
    00471                         std::vector<SolverOption*> optionsVector;
    00472                         optionsVector = osoption->getSolverOptions( "couenne");
    00473                         int num_bonmin_options = optionsVector.size();
    00474                         for(i = 0; i < num_bonmin_options; i++){
    00475                                 if(optionsVector[ i]->type == "numeric" ){
    00476                                         //std::cout << "FOUND A  NUMERIC OPTION  "  <<  os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) << std::endl;
    00477                                         if(optionsVector[ i]->category == "ipopt"){
    00478                                                 couenneSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
    00479                                         }else{
    00480                                                 if(optionsVector[ i]->category == "bonmin" ){
    00481                                                         couenneSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
    00482                                                 }
    00483                                                 else{
    00484                                                         couenneSetup.options()->SetNumericValue("couenne."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
    00485                                                 }
    00486                                         }
    00487                                 }
    00488                                 else if(optionsVector[ i]->type == "integer" ){
    00489                                         //std::cout << "FOUND AN INTEGER OPTION  "  <<optionsVector[ i]->name << std::endl;
    00490                                         if(optionsVector[ i]->category == "ipopt"){
    00491                                                 couenneSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
    00492                                         }else{
    00493                                                 if(optionsVector[ i]->category == "bonmin" ){
    00494                                                         couenneSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
    00495                                                 }
    00496                                                 else{
    00497                                                         couenneSetup.options()->SetIntegerValue("couenne."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() )  );
    00498                                                 }
    00499                                         }
    00500                                 }
    00501                                 else if(optionsVector[ i]->type == "string" ){
    00502                                         //std::cout << "FOUND A STRING OPTION  "  <<optionsVector[ i]->name << std::endl;
    00503                                         if(optionsVector[ i]->category == "ipopt"){
    00504                                                 couenneSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );
    00505                                         }else{
    00506                                                 if(optionsVector[ i]->category == "bonmin" ){
    00507                                                         couenneSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);
    00508                                                 }
    00509                                                 else{
    00510                                                         couenneSetup.options()->SetStringValue("couenne."+optionsVector[ i]->name, optionsVector[ i]->value);
    00511                                                 }
    00512                                         }
    00513
    00514                                 }
    00515                         }
    00516                 }
    00517         }
    00518
    00519         catch(const ErrorClass& eclass){
    00520                 std::cout << "THERE IS AN ERROR" << std::endl;
    00521                 osresult->setGeneralMessage( eclass.errormsg);
    00522                 osresult->setGeneralStatusType( "error");
    00523                 osrl = osrlwriter->writeOSrL( osresult);
    00524                 throw ErrorClass( osrl) ;
    00525         }
    00526
    00527 }//end setSolverOptions()
    00528
    00529
    00530 using namespace Ipopt;
    00531
    00532
    00533 void CouenneSolver::solve() throw (ErrorClass) {
    00534 #define PRINTED_PRECISION 1e-5
    00535         const int infeasible = 1;
    00536         //double time_start = CoinCpuTime();
    00537         if( this->bCallbuildSolverInstance == false) buildSolverInstance();
    00538         if(this->bSetSolverOptions == false) setSolverOptions() ;
    00539         try{
    00540
    00541                 //couenne->print();
    00542
    00543                 char **argv = NULL;
    00544
    00545         bb.setUsingCouenne (true);
    00546
    00547                 //using namespace Ipopt;
    00548
    00549                 if(osoption == NULL  && osol.length() > 0){
    00550                         m_osolreader = new OSoLReader();
    00551                         osoption = m_osolreader->readOSoL( osol);
    00552                 }
    00553
    00554
    00555                 tminlp = new BonminProblem( osinstance, osoption);
    00556
    00557                 CouenneInterface *ci = NULL;
    00558
    00559                 ci = new CouenneInterface();
    00560                 //const std::string  prefix="bonmin.";
    00561
    00562                 //std::cout << "INITIALIZE COUENNE INTERFACE" << std::endl;
    00563
    00564                 ci->initialize (couenneSetup.roptions(),//GetRawPtr(roptions),
    00565                                 couenneSetup.options(),//GetRawPtr( options),
    00566                                 couenneSetup.journalist(),//GetRawPtr(jnlst),
    00567                                  GetRawPtr( tminlp) );
    00568
    00569                 //std::cout << "INITIALIZE IPOPT SOLVER " << std::endl;
    00570                 app_ = new Bonmin::IpoptSolver(couenneSetup.roptions(),//GetRawPtr(roptions),
    00571                                                couenneSetup.options(),//GetRawPtr( options),
    00572                                                couenneSetup.journalist()//GetRawPtr(jnlst),
    00573                                                );
    00574
    00575
    00576
    00577                 //std::cout << "INITIALIZE COUENNE MODEL" << std::endl;
    00578                 ci->setModel( GetRawPtr( tminlp) );
    00579                 //std::cout << "INITIALIZE COUENNE SOLVER" << std::endl;
    00580                 ci->setSolver( GetRawPtr( app_) );
    00581                 // initialize causes lots of memory leaks
    00582
    00583
    00584                 //std::cout << "INITIALIZE COUENNE " << std::endl;
    00585                 bool setupInit = false;
    00586                 setupInit = couenneSetup.InitializeCouenne(argv, couenne, NULL, ci);
    00587                 //std::cout << "ci -> isProvenOptimal ()" << ci -> isProvenOptimal ()<< std::endl;
    00588
    00589
    00590                 if(setupInit == false){
    00591                         std::string solutionDescription = "";
    00592                         std::string message = "Couenne solver finishes to the end.";
    00593                         int solIdx = 0;
    00594                         if(osresult->setServiceName( "Couenne solver service") != true)
    00595                                 throw ErrorClass("OSResult error: setServiceName");
    00596                         if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
    00597                                 throw ErrorClass("OSResult error: setInstanceName");
    00598                         if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
    00599                                 throw ErrorClass("OSResult error: setVariableNumer");
    00600                         if(osresult->setObjectiveNumber( 1) != true)
    00601                                 throw ErrorClass("OSResult error: setObjectiveNumber");
    00602                         if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
    00603                                 throw ErrorClass("OSResult error: setConstraintNumber");
    00604                         if(osresult->setSolutionNumber(  1) != true)
    00605                                 throw ErrorClass("OSResult error: setSolutionNumer");
    00606                         if(osresult->setGeneralMessage( message) != true)
    00607                                 throw ErrorClass("OSResult error: setGeneralMessage");
    00608                         solutionDescription = "COUENNE INITIALIZE PROBLEM: \n There was a problem with Couenne Initialize: \n the problem could be infeasible \n there may be zero decision variables";
    00609                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);
    00610                         osresult->setGeneralStatusType("normal");
    00611                         osrl = osrlwriter->writeOSrL( osresult);
    00612                         return;
    00613
    00614                 }
    00615
    00616                 std::cout << std::endl << std::endl;
    00617         // see if we have an unbounded solution
    00618         // if we are not infeasible and not optimal and have no integer variables we are probably unbounded
    00619         if(( ci->isProvenPrimalInfeasible() == false) && (ci -> isProvenOptimal () == false)
    00620                 && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) ){
    00621                 std::string solutionDescription = "";
    00622                 std::string message = "Success";
    00623                 int solIdx = 0;
    00624                 if(osresult->setServiceName( "Couenne solver service") != true)
    00625                         throw ErrorClass("OSResult error: setServiceName");
    00626                 if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
    00627                         throw ErrorClass("OSResult error: setInstanceName");
    00628                 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
    00629                         throw ErrorClass("OSResult error: setVariableNumer");
    00630                 if(osresult->setObjectiveNumber( 1) != true)
    00631                         throw ErrorClass("OSResult error: setObjectiveNumber");
    00632                 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
    00633                         throw ErrorClass("OSResult error: setConstraintNumber");
    00634                 if(osresult->setSolutionNumber(  1) != true)
    00635                         throw ErrorClass("OSResult error: setSolutionNumer");
    00636                 if(osresult->setGeneralMessage( message) != true)
    00637                         throw ErrorClass("OSResult error: setGeneralMessage");
    00638                 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
    00639                         osresult->setSolutionStatus(solIdx,  "error", solutionDescription);
    00640                 osresult->setGeneralStatusType("normal");
    00641                 osrl = osrlwriter->writeOSrL( osresult);
    00642                 return;
    00643         }
    00644
    00645
    00646         //std::cout << osinstance->printModel() << std::endl;
    00647
    00648
    00649         //std::cout << " CALL bb ( couenneSetup) " << std::endl;
    00650                 bb ( couenneSetup); // do branch and bound
    00651         //std::cout << " END bb ( couenneSetup) " << std::endl;
    00652
    00653
    00654
    00655
    00656     std::cout.precision (10);
    00657
    00658     CouenneCutGenerator *cg = NULL;
    00659
    00660     if (bb.model (). cutGenerators ())
    00661       cg = dynamic_cast <CouenneCutGenerator *>
    00662         (bb.model (). cutGenerators () [0] -> generator ());
    00663
    00664
    00665     double global_opt;
    00666     couenneSetup.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
    00667         //std::cout << "Couenne Global Optimum Check Value = " << global_opt  << std::endl;
    00668     //std::cout << "GET BEST POSSIBLE OBJ VALUE =  " << bb.model (). getBestPossibleObjValue ()  << std::endl;
    00669    // std::cout << "NUMBER OF NODES  =  " << bb.numNodes()  << std::endl;
    00670     //std::cout << "BEST POSSIBLE OBJ VALUE =  " << bb.bestObj()  << std::endl;
    00671         double timeLimit = 0;
    00672         couenneSetup.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
    00673         //std::cout << "TIME LIMIT  =  "  <<  timeLimit  << std::endl;
    00674     // note model is a CbcModel, bb is a BonCbc object
    00675
    00676
    00677
    00678     // now put information in OSResult object
    00679     status = tminlp->status;
    00680     writeResult();
    00681         //if(ci  != NULL)  delete ci;
    00682         } //end try
    00683
    00684         catch(const ErrorClass& eclass){
    00685                 osresult->setGeneralMessage( eclass.errormsg);
    00686                 osresult->setGeneralStatusType( "error");
    00687                 osrl = osrlwriter->writeOSrL( osresult);
    00688                 throw ErrorClass( osrl) ;
    00689         }
    00690
    00691         // Pietro's catch
    00692
    00693           catch(TNLPSolver::UnsolvedError *E) {
    00694              E->writeDiffFiles();
    00695              E->printError(std::cerr);
    00696             //There has been a failure to solve a problem with Ipopt.
    00697             //And we will output file with information on what has been changed in the problem to make it fail.
    00698             //Now depending on what algorithm has been called (B-BB or other) the failed problem may be at different place.
    00699             //    const OsiSolverInterface &si1 = (algo > 0) ? nlpSolver : *model.solver();
    00700           }
    00701
    00702           catch(OsiTMINLPInterface::SimpleError &E) {
    00703             std::cerr<<E.className()<<"::"<<E.methodName()
    00704                      <<std::endl
    00705                      <<E.message()<<std::endl;
    00706           }
    00707
    00708           catch(CoinError &E) {
    00709             std::cerr<<E.className()<<"::"<<E.methodName()
    00710                      <<std::endl
    00711                      <<E.message()<<std::endl;
    00712           }
    00713
    00714           catch (Ipopt::OPTION_INVALID &E)
    00715           {
    00716            std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
    00717           }
    00718           catch (int generic_error) {
    00719             if (generic_error == infeasible)
    00720               printf ("problem infeasible\n");
    00721           }
    00722
    00723 }//end solve()
    00724
    00725
    00726 void CouenneSolver::writeResult(){
    00727         double *x = NULL;
    00728         double *z = NULL;
    00729         int i = 0;
    00730         int solIdx = 0;
    00731         std::string solutionDescription = "";
    00732         std::string message = "Couenne solver finishes to the end.";
    00733
    00734
    00735         try{
    00736                 if(osinstance->getVariableNumber()  > 0) x = new double[osinstance->getVariableNumber() ];
    00737                 z = new double[1];
    00738                 // resultHeader information
    00739                 if(osresult->setSolverInvoked( "COIN-OR Couenne") != true)
    00740                         throw ErrorClass("OSResult error: setSolverInvoked");
    00741                 if(osresult->setServiceName( getVersionInfo()) != true)
    00742                         throw ErrorClass("OSResult error: setServiceName");
    00743                 if(osresult->setInstanceName(  osinstance->getInstanceName()) != true)
    00744                         throw ErrorClass("OSResult error: setInstanceName");
    00745                 //if(osresult->setJobID( osoption->jobID) != true)
    00746                 //      throw ErrorClass("OSResult error: setJobID");
    00747                 // set basic problem parameters
    00748
    00749                 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
    00750                         throw ErrorClass("OSResult error: setVariableNumer");
    00751                 if(osresult->setObjectiveNumber( 1) != true)
    00752                         throw ErrorClass("OSResult error: setObjectiveNumber");
    00753                 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
    00754                         throw ErrorClass("OSResult error: setConstraintNumber");
    00755                 if(osresult->setSolutionNumber(  1) != true)
    00756                         throw ErrorClass("OSResult error: setSolutionNumer");
    00757                 if(osresult->setGeneralMessage( message) != true)
    00758                         throw ErrorClass("OSResult error: setGeneralMessage");
    00759
    00760                 switch( status){
    00761                         case  TMINLP::SUCCESS:
    00762                                 solutionDescription = "SUCCESS[COUENNE]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
    00763                                 //std::cout << solutionDescription << std::endl;
    00764                                 osresult->setSolutionStatus(solIdx,  "locallyOptimal", solutionDescription);
    00765
    00766                                 if(osinstance->getObjectiveNumber() > 0){
    00767                                         /* Retrieve the solution */
    00768                                         *(z + 0)  =  osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
    00769                                         // okay if equal to 9999000000000 we are probably unbounded
    00770                                         if(fabs(*(z + 0)) == 9.999e+12){
    00771                                                 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: Continuous relaxation is unbounded, the MINLP may or may not be          unbounded.";
    00772                                                 //std::cout << solutionDescription << std::endl;
    00773                                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);
    00774                                                 break;
    00775                                         }
    00776                                         osresult->setObjectiveValuesDense(solIdx, z);
    00777                                 }
    00778
    00779
    00780                                 if(osinstance->getVariableNumber() > 0){
    00781                                         for(i=0; i < osinstance->getVariableNumber(); i++){
    00782                                                 *(x + i) = bb.bestSolution()[i];
    00783                                                 //std::cout <<  *(x + i)  << std::endl;
    00784                                         }
    00785                                         osresult->setPrimalVariableValuesDense(solIdx, x);
    00786                                 }
    00787
    00788
    00789                         break;
    00790
    00791                         case TMINLP::LIMIT_EXCEEDED:
    00792                                 solutionDescription = "LIMIT_EXCEEDED[COUENNE]: A resource limit was exceeded, we provide the current solution.";
    00793                                 //std::cout << solutionDescription << std::endl;
    00794                                 osresult->setSolutionStatus(solIdx,  "other", solutionDescription);
    00795                                 //osresult->setPrimalVariableValuesDense(solIdx, const_cast<double*>(x));
    00796                                 //osresult->setDualVariableValuesDense(solIdx, const_cast<double*>( lambda));
    00797                                 /* Retrieve the solution */
    00798                                 if(osinstance->getObjectiveNumber() > 0){
    00799                                         *(z + 0)  =  osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.model().getColSolution()), true)[ 0];
    00800                                         osresult->setObjectiveValuesDense(solIdx, z);
    00801                                 }
    00802
    00803                                 if(osinstance->getVariableNumber() > 0){
    00804                                         for(i=0; i < osinstance->getVariableNumber(); i++){
    00805                                                 *(x + i) = bb.model().getColSolution()[i];
    00806                                                 //std::cout <<  *(x + i)  << std::endl;
    00807                                         }
    00808                                         osresult->setPrimalVariableValuesDense(solIdx, x);
    00809                                 }
    00810                         break;
    00811
    00812                         case TMINLP::MINLP_ERROR:
    00813                                 solutionDescription = "MINLP_ERROR [COUENNE]: Algorithm stopped with unspecified error.";
    00814                                 //std::cout << solutionDescription << std::endl;
    00815                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);
    00816
    00817                         break;
    00818
    00819                         case TMINLP::CONTINUOUS_UNBOUNDED:
    00820                                 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
    00821                                 //std::cout << solutionDescription << std::endl;
    00822                                 osresult->setSolutionStatus(solIdx,  "error", solutionDescription);
    00823
    00824                         break;
    00825
    00826
    00827                         case TMINLP::INFEASIBLE:
    00828                                 solutionDescription = "INFEASIBLE [COUENNE]: Problem may be infeasible.";
    00829                                 //std::cout << solutionDescription << std::endl;
    00830                                 osresult->setSolutionStatus(solIdx,  "infeasible", solutionDescription);
    00831                         break;
    00832
    00833                         default:
    00834                                 solutionDescription = "OTHER[COUENNE]: other unknown solution status from Couenne solver";
    00835                                 osresult->setSolutionStatus(solIdx,  "other", solutionDescription);
    00836                 }//switch end
    00837                 osresult->setGeneralStatusType("normal");
    00838                 osrl = osrlwriter->writeOSrL( osresult);
    00839                 if(osinstance->getVariableNumber()  > 0) delete[] x;
    00840                 x = NULL;
    00841                 delete[] z;
    00842                 z = NULL;
    00843         }//end try
    00844
    00845
    00846         catch(const ErrorClass& eclass){
    00847                 delete[] x;
    00848                 x = NULL;
    00849                 delete[] z;
    00850                 z = NULL;
    00851                 osresult->setGeneralMessage( eclass.errormsg);
    00852                 osresult->setGeneralStatusType( "error");
    00853                 osrl = osrlwriter->writeOSrL( osresult);
    00854                 throw ErrorClass( osrl) ;
    00855         }
    00856
    00857
    00858 }// end writeResult()
    00859
    00860
    00861