source: trunk/Couenne/src/main/BonCouenne.cpp @ 586

Last change on this file since 586 was 586, checked in by fmargot, 9 years ago

Couenne/src/main/BonCouenne.cpp: add ifdef FM_RES for storing results of
several runs; Best value found and required tolearance now printed at the
end of the run.

Couenne/src/branch/CouenneChooseStrong.hpp: add minDepthPrint_ to the class;
add method gutsOfSetupList() to the class.

Couenne/src/branch/CouenneChooseStrong.cpp: add minDepthPrint_ to the class;
complete rewrite of CouenneChooseStrong::chooseVariable(), treating carefully
OsiSimpleInteger? objects to avoid inconsistant branching; new version is used
only if FM_MOD is defined, otherwise the older version is used (for comparison
purposes); add method gutsOfSetupList() to give the option of selecting objects
according to priority and usefulness more precisely than
Bonmin::BonChooseVariable::setupList(); add ifdef FM_SORT_STRONG
to activate sorting when FM_MOD is set. Add debugging ifdefs TRACE_STRONG
and TRACE_STRONG2.

Couenne/src/branch/doStrongBranching.cpp: Modif. doStrongBranching() to
make sure that OsiSimpleInteger? objects for which the branching point is
outside the current solver bounds do not enlarge the feasible set when branched
on; make sure that bounds from solver and from problem are intersected.
Add debugging ifdefs TRACE_STRONG and TRACE_STRONG2.

Couenne/src/problem/CouenneProblem.hpp/cpp: add lastPrioSort_ and corresp.
set/get methods.

