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