00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <iomanip>
00015 #include <fstream>
00016
00017 #include <stdlib.h>
00018
00019 #include "CoinPragma.hpp"
00020 #include "CoinTime.hpp"
00021 #include "CoinError.hpp"
00022 #include "BonCouenneInterface.hpp"
00023
00024 #include "BonCouenneSetup.hpp"
00025
00026 #include "BonCbc.hpp"
00027 #include "CouenneBab.hpp"
00028
00029 #include "CbcCutGenerator.hpp"
00030 #include "CouenneProblem.hpp"
00031 #include "CouenneCutGenerator.hpp"
00032
00033 #include "CouenneRecordBestSol.hpp"
00034
00035 using namespace Couenne;
00036
00037
00038 #define PRINTED_PRECISION 1e-5
00039
00040 #include "CouenneExprVar.hpp"
00041 #include "CouenneExprConst.hpp"
00042 #include "CouenneExprSum.hpp"
00043 #include "CouenneExprClone.hpp"
00044 #include "CouenneProblemElem.hpp"
00045 #include "CouenneProblem.hpp"
00046 #include "CouenneJournalist.hpp"
00047
00048 #ifdef COIN_HAS_NTY
00049 #include "Nauty.h"
00050 #include "CouenneBranchingObject.hpp"
00051 #endif
00052
00053 #ifdef COIN_HAS_SCIP
00054 #include "lpiswitch.h"
00055 #endif
00056
00057 #include "CoinSignal.hpp"
00058
00059 #undef printError // defined in SCIP, replaces error handling below...
00060
00061 #if 0
00062 extern "C" {
00063
00064 static int nInterrupts = 0;
00065 static void signal_handler (int sig) {
00066
00067 if (!nInterrupts) {
00068 std::cerr << "[BREAK]" << std::endl;
00069 abort ();
00070 }
00071 return;
00072 }
00073 }
00074 #endif
00075
00076
00077
00078
00079
00080 int main (int argc, char *argv[]) {
00081
00082 #ifdef WIN_
00083 srand ((long) 42*666);
00084 #endif
00085
00086
00087
00088
00089 printf ("\
00090 Couenne %s -- an Open-Source solver for Mixed Integer Nonlinear Optimization\n\
00091 Mailing list: couenne@list.coin-or.org\n\
00092 Instructions: http://www.coin-or.org/Couenne\n",
00093 strcmp (COUENNE_VERSION, "trunk") ? COUENNE_VERSION : "");
00094
00095 WindowsErrorPopupBlocker();
00096
00097 using namespace Ipopt;
00098
00099 #ifdef COIN_HAS_SCIP
00100
00101 SCIPlpiSwitchSetSolver(SCIP_LPISW_CLP);
00102 #endif
00103
00104 char * pbName = NULL;
00105
00106 bool infeasible = false;
00107
00108 try {
00109
00110 CouenneBab bb;
00111
00112 CouenneProblem *p = NULL;
00113 CouenneInterface *ci = NULL;
00114
00115 #if 0
00116
00117 p = new CouenneProblem;
00118
00119 p -> addVariable (false, p -> domain ());
00120 p -> addVariable (false, p -> domain ());
00121 p -> addVariable (false, p -> domain ());
00122 p -> addVariable (false, p -> domain ());
00123
00124 p -> addObjective (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), "min");
00125 p -> addLEConstraint (new exprSum (new exprClone (p->Var (0)), new exprClone (p->Var (2))), new exprConst (1));
00126 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), new exprConst (1));
00127 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (3))), new exprConst (1));
00128 p -> addEQConstraint (new exprSum (new exprClone (p->Var (2)), new exprClone (p->Var (3))), new exprConst (1));
00129 #endif
00130
00131 CouenneSetup couenne;
00132 CouenneCutGenerator *cg = NULL;
00133 ConstJnlstPtr jnlst;
00134 CouenneProblem *prob = NULL;
00135
00136 infeasible = !(couenne.InitializeCouenne (argv, p, NULL, ci, &bb));
00137
00138
00139
00140
00141 if (couenne. cutGenerators () . size () > 0) {
00142
00143 for (std::list <Bonmin::BabSetupBase::CuttingMethod>::iterator
00144 i = couenne.cutGenerators () . begin ();
00145 !cg && (i != couenne.cutGenerators () . end ());
00146 ++i)
00147
00148 cg = dynamic_cast <CouenneCutGenerator *> (i -> cgl);
00149 }
00150
00151
00152
00153
00154
00155 if (cg)
00156
00157 cg -> setBabPtr (&bb);
00158
00159 else if (!infeasible) {
00160
00161 printf ("main(): ### ERROR: Can not get CouenneCutGenerator\n");
00162 exit (-1);
00163 }
00164
00165
00166
00167 jnlst = couenne. couennePtr () -> Jnlst ();
00168 prob = couenne. couennePtr () -> Problem ();
00169
00170 bb. setProblem (prob);
00171
00172 int retcomp = 2;
00173
00174 jnlst -> Printf (J_ERROR, J_COUENNE, "\
00175 Loaded instance \"%s\"\n\
00176 Constraints: %8d\n\
00177 Variables: %8d (%d integer)\n\
00178 Auxiliaries: %8d (%d integer)\n\n",
00179 prob -> problemName ().c_str (),
00180 prob -> nOrigCons (),
00181 prob -> nOrigVars (),
00182 prob -> nOrigIntVars (),
00183 prob -> nVars () - prob -> nOrigVars (),
00184 CoinMax (0, prob -> nIntVars () - prob -> nOrigIntVars ()));
00185
00186 double time_start = CoinCpuTime();
00187
00188 #if 0
00189 CouenneFeasibility feasibility;
00190 bb.model().setProblemFeasibility (feasibility);
00191 #endif
00192
00193 couenne.options () -> SetIntegerValue ("bb_log_level", 1);
00194 couenne.options () -> SetIntegerValue ("lp_log_level", 0);
00195 couenne.options () -> SetIntegerValue ("nlp_log_level", 0);
00196
00198 double timeLimit = 0;
00199 couenne.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00200 couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime,
00201 CoinMax (1., timeLimit - time_start));
00202
00203
00204
00206
00207 #ifdef COIN_HAS_NTY
00208 double symmGroupSize = prob -> orbitalBranching () ? prob -> getNtyInfo () -> getGroupSize () : -1;
00209 #endif
00210
00211
00212
00213 std::string s;
00214 couenne.options () -> GetStringValue ("feas_pump_heuristic", s, "couenne.");
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 if (!infeasible)
00238 bb (couenne);
00239
00240 else {
00241
00242 char *filename = new char [prob -> problemName (). length () + strlen ((char *) ".sol") + 1],
00243 *lastdot;
00244
00245 FILE *amplsol;
00246
00247 strcpy (filename, prob -> problemName () . c_str ());
00248
00249 if ((lastdot = strrchr (filename, '.')) != NULL)
00250 *lastdot = 0;
00251
00252 strcat (filename, ".sol");
00253
00254 amplsol = fopen (filename, "w");
00255
00256 if (amplsol != NULL) {
00257
00258 fprintf (amplsol, "\n Couenne (%s %s): Infeasible\n\nOptions\n3\n0\n1\n0\n%d\n0\n%d\n0\nobjno 0 220\n",
00259 prob -> problemName (). c_str (),
00260 __DATE__,
00261 prob -> nOrigCons (),
00262 prob -> nOrigVars ());
00263
00264 fclose (amplsol);
00265 }
00266
00267 delete [] filename;
00268 }
00269
00270 #ifdef COIN_HAS_NTY
00271 if (CouenneBranchingObject::nOrbBr)
00272 printf ("%d orbital nontrivial branchings\n", CouenneBranchingObject::nOrbBr);
00273 #endif
00274
00275 std::cout.precision (10);
00276
00277 int nr=-1, nt=-1;
00278 double st=-1;
00279
00280 if (cg) cg -> getStats (nr, nt, st);
00281 else printf ("Warning, could not get pointer to CouenneCutGenerator\n");
00282
00283 CouenneProblem *cp = cg ? cg -> Problem () : NULL;
00284
00285 #if defined (FM_TRACE_OPTSOL) || defined (FM_FRES)
00286 double cbcLb = (infeasible ? -COIN_DBL_MAX : bb.model (). getBestPossibleObjValue ());
00287 double printObj = 0;
00288 bool foundSol = false;
00289 #endif
00290
00291 #ifdef FM_TRACE_OPTSOL
00292
00293
00294
00295
00296
00297
00298
00299
00300 if (cp != NULL) {
00301 double cbcObjVal = infeasible ? COIN_DBL_MAX : bb.model().getObjValue();
00302 int modelNvars = prob -> nVars ();
00303
00304 CouenneRecordBestSol *rs = cp->getRecordBestSol();
00305 const double *cbcSol = infeasible ? NULL : bb.model().getColSolution();
00306 double *modCbcSol = new double[modelNvars];
00307 double modCbcSolVal= 1e100, modCbcSolMaxViol = 0;
00308 bool cbcSolIsFeas = false;
00309
00310 if(modelNvars != cp->nVars()) {
00311 printf("### ERROR: modelNvars: %d nVars: %d\n",
00312 modelNvars, cp->nVars());
00313 exit(1);
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 if (cbcObjVal < 1e49 && !infeasible) {
00323
00324 #ifdef FM_CHECKNLP2
00325 int cMS = rs->getCardModSol();
00326 cbcSolIsFeas = cp->checkNLP2(cbcSol, 0, false,
00327 false,
00328 true,
00329 cp->getFeasTol());
00330 cMS = rs->getCardModSol();
00331 CoinCopyN(rs->getModSol(cMS), cMS, modCbcSol);
00332 modCbcSolVal = rs->getModSolVal();
00333 modCbcSolMaxViol = rs->getModSolMaxViol();
00334 #else
00335 int cMS = cp->nVars();
00336 cbcSolIsFeas = cp->checkNLP(cbcSol, modCbcSolVal, true);
00337 CoinCopyN(cbcSol, cMS, modCbcSol);
00338 modCbcSolMaxViol = cp->getFeasTol();
00339 #endif
00340 foundSol = true;
00341 }
00342
00343 const double *couenneSol = rs->getSol();
00344 double *modCouenneSol = new double[modelNvars];
00345 double modCouenneSolVal= 1e100, modCouenneSolMaxViol = 0;
00346 bool couenneSolIsFeas = false;
00347
00348
00349
00350
00351
00352
00353
00354 if(couenneSol != NULL) {
00355 #ifdef FM_CHECKNLP2
00356 int cMS = rs->getCardModSol();
00357 couenneSolIsFeas = cp->checkNLP2(couenneSol, 0, false,
00358 false, true,
00359 cp->getFeasTol());
00360 CoinCopyN(rs->getModSol(cMS), cMS, modCouenneSol);
00361 modCouenneSolVal = rs->getModSolVal();
00362 modCouenneSolMaxViol = rs->getModSolMaxViol();
00363 #else
00364 int cMS = cp->nVars();
00365 couenneSolIsFeas = cp->checkNLP(couenneSol, modCouenneSolVal, true);
00366 CoinCopyN(couenneSol, cMS, modCouenneSol);
00367 modCouenneSolMaxViol = cp->getFeasTol();
00368 #endif
00369 foundSol = true;
00370 }
00371
00372 retcomp = rs -> compareAndSave (modCbcSol, modCbcSolVal, modCbcSolMaxViol, cbcSolIsFeas,
00373 modCouenneSol, modCouenneSolVal, modCouenneSolMaxViol, couenneSolIsFeas,
00374 modelNvars, cp->getFeasTol());
00375
00376
00377
00378
00379 std::string saveSol;
00380
00381 couenne.options () -> GetStringValue ("save_soltext", saveSol, "couenne.");
00382
00383 if (saveSol == "yes") {
00384
00385 char *txtFileName = new char [20 + cp -> problemName () . length ()];
00386
00387 sprintf (txtFileName, "%s-sol.txt", cp -> problemName (). c_str ());
00388
00389 FILE *txtSol = fopen (txtFileName, "w");
00390
00391 if (txtSol == NULL) {
00392
00393 printf ("Could not create file %s for solving solution\n", txtFileName);
00394
00395 } else {
00396
00397 cp -> domain () -> push (cp -> nOrigVars (), rs -> getSol (), NULL, NULL);
00398
00399 cp -> initAuxs ();
00400
00401 for (std::vector <exprVar *>::iterator it = cp -> Variables (). begin ();
00402 it != cp -> Variables(). end (); ++it) {
00403
00404 if ((*it) -> Index () >= cp -> nOrigVars ())
00405 continue;
00406
00407 if ((*it) -> Multiplicity () == 0) {
00408
00409 if ((*it) -> Image ()) fprintf (txtSol, "%d %e\n", (*it) -> Index (), (*(*it) -> Image ()) ());
00410 else fprintf (txtSol, "%d %e\n", (*it) -> Index (), 0);
00411
00412 } else fprintf (txtSol, "%d %e\n", (*it) -> Index (), (*(*it)) ());
00413 }
00414
00415 cp -> domain () -> pop ();
00416 }
00417
00418 fclose (txtSol);
00419
00420 delete [] txtFileName;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430 if(rs->getHasSol()) {
00431 if(cbcLb > rs->getVal()) {
00432
00433 cbcLb = rs->getVal();
00434 }
00435 printObj = rs->getVal();
00436
00437 }
00438 delete[] modCbcSol;
00439 delete[] modCouenneSol;
00440 }
00441
00442 #endif
00443
00444 #ifdef FM_FRES
00445 if(cp != NULL) {
00446 FILE *f_res = NULL;
00447 f_res = fopen("fres.xxx", "r");
00448 if(f_res == NULL) {
00449 f_res = fopen("fres.xxx", "w");
00450 fprintf(f_res, "END_OF_HEADER\n");
00451 }
00452 else {
00453 fclose(f_res);
00454 f_res = fopen("fres.xxx", "a");
00455 }
00456 char *pbName, shortName[256];
00457
00458 pbName = strdup(cp -> problemName ().c_str ());
00459 char *f_name_pos = strrchr(pbName, '/');
00460 if(f_name_pos != NULL) {
00461 strcpy(shortName, &(f_name_pos[1]));
00462 }
00463 else {
00464 strcpy(shortName, pbName);
00465 }
00466
00467
00468 fprintf(f_res, "%20s ", shortName);
00469 if((cbcLb > 1e20) || (cbcLb < -1e20)) {
00470 fprintf(f_res, "%10.4g", cbcLb);
00471 }
00472 else {
00473 fprintf(f_res, "%10.4f", cbcLb);
00474 }
00475 if(foundSol) {
00476 fprintf(f_res, " %10.4f", printObj);
00477 }
00478 else {
00479 fprintf(f_res, " *");
00480 }
00481 fprintf(f_res, " %10d %10.4f\n", infeasible ? 0 : bb.numNodes (),
00482 CoinCpuTime () - time_start);
00483 fclose(f_res);
00484 }
00485 #endif
00486
00487
00488
00489
00490 double global_opt;
00491 couenne.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00492
00493 double
00494 ub = infeasible ? COIN_DBL_MAX : bb. model (). getObjValue (),
00495 lb = infeasible ? -COIN_DBL_MAX : bb. model (). getBestPossibleObjValue ();
00496
00497 if (cp -> getRecordBestSol () &&
00498 cp -> getRecordBestSol () -> getHasSol () &&
00499 (ub > cp -> getRecordBestSol () -> getVal ()))
00500 ub = cp -> getRecordBestSol () -> getVal ();
00501
00502 if (false ||
00503 (lb > ub))
00504 lb = ub;
00505
00506 char
00507 *gapstr = new char [40],
00508 *lbstr = new char [40],
00509 *ubstr = new char [40];
00510
00511
00512
00513
00514
00515 sprintf (lbstr, "%10g", lb);
00516 sprintf (ubstr, "%10g", ub);
00517 if(ub > COUENNE_INFINITY/1e4) {
00518 sprintf (gapstr, "--");
00519 }
00520 else {
00521 sprintf (gapstr, "%.2f%%", fabs (100. * (ub - lb) / (1. + fabs (lb))));
00522 }
00523
00524 if (!infeasible)
00525 jnlst -> Printf (J_ERROR, J_COUENNE, "\n\
00526 Linearization cuts added at root node: %8d\n\
00527 Linearization cuts added in total: %8d (separation time: %gs)\n",
00528 nr, nt, st);
00529
00530 else jnlst -> Printf (J_ERROR, J_COUENNE, "Problem infeasible\n");
00531
00532 jnlst -> Printf (J_NONE, J_COUENNE, "\
00533 Total solve time: %8gs (%gs in branch-and-bound)\n\
00534 Lower bound: %s\n\
00535 Upper bound: %s (gap: %s)\n\
00536 Branch-and-bound nodes: %8d\n",
00537 CoinCpuTime () - time_start,
00538 cg ? (CoinCpuTime () - CoinMax (time_start, cg -> rootTime ())) : CoinCpuTime () - time_start,
00539 ((lb <= -8.9999e12) ||
00540 infeasible || (fabs (lb) > COUENNE_INFINITY/1e4)) ? " -inf" : lbstr,
00541 ((retcomp < 0) || infeasible || (ub > COUENNE_INFINITY/1e4)) ? " inf" : ubstr,
00542 ( infeasible || (CoinMax (fabs (lb), fabs (ub)) > COUENNE_INFINITY/1e4)) ? "--" : gapstr,
00543 infeasible ? 0 : bb.numNodes ());
00544
00545
00546
00547
00548
00549 delete [] lbstr;
00550 delete [] ubstr;
00551 delete [] gapstr;
00552
00553 if (global_opt < COUENNE_INFINITY) {
00554
00555 double opt = infeasible ? -COIN_DBL_MAX : bb.model (). getBestPossibleObjValue ();
00556
00557 printf ("Global Optimum Test on %-40s %s\n",
00558 cp ? cp -> problemName ().c_str () : "unknown",
00559 (fabs (opt - global_opt) /
00560 (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ?
00561 (const char *) "OK" : (const char *) "FAILED");
00562
00563
00564
00565 } else
00566
00567 if (couenne.displayStats ()) {
00568
00569 if (cg && !cp) printf ("Warning, could not get pointer to problem\n");
00570 else
00571 printf ("Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
00572 "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
00573 #ifdef COIN_HAS_NTY
00574 "%20e [lower] %20e [upper] %7d [nodes] %.0g [sg] %d [sgc]\n",
00575 #else
00576 "%20e [lower] %20e [upper] %7d [nodes]\n",
00577 #endif
00578 cp ? cp -> problemName (). c_str () : "unknown",
00579 cp ? cp -> nOrigVars () : -1,
00580 cp ? cp -> nOrigIntVars () : -1,
00581 cp ? cp -> nOrigCons () : -1,
00582 cp ? (cp -> nVars () -
00583 cp -> nOrigVars ()) : -1,
00584 nr, nt, st,
00585 CoinCpuTime () - time_start,
00586 cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
00587 lb,
00588 ub,
00589
00590
00591 infeasible ? 0 : bb.numNodes ()
00592 #ifdef COIN_HAS_NTY
00593 ,symmGroupSize
00594 ,CouenneBranchingObject::nSGcomputations
00595 #endif
00596 );
00597
00598
00599 }
00600 }
00601 catch(Bonmin::TNLPSolver::UnsolvedError *E) {
00602 E->writeDiffFiles();
00603 E->printError(std::cerr);
00604
00605
00606
00607
00608 }
00609 catch (Bonmin::OsiTMINLPInterface::SimpleError &E) {
00610 std::cerr<<E.className()<<"::"<<E.methodName()
00611 <<std::endl
00612 <<E.message()<<std::endl;
00613 }
00614 catch (CoinError &E) {
00615 std::cerr<<E.className()<<"::"<<E.methodName()
00616 <<std::endl
00617 <<E.message()<<std::endl;
00618 }
00619 catch (Ipopt::OPTION_INVALID &E)
00620 {
00621 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 delete [] pbName;
00635 return 0;
00636 }