Couenne/src/problem/CouenneProblemConstructors.hpp: add lastPrioSort_.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1// $Id: BonCouenne.cpp 586 2011-05-29 11:25:38Z fmargot $
2//
3// (C) Copyright International Business Machines Corporation and Carnegie Mellon University 2006, 2007
4// All Rights Reserved.
5// This code is published under the Eclipse Public License (EPL).
6//
7// Authors :
8// Pietro Belotti, Carnegie Mellon University,
9// Pierre Bonami, International Business Machines Corporation
10//
11// Date : 12/19/2006
12
13
14#if defined(_MSC_VER)
15// Turn off compiler warning about long names
16#  pragma warning(disable:4786)
17#endif
18#include <iomanip>
19#include <fstream>
20
21#include <stdlib.h>
22
23#include "CoinTime.hpp"
24#include "CoinError.hpp"
25#include "BonCouenneInterface.hpp"
26
27#include "BonCouenneSetup.hpp"
28
29#include "BonCbc.hpp"
30
31#include "CbcCutGenerator.hpp"
32#include "CouenneProblem.hpp"
33#include "CouenneCutGenerator.hpp"
34
35#include "CouenneRecordBestSol.hpp"
36
37using namespace Couenne;
38
39// the maximum difference between a printed optimum and a CouNumber
40#define PRINTED_PRECISION 1e-5
41
42#include "CouenneExprVar.hpp"
43#include "CouenneExprConst.hpp"
44#include "CouenneExprSum.hpp"
45#include "CouenneExprClone.hpp"
46#include "CouenneProblemElem.hpp"
47#include "CouenneProblem.hpp"
48#include "CouenneJournalist.hpp"
49
50#ifdef COIN_HAS_NTY
51int nOrbBr = 0;
52#endif
53
54#include "CoinSignal.hpp"
55
56extern "C" {
57
58  static int nInterrupts = 0;
59  static void signal_handler (int sig) {
60
61    if (!nInterrupts) {
62      std::cerr << "[BREAK]" << std::endl;
63      abort ();
64    }
65    return;
66  }
67}
68
69//#define FM_FRES
70
71int main (int argc, char *argv[]) {
72
73  //CoinSighandler_t saveSignal = SIG_DFL;
74  //saveSignal = signal (SIGINT, signal_handler);
75
76    printf ("Couenne %s --  an Open-Source solver for Mixed Integer Nonlinear Optimization\n\
77Mailing list: couenne@list.coin-or.org\n\
78Instructions: http://www.coin-or.org/Couenne\n", 
79            strcmp (COUENNE_VERSION, "trunk") ? COUENNE_VERSION : "");
80
81  WindowsErrorPopupBlocker();
82  using namespace Ipopt;
83
84  char * pbName = NULL;
85
86  const int infeasible = 1;
87
88  try {
89
90    Bonmin::Bab bb;
91    bb.setUsingCouenne (true);
92
93    CouenneProblem *p = NULL;
94    CouenneInterface *ci = NULL;
95
96#if 0
97    //ci = new CouenneInterface;
98    p = new CouenneProblem;
99
100    p -> addVariable (false, p -> domain ());
101    p -> addVariable (false, p -> domain ());
102    p -> addVariable (false, p -> domain ());
103    p -> addVariable (false, p -> domain ());
104
105    p -> addObjective    (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), "min");
106    p -> addLEConstraint (new exprSum (new exprClone (p->Var (0)), new exprClone (p->Var (2))),
107                          new exprConst (1));
108    p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))),
109                          new exprConst (1));
110    p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (3))),
111                          new exprConst (1));
112    p -> addEQConstraint (new exprSum (new exprClone (p->Var (2)), new exprClone (p->Var (3))),
113                          new exprConst (1));
114#endif
115
116    CouenneSetup couenne;
117    if (!couenne.InitializeCouenne (argv, p, NULL, ci, &bb))
118      throw infeasible;
119
120#ifdef FM_PRINT_INFO
121    // This assumes that first cut generator is CouenneCutGenerator
122    CouenneCutGenerator *ccg = dynamic_cast<CouenneCutGenerator *> 
123      (couenne.cutGenerators().begin()->cgl);
124    if(ccg) {
125      ccg->setBabPtr(&bb);
126    }
127    else {
128      printf("main(): ### ERROR: Can not get CouenneCutGenerator\n");
129      exit(1);
130    }
131#endif
132
133    // initial printout
134
135    ConstJnlstPtr jnlst = couenne. couennePtr () -> Jnlst ();
136
137    CouenneProblem *prob = couenne. couennePtr () -> Problem ();
138
139    jnlst -> Printf (J_ERROR, J_COUENNE, "\
140Loaded instance \"%s\"\n\
141Constraints:     %8d\n\
142Variables:       %8d (%d integer)\n\
143Auxiliaries:     %8d (%d integer)\n\n",
144                     prob -> problemName ().c_str (),
145                     prob -> nOrigCons (),
146                     prob -> nOrigVars (),
147                     prob -> nOrigIntVars (),
148                     prob -> nVars    () - prob -> nOrigVars (),
149                     prob -> nIntVars () - prob -> nOrigIntVars ());
150
151    double time_start = CoinCpuTime();
152
153#if 0
154    CouenneFeasibility feasibility;
155    bb.model().setProblemFeasibility (feasibility);
156#endif
157
158    /// update time limit (read/preprocessing might have taken some)
159    double timeLimit = 0;
160    couenne.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
161    couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime, 
162                                CoinMax (1., timeLimit - time_start));
163
164    jnlst -> Printf (J_ERROR, J_COUENNE, "Starting branch-and-bound\n");
165
166    //////////////////////////////////
167
168    bb (couenne); // do branch and bound
169
170#ifdef COIN_HAS_NTY
171    if (nOrbBr)
172      printf ("%d orbital nontrivial branchings\n", nOrbBr);
173#endif
174
175    //////////////////////////////////
176
177    std::cout.precision (10);
178
179    //////////////////////////////
180    CouenneCutGenerator *cg = NULL;
181
182    // there is only one cut generator, so scan array until
183    // dynamic_cast returns non-NULL
184
185    if (bb.model (). cutGenerators ()) {
186
187      int nGen = bb.model (). numberCutGenerators ();
188     
189      for (int i=0; !cg && i < nGen; i++)
190        cg = dynamic_cast <CouenneCutGenerator *> 
191          (bb.model (). cutGenerators () [i] -> generator ());
192    }
193
194    ////////////////////////////////
195    int nr=-1, nt=-1;
196    double st=-1;
197
198    if (cg) cg -> getStats (nr, nt, st);
199    else printf ("Warning, could not get pointer to CouenneCutGenerator\n");
200
201    CouenneProblem *cp = cg ? cg -> Problem () : NULL;
202
203    double cbcLb = bb.model ().getBestPossibleObjValue();
204    double printObj = 0;
205    bool foundSol = false;
206
207#ifdef FM_TRACE_OPTSOL
208
209    FILE *fSol = fopen("bidon.sol", "w");
210    if(fSol == NULL) {
211      printf("### ERROR: can not open bidon.sol\n");
212      exit(1);
213    }
214
215    if(cp != NULL) {
216      double cbcObjVal = bb.model().getObjValue();
217      int modelNvars = bb.model().getNumCols();
218
219      CouenneRecordBestSol *rs = cp->getRecordBestSol(); 
220      const double *cbcSol = bb.model().getColSolution();
221      double *modCbcSol = new double[modelNvars];
222      double modCbcSolVal= 1e100, modCbcSolMaxViol = 0;
223      bool cbcSolIsFeas = false;
224
225      if(modelNvars != cp->nVars()) {
226        printf("### ERROR: modelNvars: %d nVars: %d\n", 
227               modelNvars, cp->nVars());
228        exit(1);
229      }
230
231      if(cbcObjVal < 1e49) {
232
233#ifdef FM_CHECKNLP2
234        int cMS = rs->getCardModSol();
235        cbcSolIsFeas = cp->checkNLP2(cbcSol, 0, false, // do not care about obj
236                                     false, // do not stop at first viol
237                                     true, // checkAll
238                                     cp->getFeasTol());
239        CoinCopyN(rs->getModSol(cMS), cMS, modCbcSol);
240        modCbcSolVal = rs->getModSolVal();
241        modCbcSolMaxViol = rs->getModSolMaxViol();
242#else /* not FM_CHECKNLP2 */
243        int cMS = cp->nVars();
244        cbcSolIsFeas = cp->checkNLP(cbcSol, modCbcSolVal, true);
245        CoinCopyN(cbcSol, cMS, modCbcSol);
246        modCbcSolMaxViol = cp->getFeasTol();
247#endif /* not FM_CHECKNLP2 */
248        foundSol = true;
249      }
250
251      const double *couenneSol = rs->getSol();
252      double *modCouenneSol = new double[modelNvars];
253      double modCouenneSolVal= 1e100, modCouenneSolMaxViol = 0;
254      bool couenneSolIsFeas = false;
255
256      if(couenneSol != NULL) {
257#ifdef FM_CHECKNLP2
258        couenneSolIsFeas = cp->checkNLP2(couenneSol, 0, false, 
259                                         false, true, 
260                                         cp->getFeasTol());
261        int cMS = rs->getCardModSol();
262        CoinCopyN(rs->getModSol(cMS), cMS, modCouenneSol);
263        modCouenneSolVal = rs->getModSolVal();
264        modCouenneSolMaxViol = rs->getModSolMaxViol();
265#else /* not FM_CHECKNLP2 */
266        couenneSolIsFeas = cp->checkNLP(couenneSol, modCouenneSolVal, true);
267        int cMS = cp->nVars();
268        CoinCopyN(couenneSol, cMS, modCouenneSol);
269        modCouenneSolMaxViol = cp->getFeasTol();
270#endif /* not FM_CHECKNLP2 */
271        foundSol = true;
272      }
273
274      int retcomp = rs->compareAndSave(modCbcSol, modCbcSolVal, 
275                                       modCbcSolMaxViol, cbcSolIsFeas,
276                                       modCouenneSol, modCouenneSolVal, 
277                                       modCouenneSolMaxViol, couenneSolIsFeas, 
278                                       modelNvars, cp->getFeasTol());
279      switch (retcomp) {
280      case -1: printf("No solution found\n"); break;
281      case 0: printf("Best solution found by Cbc  Value: %10.4f  Tolerance: %10g\n", modCbcSolVal, modCbcSolMaxViol); break;
282      case 1: printf("Best solution found by Couenne  Value: %10.4f  Tolerance: %10g\n", modCouenneSolVal, modCouenneSolMaxViol); break;
283      default: break; // never happens
284      }
285
286      if(rs->getHasSol()) {
287        if(cbcLb > rs->getVal()) { // Best sol found by Couenne and not
288                                   // transmitted to Cbc
289          cbcLb = rs->getVal();
290        }
291        printObj = rs->getVal();
292        rs->printSol(fSol);
293      }
294      delete[] modCbcSol;
295      delete[] modCouenneSol;
296    }
297    fclose(fSol);
298#endif /* FM_TRACE_OPTSOL */
299
300#ifdef FM_FRES
301    if(cp != NULL) {
302      FILE *f_res = fopen("fres.xxx", "a");
303      char *pbName, shortName[256]; 
304     
305      pbName = strdup(cp -> problemName ().c_str ());
306      char *f_name_pos = strrchr(pbName, '/');
307      if(f_name_pos != NULL) {
308        strcpy(shortName, &(f_name_pos[1]));
309      }
310      else {
311        strcpy(shortName, pbName);
312      }
313     
314      fprintf(f_res, "%20s %10.4f", shortName, cbcLb);
315      if(foundSol) {
316        fprintf(f_res, " %10.4f", printObj);
317      }
318      else {
319        fprintf(f_res, "         *");
320      }
321      fprintf(f_res, " %10d %10.4f\n", bb.numNodes (),
322              CoinCpuTime () - time_start);
323      fclose(f_res);
324    }
325#endif
326
327    // retrieve test value to check
328    double global_opt;
329    couenne.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
330
331    double 
332      ub = bb.model (). getObjValue (),
333      lb = bb.model (). getBestPossibleObjValue ();
334
335    char *gapstr = new char [80];
336
337    sprintf (gapstr, "%.2f%%", 100. * (ub - lb) / (1. + fabs (lb)));
338
339    jnlst -> Printf (J_ERROR, J_COUENNE, "\n\
340Linearization cuts added at root node:   %8d\n\
341Linearization cuts added in total:       %8d  (separation time: %gs)\n\
342Total solving time:                      %8gs (%gs in branch-and-bound)\n\
343Lower bound:                           %10g\n\
344Upper bound:                           %10g  (gap: %s)\n\
345Branch-and-bound nodes:                  %8d\n\n",
346                     nr, nt, st, 
347                     CoinCpuTime () - time_start,
348                     cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
349                     lb, 
350                     ub,
351                     (ub > COUENNE_INFINITY/1e4) ? "inf" : gapstr,
352                     bb.numNodes ());
353
354    delete [] gapstr;
355
356    if (global_opt < COUENNE_INFINITY) { // some value found in couenne.opt
357
358      double opt = bb.model (). getBestPossibleObjValue ();
359
360      printf ("Global Optimum Test on %-40s %s\n", 
361              cp ? cp -> problemName ().c_str () : "unknown", 
362              (fabs (opt - global_opt) / 
363               (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ? 
364              (const char *) "OK" : (const char *) "FAILED");
365              //opt, global_opt,
366              //fabs (opt - global_opt));
367
368    } else // good old statistics
369
370    if (couenne.displayStats ()) { // print statistics
371
372      // CAUTION: assuming first cut generator is our CouenneCutGenerator
373
374      if (cg && !cp) printf ("Warning, could not get pointer to problem\n");
375      else
376        printf ("Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
377                "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
378                "%20e [lower] %20e [upper] %7d [nodes]\n",// %s %s\n",
379                cp ? cp -> problemName (). c_str () : "unknown",
380                (cp) ? cp -> nOrigVars     () : -1, 
381                (cp) ? cp -> nOrigIntVars  () : -1, 
382                (cp) ? cp -> nOrigCons     () : -1,
383                (cp) ? (cp -> nVars     () - 
384                        cp -> nOrigVars ()): -1,
385                nr, nt, st, 
386                CoinCpuTime () - time_start,
387                cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
388                bb.model (). getBestPossibleObjValue (),
389                bb.model (). getObjValue (),
390                //bb.bestBound (),
391                //bb.bestObj (),
392                bb.numNodes ());
393                //bb.iterationCount ());
394                //status.c_str (), message.c_str ());
395    }
396
397//    nlp_and_solver -> writeAmplSolFile (message, bb.bestSolution (), NULL);
398  }
399  catch(Bonmin::TNLPSolver::UnsolvedError *E) {
400     E->writeDiffFiles();
401     E->printError(std::cerr);
402    //There has been a failure to solve a problem with Ipopt.
403    //And we will output file with information on what has been changed in the problem to make it fail.
404    //Now depending on what algorithm has been called (B-BB or other) the failed problem may be at different place.
405    //    const OsiSolverInterface &si1 = (algo > 0) ? nlpSolver : *model.solver();
406  }
407  catch (Bonmin::OsiTMINLPInterface::SimpleError &E) {
408    std::cerr<<E.className()<<"::"<<E.methodName()
409             <<std::endl
410             <<E.message()<<std::endl;
411  }
412  catch (CoinError &E) {
413    std::cerr<<E.className()<<"::"<<E.methodName()
414             <<std::endl
415             <<E.message()<<std::endl;
416  }
417  catch (Ipopt::OPTION_INVALID &E)
418  {
419   std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
420  }
421  catch (int generic_error) {
422    if (generic_error == infeasible)
423      printf ("problem infeasible\n");
424  }
425
426//  catch(...) {
427//    std::cerr<<pbName<<" unrecognized excpetion"<<std::endl;
428//    std::cerr<<pbName<<"\t Finished \t exception"<<std::endl;
429//    throw;
430//  }
431
432  delete [] pbName;
433  return 0;
434}
Note: See TracBrowser for help on using the repository browser.