00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #if defined(_MSC_VER)
00014
00015 # pragma warning(disable:4786)
00016 #endif
00017
00018 #include <iomanip>
00019 #include <fstream>
00020
00021 #include <stdlib.h>
00022
00023 #include "CoinTime.hpp"
00024 #include "CoinError.hpp"
00025 #include "BonCouenneInterface.hpp"
00026
00027 #include "BonCouenneSetup.hpp"
00028
00029 #include "BonCbc.hpp"
00030 #include "CouenneBab.hpp"
00031
00032 #include "CbcCutGenerator.hpp"
00033 #include "CouenneProblem.hpp"
00034 #include "CouenneCutGenerator.hpp"
00035
00036 #include "CouenneRecordBestSol.hpp"
00037
00038 using namespace Couenne;
00039
00040
00041 #define PRINTED_PRECISION 1e-5
00042
00043 #include "CouenneExprVar.hpp"
00044 #include "CouenneExprConst.hpp"
00045 #include "CouenneExprSum.hpp"
00046 #include "CouenneExprClone.hpp"
00047 #include "CouenneProblemElem.hpp"
00048 #include "CouenneProblem.hpp"
00049 #include "CouenneJournalist.hpp"
00050
00051 #ifdef COIN_HAS_NTY
00052
00053 #include "CouenneBranchingObject.hpp"
00054 #endif
00055
00056 #include "CoinSignal.hpp"
00057
00058 #if 0
00059 extern "C" {
00060
00061 static int nInterrupts = 0;
00062 static void signal_handler (int sig) {
00063
00064 if (!nInterrupts) {
00065 std::cerr << "[BREAK]" << std::endl;
00066 abort ();
00067 }
00068 return;
00069 }
00070 }
00071 #endif
00072
00073
00074
00075 int main (int argc, char *argv[]) {
00076
00077
00078
00079
00080 printf ("Couenne %s -- an Open-Source solver for Mixed Integer Nonlinear Optimization\n\
00081 Mailing list: couenne@list.coin-or.org\n\
00082 Instructions: http://www.coin-or.org/Couenne\n",
00083 strcmp (COUENNE_VERSION, "trunk") ? COUENNE_VERSION : "");
00084
00085 WindowsErrorPopupBlocker();
00086 using namespace Ipopt;
00087
00088 char * pbName = NULL;
00089
00090 const int infeasible = 1;
00091
00092 try {
00093
00094 CouenneBab bb;
00095
00096
00097 CouenneProblem *p = NULL;
00098 CouenneInterface *ci = NULL;
00099
00100 #if 0
00101
00102 p = new CouenneProblem;
00103
00104 p -> addVariable (false, p -> domain ());
00105 p -> addVariable (false, p -> domain ());
00106 p -> addVariable (false, p -> domain ());
00107 p -> addVariable (false, p -> domain ());
00108
00109 p -> addObjective (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), "min");
00110 p -> addLEConstraint (new exprSum (new exprClone (p->Var (0)), new exprClone (p->Var (2))), new exprConst (1));
00111 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), new exprConst (1));
00112 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (3))), new exprConst (1));
00113 p -> addEQConstraint (new exprSum (new exprClone (p->Var (2)), new exprClone (p->Var (3))), new exprConst (1));
00114 #endif
00115
00116 CouenneSetup couenne;
00117
00118 if (!couenne.InitializeCouenne (argv, p, NULL, ci, &bb))
00119 throw infeasible;
00120
00122 CouenneCutGenerator *cg = NULL;
00123
00124
00125
00126
00127 if (couenne. cutGenerators () . size () > 0) {
00128
00129 for (std::list <Bonmin::BabSetupBase::CuttingMethod>::iterator
00130 i = couenne.cutGenerators () . begin ();
00131 !cg && (i != couenne.cutGenerators () . end ());
00132 ++i)
00133
00134 cg = dynamic_cast <CouenneCutGenerator *> (i -> cgl);
00135 }
00136
00137
00138
00139
00140
00141 if (cg)
00142
00143 cg -> setBabPtr (&bb);
00144
00145 else {
00146 printf ("main(): ### ERROR: Can not get CouenneCutGenerator\n");
00147 exit (1);
00148 }
00149
00150
00151
00152 ConstJnlstPtr jnlst = couenne. couennePtr () -> Jnlst ();
00153
00154 CouenneProblem *prob = couenne. couennePtr () -> Problem ();
00155
00156 bb. setProblem (prob);
00157
00158 jnlst -> Printf (J_ERROR, J_COUENNE, "\
00159 Loaded instance \"%s\"\n\
00160 Constraints: %8d\n\
00161 Variables: %8d (%d integer)\n\
00162 Auxiliaries: %8d (%d integer)\n\n",
00163 prob -> problemName ().c_str (),
00164 prob -> nOrigCons (),
00165 prob -> nOrigVars (),
00166 prob -> nOrigIntVars (),
00167 prob -> nVars () - prob -> nOrigVars (),
00168 CoinMax (0, prob -> nIntVars () - prob -> nOrigIntVars ()));
00169
00170 double time_start = CoinCpuTime();
00171
00172 #if 0
00173 CouenneFeasibility feasibility;
00174 bb.model().setProblemFeasibility (feasibility);
00175 #endif
00176
00178 double timeLimit = 0;
00179 couenne.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00180 couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime,
00181 CoinMax (1., timeLimit - time_start));
00182
00183
00184
00186
00187 bb (couenne);
00188
00189 #ifdef COIN_HAS_NTY
00190 if (CouenneBranchingObject::nOrbBr)
00191 printf ("%d orbital nontrivial branchings\n", CouenneBranchingObject::nOrbBr);
00192 #endif
00193
00194 std::cout.precision (10);
00195
00196 int nr=-1, nt=-1;
00197 double st=-1;
00198
00199 if (cg) cg -> getStats (nr, nt, st);
00200 else printf ("Warning, could not get pointer to CouenneCutGenerator\n");
00201
00202 CouenneProblem *cp = cg ? cg -> Problem () : NULL;
00203
00204 #if defined (FM_TRACE_OPTSOL) || defined (FM_FRES)
00205 double cbcLb = bb.model ().getBestPossibleObjValue();
00206 double printObj = 0;
00207 bool foundSol = false;
00208 #endif
00209
00210 #ifdef FM_TRACE_OPTSOL
00211
00212
00213
00214
00215
00216
00217
00218
00219 if(cp != NULL) {
00220 double cbcObjVal = bb.model().getObjValue();
00221 int modelNvars = bb.model().getNumCols();
00222
00223 CouenneRecordBestSol *rs = cp->getRecordBestSol();
00224 const double *cbcSol = bb.model().getColSolution();
00225 double *modCbcSol = new double[modelNvars];
00226 double modCbcSolVal= 1e100, modCbcSolMaxViol = 0;
00227 bool cbcSolIsFeas = false;
00228
00229 if(modelNvars != cp->nVars()) {
00230 printf("### ERROR: modelNvars: %d nVars: %d\n",
00231 modelNvars, cp->nVars());
00232 exit(1);
00233 }
00234
00235 if(cbcObjVal < 1e49) {
00236
00237 #ifdef FM_CHECKNLP2
00238 int cMS = rs->getCardModSol();
00239 cbcSolIsFeas = cp->checkNLP2(cbcSol, 0, false,
00240 false,
00241 true,
00242 cp->getFeasTol());
00243 CoinCopyN(rs->getModSol(cMS), cMS, modCbcSol);
00244 modCbcSolVal = rs->getModSolVal();
00245 modCbcSolMaxViol = rs->getModSolMaxViol();
00246 #else
00247 int cMS = cp->nVars();
00248 cbcSolIsFeas = cp->checkNLP(cbcSol, modCbcSolVal, true);
00249 CoinCopyN(cbcSol, cMS, modCbcSol);
00250 modCbcSolMaxViol = cp->getFeasTol();
00251 #endif
00252 foundSol = true;
00253 }
00254
00255 const double *couenneSol = rs->getSol();
00256 double *modCouenneSol = new double[modelNvars];
00257 double modCouenneSolVal= 1e100, modCouenneSolMaxViol = 0;
00258 bool couenneSolIsFeas = false;
00259
00260 if(couenneSol != NULL) {
00261 #ifdef FM_CHECKNLP2
00262 couenneSolIsFeas = cp->checkNLP2(couenneSol, 0, false,
00263 false, true,
00264 cp->getFeasTol());
00265 int cMS = rs->getCardModSol();
00266 CoinCopyN(rs->getModSol(cMS), cMS, modCouenneSol);
00267 modCouenneSolVal = rs->getModSolVal();
00268 modCouenneSolMaxViol = rs->getModSolMaxViol();
00269 #else
00270 couenneSolIsFeas = cp->checkNLP(couenneSol, modCouenneSolVal, true);
00271 int cMS = cp->nVars();
00272 CoinCopyN(couenneSol, cMS, modCouenneSol);
00273 modCouenneSolMaxViol = cp->getFeasTol();
00274 #endif
00275 foundSol = true;
00276 }
00277
00278 int retcomp = rs->compareAndSave(modCbcSol, modCbcSolVal,
00279 modCbcSolMaxViol, cbcSolIsFeas,
00280 modCouenneSol, modCouenneSolVal,
00281 modCouenneSolMaxViol, couenneSolIsFeas,
00282 modelNvars, cp->getFeasTol());
00283 switch (retcomp) {
00284 case -1: printf("No solution found\n"); break;
00285 case 0: printf("Best solution found by Cbc. Value: %10.4f. Tolerance: %10g\n", modCbcSolVal, modCbcSolMaxViol); break;
00286 case 1:
00287 default: break;
00288 }
00289
00290 if(rs->getHasSol()) {
00291 if(cbcLb > rs->getVal()) {
00292
00293 cbcLb = rs->getVal();
00294 }
00295 printObj = rs->getVal();
00296
00297 }
00298 delete[] modCbcSol;
00299 delete[] modCouenneSol;
00300 }
00301
00302 #endif
00303
00304 #ifdef FM_FRES
00305 if(cp != NULL) {
00306 FILE *f_res = NULL;
00307 f_res = fopen("fres.xxx", "r");
00308 if(f_res == NULL) {
00309 f_res = fopen("fres.xxx", "w");
00310 fprintf(f_res, "END_OF_HEADER\n");
00311 }
00312 else {
00313 fclose(f_res);
00314 f_res = fopen("fres.xxx", "a");
00315 }
00316 char *pbName, shortName[256];
00317
00318 pbName = strdup(cp -> problemName ().c_str ());
00319 char *f_name_pos = strrchr(pbName, '/');
00320 if(f_name_pos != NULL) {
00321 strcpy(shortName, &(f_name_pos[1]));
00322 }
00323 else {
00324 strcpy(shortName, pbName);
00325 }
00326
00327 fprintf(f_res, "%20s %10.4f", shortName, cbcLb);
00328 if(foundSol) {
00329 fprintf(f_res, " %10.4f", printObj);
00330 }
00331 else {
00332 fprintf(f_res, " *");
00333 }
00334 fprintf(f_res, " %10d %10.4f\n", bb.numNodes (),
00335 CoinCpuTime () - time_start);
00336 fclose(f_res);
00337 }
00338 #endif
00339
00340
00341 double global_opt;
00342 couenne.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00343
00344 double
00345 ub = bb. model (). getObjValue (),
00346 lb = bb. model (). getBestPossibleObjValue ();
00347
00348 if (cp -> getRecordBestSol () &&
00349 (ub > cp -> getRecordBestSol () -> getVal ())) ub = cp -> getRecordBestSol () -> getVal ();
00350
00351 if ((fabs (lb) > COUENNE_INFINITY / 1e4) ||
00352 (lb > ub)) lb = ub;
00353
00354 char
00355 *gapstr = new char [80],
00356 *lbstr = new char [80],
00357 *ubstr = new char [80];
00358
00359 sprintf (lbstr, "%10g", lb);
00360 sprintf (ubstr, "%10g", ub);
00361 sprintf (gapstr, "%.2f%%", fabs (100. * (ub - lb) / (1. + fabs (lb))));
00362
00363 jnlst -> Printf (J_ERROR, J_COUENNE, "\n\
00364 Linearization cuts added at root node: %8d\n\
00365 Linearization cuts added in total: %8d (separation time: %gs)\n\
00366 Total solving time: %8gs (%gs in branch-and-bound)\n\
00367 Lower bound: %s\n\
00368 Upper bound: %s (gap: %s)\n\
00369 Branch-and-bound nodes: %8d\n",
00370 nr, nt, st,
00371 CoinCpuTime () - time_start,
00372 cg ? (CoinCpuTime () - CoinMax (time_start, cg -> rootTime ())) : CoinCpuTime () - time_start,
00373 (lb < -9e12) ||
00374 (lb > COUENNE_INFINITY/1e4) ? " -inf" : lbstr,
00375 (ub > COUENNE_INFINITY/1e4) ? " inf" : ubstr,
00376 (ub > COUENNE_INFINITY/1e4) ? "--" : gapstr,
00377 bb.numNodes ());
00378
00379 if (fabs (ub - bb. model (). getObjValue ()) > COUENNE_EPS * fabs (ub))
00380 jnlst -> Printf (J_ERROR, J_COUENNE,
00381 "Warning: upper bounds differ between Couenne and Cbc. Saving Couenne's (more reliable).\n");
00382
00383 delete [] lbstr;
00384 delete [] ubstr;
00385 delete [] gapstr;
00386
00387 if (global_opt < COUENNE_INFINITY) {
00388
00389 double opt = bb.model (). getBestPossibleObjValue ();
00390
00391 printf ("Global Optimum Test on %-40s %s\n",
00392 cp ? cp -> problemName ().c_str () : "unknown",
00393 (fabs (opt - global_opt) /
00394 (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ?
00395 (const char *) "OK" : (const char *) "FAILED");
00396
00397
00398
00399 } else
00400
00401 if (couenne.displayStats ()) {
00402
00403 if (cg && !cp) printf ("Warning, could not get pointer to problem\n");
00404 else
00405 printf ("Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
00406 "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
00407 "%20e [lower] %20e [upper] %7d [nodes]\n",
00408 cp ? cp -> problemName (). c_str () : "unknown",
00409 (cp) ? cp -> nOrigVars () : -1,
00410 (cp) ? cp -> nOrigIntVars () : -1,
00411 (cp) ? cp -> nOrigCons () : -1,
00412 (cp) ? (cp -> nVars () -
00413 cp -> nOrigVars ()): -1,
00414 nr, nt, st,
00415 CoinCpuTime () - time_start,
00416 cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
00417 lb,
00418 ub,
00419
00420
00421 bb.numNodes ());
00422
00423
00424 }
00425
00426
00427 }
00428 catch(Bonmin::TNLPSolver::UnsolvedError *E) {
00429 E->writeDiffFiles();
00430 E->printError(std::cerr);
00431
00432
00433
00434
00435 }
00436 catch (Bonmin::OsiTMINLPInterface::SimpleError &E) {
00437 std::cerr<<E.className()<<"::"<<E.methodName()
00438 <<std::endl
00439 <<E.message()<<std::endl;
00440 }
00441 catch (CoinError &E) {
00442 std::cerr<<E.className()<<"::"<<E.methodName()
00443 <<std::endl
00444 <<E.message()<<std::endl;
00445 }
00446 catch (Ipopt::OPTION_INVALID &E)
00447 {
00448 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00449 }
00450 catch (int generic_error) {
00451 if (generic_error == infeasible)
00452 printf ("problem infeasible\n");
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 delete [] pbName;
00462 return 0;
00463 }