CouenneMINLPInterface.cpp
Go to the documentation of this file.
1 /* $Id: CouenneMINLPInterface.cpp 530 2011-03-12 16:52:06Z pbelotti $
2  *
3  * Name: CouenneMINLPInterface
4  * Author: Pietro Belotti
5  * Purpose: MINLP interface with computation of gradient and Jacobian
6  * through CouenneExpressions
7  *
8  * (C) Pietro Belotti 2010
9  * This file is licensed under the Eclipse Public License (EPL)
10  */
11 
13 
14 using namespace Couenne;
15 
18 
19 }
20 
24 
25  return 0.;
26 }
27 
28 
29 #if 0
30 //#include "BonminConfig.h"
31 
32 //#include "BonOsiTMINLPInterface.hpp"
33 #include "CoinTime.hpp"
34 #include <climits>
35 #include <string>
36 #include <sstream>
37 #include "BonAuxInfos.hpp"
38 
39 #include "Ipopt/BonIpoptSolver.hpp"
41 
42 #ifdef COIN_HAS_FILTERSQP
45 //#include "Filter/BonBqpdWarmStart.hpp"
46 #endif
47 
48 #include "OsiBranchingObject.hpp"
50 
51 //Macros to try and make messages definition less heavy
52 #include "BonMsgUtils.hpp"
53 
54 using namespace Ipopt;
55 using namespace Couenne;
56 
58 static void
61 {
62  roptions->SetRegisteringCategory("nlp interface option", RegisteredOptions::BonminCategory);
63  roptions->AddStringOption3("nlp_solver",
64  "Choice of the solver for local optima of continuous nlp's",
65  "Ipopt",
66  "Ipopt", "Interior Point OPTimizer (https://projects.coin-or.org/Ipopt)",
67  "filterSQP", "Sequential quadratic programming trust region "
68  "algorithm (http://www-unix.mcs.anl.gov/~leyffer/solvers.html)",
69  "all", "run all available solvers at each node",
70  "Note that option will work only if the specified solver has been installed. Ipopt will usualy be installed with Bonmin by default. For FilterSQP please see http://www-unix.mcs.anl.gov/~leyffer/solvers.html on how to obtain it and https://projects.coin-or.org/Bonmin/wiki/HintTricks on how to configure Bonmin to use it.");
71  roptions->setOptionExtraInfo("nlp_solver",15);
72  roptions->AddBoundedIntegerOption("nlp_log_level",
73  "specify NLP solver interface log level (independent from ipopt print_level).",
74  0,2,1,
75  "Set the level of output of the CouenneMINLPInterface : "
76  "0 - none, 1 - normal, 2 - verbose"
77  );
78  roptions->setOptionExtraInfo("nlp_log_level",15);
79 
80  roptions->AddStringOption2("file_solution",
81  "Write a file bonmin.sol with the solution",
82  "no",
83  "yes","",
84  "no","","");
85 
86  roptions->AddStringOption3("warm_start",
87  "Select the warm start method",
88  "none",
89  "none","No warm start",
90  "optimum","Warm start with direct parent optimum",
91  "interior_point","Warm start with an interior point of direct parent",
92  "This will affect the function getWarmStart(), and as a consequence the warm starting in the various algorithms.");
93  roptions->setOptionExtraInfo("warm_start",8);
94 
95  roptions->SetRegisteringCategory("Nlp solution robustness", RegisteredOptions::BonminCategory);
96 
97  roptions->AddLowerBoundedNumberOption("max_random_point_radius",
98  "Set max value r for coordinate of a random point.",
99  0.,1,1e5,
100  "When picking a random point coordinate i will be in the interval [min(max(l,-r),u-r), max(min(u,r),l+r)] "
101  "(where l is the lower bound for the variable and u is its upper bound)");
102  roptions->setOptionExtraInfo("max_random_point_radius",8);
103 
104  roptions->AddStringOption3("random_point_type","method to choose a random starting point",
105  "Jon",
106  "Jon", "Choose random point uniformly between the bounds",
107  "Andreas", "perturb the starting point of the problem within a prescribed interval",
108  "Claudia", "perturb the starting point using the perturbation radius suffix information",
109  "");
110  roptions->setOptionExtraInfo("random_point_type",8);
111 
112  roptions->AddLowerBoundedNumberOption("random_point_perturbation_interval",
113  "Amount by which starting point is perturbed when choosing to pick random point by perturbating starting point",
114  0.,true, 1.,
115  "");
116  roptions->setOptionExtraInfo("random_point_perturbation_interval",8);
117 
118 
119  roptions->AddLowerBoundedIntegerOption
120  ("num_iterations_suspect",
121  "Number of iterations over which a node is considered \"suspect\" (for debugging purposes only, see detailed documentation).",
122  -1,-1,
123  "When the number of iterations to solve a node is above this number, the subproblem at this"
124  " node is considered to be suspect and it will be outputed in a file (set to -1 to deactivate this).");
125  roptions->setOptionExtraInfo("num_iterations_suspect",15);
126 
127 
128 
129  roptions->AddLowerBoundedIntegerOption("num_retry_unsolved_random_point",
130  "Number $k$ of times that the algorithm will try to resolve an unsolved NLP with a random starting point "
131  "(we call unsolved an NLP for which Ipopt is not "
132  "able to guarantee optimality within the specified tolerances).",
133  0,0,
134  "When Ipopt fails to solve a continuous NLP sub-problem, if $k > 0$, the algorithm will "
135  "try again to solve the failed NLP with $k$ new randomly chosen starting points "
136  " or until the problem is solved with success.");
137  roptions->setOptionExtraInfo("num_retry_unsolved_random_point",15);
138 
139 
140  roptions->SetRegisteringCategory("Options for non-convex problems", RegisteredOptions::BonminCategory);
141 
142 
143  roptions->AddLowerBoundedIntegerOption("num_resolve_at_root",
144  "Number $k$ of tries to resolve the root node with different starting points.",
145  0,0,
146  "The algorithm will solve the root node with $k$ random starting points"
147  " and will keep the best local optimum found.");
148  roptions->setOptionExtraInfo("num_resolve_at_root",8);
149 
150  roptions->AddLowerBoundedIntegerOption("num_resolve_at_node",
151  "Number $k$ of tries to resolve a node (other than the root) of the tree with different starting point.",
152  0,0,
153  "The algorithm will solve all the nodes with $k$ different random starting points "
154  "and will keep the best local optimum found.");
155  roptions->setOptionExtraInfo("num_resolve_at_node",8);
156 
157  roptions->AddLowerBoundedIntegerOption("num_resolve_at_infeasibles",
158  "Number $k$ of tries to resolve an infeasible node (other than the root) of the tree with different starting point.",
159  0,0,
160  "The algorithm will solve all the infeasible nodes with $k$ different random starting points "
161  "and will keep the best local optimum found.");
162  roptions->setOptionExtraInfo("num_resolve_at_infeasibles",8);
163 
164 
165 
166 }
167 
168 static void register_OA_options
170 {
171  roptions->SetRegisteringCategory("Outer Approximation cuts generation", RegisteredOptions::BonminCategory);
172 
173  roptions->AddStringOption2("disjunctive_cut_type",
174  "Determine if and what kind of disjunctive cuts should be computed.",
175  "none",
176  "none", "No disjunctive cuts.",
177  "most-fractional", "If discrete variables present, compute disjunction for most-fractional variable");
178  roptions->setOptionExtraInfo("disjunctive_cut_type",7);
179 
180  roptions->AddStringOption2("oa_cuts_scope","Specify if OA cuts added are to be set globally or locally valid",
181  "global",
182  "local","Cuts are treated as globally valid",
183  "global", "Cuts are treated as locally valid",
184  "");
185  roptions->setOptionExtraInfo("oa_cuts_scope",7);
186 
187  roptions->AddStringOption2("add_only_violated_oa","Do we add all OA cuts or only the ones violated by current point?",
188  "no",
189  "no","Add all cuts",
190  "yes","Add only violated Cuts","");
191  roptions->setOptionExtraInfo("add_only_violated_oa",7);
192 
193  roptions->AddStringOption4("cut_strengthening_type",
194  "Determines if and what kind of cut strengthening should be performed.",
195  "none",
196  "none", "No strengthening of cuts.",
197  "sglobal", "Strengthen global cuts.",
198  "uglobal-slocal", "Unstrengthened global and strengthened local cuts",
199  "sglobal-slocal", "Strengthened global and strengthened local cuts",
200  "");
201  roptions->setOptionExtraInfo("cut_strengthening_type",7);
202 
203  roptions->AddLowerBoundedNumberOption("tiny_element","Value for tiny element in OA cut",
204  -0.,0,1e-08,
205  "We will remove \"cleanly\" (by relaxing cut) an element lower"
206  " than this.");
207  roptions->setOptionExtraInfo("tiny_element",7);
208 
209  roptions->AddLowerBoundedNumberOption("very_tiny_element","Value for very tiny element in OA cut",
210  -0.,0,1e-17,
211  "Algorithm will take the risk of neglecting an element lower"
212  " than this.");
213  roptions->setOptionExtraInfo("very_tiny_element",7);
214 
215  roptions->AddLowerBoundedIntegerOption("oa_cuts_log_level",
216  "level of log when generating OA cuts.",
217  0, 0,
218  "0: outputs nothing,\n"
219  "1: when a cut is generated, its violation and index of row from which it originates,\n"
220  "2: always output violation of the cut.\n"
221  "3: output generated cuts incidence vectors.");
222  roptions->setOptionExtraInfo("oa_cuts_log_level",7);
223 
224 }
225 
226 
228 void
229 CouenneMINLPInterface::registerOptions
231 {
232  // We try to register the options - if those have been registered
233  // already, we catch the exception and don't need to do it again
234  try {
235  register_general_options(roptions);
236  register_OA_options(roptions);
237 #ifdef COIN_HAS_FILTERSQP
238  FilterSolver::RegisterOptions(roptions);
239 #endif
240 #ifdef COIN_HAS_IPOPT
241  IpoptSolver::RegisterOptions(roptions);
242 #endif
243  }
244  catch(RegisteredOptions::OPTION_ALREADY_REGISTERED) {
245  // skipping
246  }
247 
248 
249 }
250 
252 void
253 CouenneMINLPInterface::setAppDefaultOptions(SmartPtr<OptionsList> Options)
254 {}
255 
256 CouenneMINLPInterface::Messages::Messages
257 ():CoinMessages((int)OSITMINLPINTERFACE_DUMMY_END)
258 {
259  strcpy(source_ ,"NLP");
260  ADD_MSG(SOLUTION_FOUND, std_m, 2,
261  "After %d tries found a solution of %g (previous best %g).");
262 
263  ADD_MSG(INFEASIBLE_SOLUTION_FOUND, std_m, 2,
264  "After %d tries found an solution of %g infeasible problem.");
265 
266  ADD_MSG(UNSOLVED_PROBLEM_FOUND, std_m, 2,
267  "After %d tries found an solution of %g unsolved problem.");
268  ADD_MSG(WARN_SUCCESS_WS, warn_m, 2,
269  "Problem not solved with warm start but solved without");
270 
271  ADD_MSG(WARNING_RESOLVING, warn_m,2,
272  "Trying to resolve NLP with different starting point (%d attempts).");
273  ADD_MSG(WARN_SUCCESS_RANDOM, warn_m, 1,
274  "Problem initially not solved but solved with a random starting point (success on %d attempt)");
275  ADD_MSG(WARN_CONTINUING_ON_FAILURE, warn_m, 1,
276  "Warning : continuing branching, while there are unrecovered failures at nodes");
277 
278  ADD_MSG(SUSPECT_PROBLEM, std_m, 2, "NLP number %d is suspect (see bounds and start file)");
279  ADD_MSG(IPOPT_SUMMARY, std_m, 2, "Ipopt return (for %s): status %2d, iter count %4d, time %g");
280  ADD_MSG(BETTER_SOL, std_m, 2, "Solution of value %g found on %d'th attempt");
281 
282  ADD_MSG(LOG_HEAD, std_m, 1,
283  "\n "
284  " Num Status Obj It time");
285  ADD_MSG(LOG_FIRST_LINE, std_m, 1,
286  " %-8d %-11s %-23.16g %-8d %-3g");
287  ADD_MSG(LOG_LINE, std_m, 1, " %c r%-7d %-11s %-23.16g %-8d %-3g");
288 
289  ADD_MSG(ALTERNATE_OBJECTIVE, std_m, 1, "Objective value recomputed with alternate objective: %g.");
290 
291  ADD_MSG(WARN_RESOLVE_BEFORE_INITIAL_SOLVE, warn_m, 1,
292  "resolve called before any call to initialSol can not use warm starts.");
293  ADD_MSG(ERROR_NO_TNLPSOLVER, warn_m, 1,"Can not parse options when no IpApplication has been created");
294  ADD_MSG(WARNING_NON_CONVEX_OA, warn_m, 1,
295  "OA on non-convex constraint is very experimental.");
296  ADD_MSG(SOLVER_DISAGREE_STATUS, warn_m, 1, "%s says problem %s, %s says %s.");
297  ADD_MSG(SOLVER_DISAGREE_VALUE, warn_m, 1, "%s gives objective %.16g, %s gives %.16g.");
298 
299 }
300 
301 
302 void
303 CouenneMINLPInterface::OaMessageHandler::print(OsiRowCut &row){
304  FILE * fp = filePointer();
305  const int &n = row.row().getNumElements();
306  fprintf(fp,"Row cut has %d elements. Lower bound: %g, upper bound %g.\n", n, row.lb(), row.ub());
307  const int * idx = row.row().getIndices();
308  const double * val = row.row().getElements();
309  for(int i = 0 ; i < n ; i++){
310  fprintf(fp,"%g, x%d",val[i], idx[i]);
311  if(i && i % 7 == 0)
312  fprintf(fp,"\n");
313  }
314 }
315 
316 CouenneMINLPInterface::OaMessages::OaMessages(): CoinMessages((int) OA_MESSAGES_DUMMY_END){
317  strcpy(source_,"OaCg");
318  ADD_MSG(VIOLATED_OA_CUT_GENERATED, std_m, 1,"Row %d, cut violation is %g: Outer approximation cut generated.");
319 
320  ADD_MSG(CUT_NOT_VIOLATED_ENOUGH, std_m, 2,"Row %d, cut violation is %g: Outer approximation cut not generated.");
321 
322  ADD_MSG(OA_CUT_GENERATED, std_m, 1,"Row %d: Outer approximation cut not generated.");
323 }
324 bool CouenneMINLPInterface::hasPrintedOptions=0;
325 
327 // Constructors and desctructors //
330 CouenneMINLPInterface::CouenneMINLPInterface():
331  OsiSolverInterface(),
332  tminlp_(NULL),
333  problem_(NULL),
334  problem_to_optimize_(NULL),
335  feasibility_mode_(false),
336  app_(NULL),
337  debug_apps_(),
338  testOthers_(false),
339  warmstart_(NULL),
340  rowsense_(NULL),
341  rhs_(NULL),
342  rowrange_(NULL),
343  reducedCosts_(NULL),
344  OsiDualObjectiveLimit_(1e200),
345  hasVarNamesFile_(true),
346  nCallOptimizeTNLP_(0),
347  totalNlpSolveTime_(0),
348  totalIterations_(0),
349  maxRandomRadius_(1e08),
350  randomGenerationType_(0),
351  max_perturbation_(COIN_DBL_MAX),
352  pushValue_(1e-02),
353  numRetryInitial_(-1),
354  numRetryResolve_(-1),
355  numRetryInfeasibles_(-1),
356  numRetryUnsolved_(1),
357  messages_(),
358  pretendFailIsInfeasible_(0),
359  hasContinuedAfterNlpFailure_(false),
360  numIterationSuspect_(-1),
361  hasBeenOptimized_(false),
362  obj_(NULL),
363  feasibilityProblem_(NULL),
364  jRow_(NULL),
365  jCol_(NULL),
366  jValues_(NULL),
367  nnz_jac(0),
368  constTypes_(NULL),
369  nNonLinear_(0),
370  tiny_(1e-8),
371  veryTiny_(1e-20),
372  infty_(1e100),
373  exposeWarmStart_(false),
374  firstSolve_(true),
375  cutStrengthener_(NULL),
376  oaMessages_(),
377  oaHandler_(NULL)
378 {
379  oaHandler_ = new OaMessageHandler;
380  oaHandler_->setLogLevel(0);
381 }
382 
383 void
384 CouenneMINLPInterface::initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
387  Ipopt::SmartPtr<TMINLP> tminlp){
388  if(!IsValid(app_))
389  createApplication(roptions, options, journalist);
390  setModel(tminlp);
391 }
392 
393 void CouenneMINLPInterface::setSolver(Ipopt::SmartPtr<TNLPSolver> app){
394  app_ = app;
395 }
396 
397 
398 void
399 CouenneMINLPInterface::createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,
402  )
403 {
404  assert(!IsValid(app_));
405  int ival;
406  options->GetEnumValue("nlp_solver", ival, "bonmin.");
407  Solver s = (Solver) ival;
408  if(s == EFilterSQP){
409  testOthers_ = false;;
410 #ifdef COIN_HAS_FILTERSQP
411  app_ = new Bonmin::FilterSolver(roptions, options, journalist);
412 #else
413  throw SimpleError("createApplication",
414  "Bonmin not configured to run with FilterSQP.");
415 #endif
416  }
417  else if(s == EIpopt){
418  testOthers_ = false;
419 #ifdef COIN_HAS_IPOPT
420  app_ = new IpoptSolver(roptions, options, journalist);
421 #else
422  throw SimpleError("createApplication",
423  "Bonmin not configured to run with Ipopt.");
424 #endif
425  }
426  else if(s == EAll){
427 #ifdef COIN_HAS_FILTERSQP
428  app_ = new Bonmin::FilterSolver(roptions, options, journalist);
429 #else
430  throw SimpleError("createApplication",
431  "Bonmin not configured to run with Ipopt.");
432 #endif
433 #ifdef COIN_HAS_IPOPT
434  debug_apps_.push_back(new IpoptSolver(roptions, options, journalist));
435 #endif
436  testOthers_ = true;
437  }
438  if (!app_->Initialize("")) {
439  throw CoinError("Error during initialization of app_","createApplication", "CouenneMINLPInterface");
440  }
441  for(std::list<Ipopt::SmartPtr<TNLPSolver> >::iterator i = debug_apps_.begin() ;
442  i != debug_apps_.end() ; i++){
443  (*i)->Initialize("");
444  }
445  extractInterfaceParams();
446 
447 }
448 
450 void
451 CouenneMINLPInterface::setModel(SmartPtr<TMINLP> tminlp)
452 {
453  assert(IsValid(tminlp));
454  tminlp_ = tminlp;
455  problem_ = new TMINLP2TNLP(tminlp_);
456  feasibilityProblem_ = new TNLP2FPNLP
458  if(feasibility_mode_){
459  problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
460  }
461  else {
462  problem_to_optimize_ = GetRawPtr(problem_);
463  }
464 }
465 
466 
467 
468 void
469 CouenneMINLPInterface::readOptionFile(const std::string & fileName)
470 {
471  if(IsValid(app_)){
472  std::ifstream is;
473  if (fileName != "") {
474  try {
475  is.open(fileName.c_str());
476  }
477  catch(std::bad_alloc) {
478  throw CoinError("Not enough memory to open option file.\n", "readOptionFile", "CouenneMINLPInterface");
479  }
480  }
481  options()->ReadFromStream(*app_->journalist(), is);
482  extractInterfaceParams();
483  }
484 }
485 
487 CouenneMINLPInterface::CouenneMINLPInterface (const CouenneMINLPInterface &source):
488  OsiSolverInterface(source),
489  tminlp_(source.tminlp_),
490  problem_(NULL),
491  problem_to_optimize_(NULL),
492  feasibility_mode_(source.feasibility_mode_),
493  rowsense_(NULL),
494  rhs_(NULL),
495  rowrange_(NULL),
496  reducedCosts_(NULL),
497  OsiDualObjectiveLimit_(source.OsiDualObjectiveLimit_),
498  hasVarNamesFile_(source.hasVarNamesFile_),
499  nCallOptimizeTNLP_(0),
500  totalNlpSolveTime_(0),
501  totalIterations_(0),
502  maxRandomRadius_(source.maxRandomRadius_),
503  randomGenerationType_(source.randomGenerationType_),
504  max_perturbation_(source.max_perturbation_),
505  pushValue_(source.pushValue_),
506  numRetryInitial_(source.numRetryInitial_),
507  numRetryResolve_(source.numRetryResolve_),
508  numRetryInfeasibles_(source.numRetryInfeasibles_),
509  numRetryUnsolved_(source.numRetryUnsolved_),
510  messages_(),
511  pretendFailIsInfeasible_(source.pretendFailIsInfeasible_),
512  hasContinuedAfterNlpFailure_(source.hasContinuedAfterNlpFailure_),
513  numIterationSuspect_(source.numIterationSuspect_),
514  hasBeenOptimized_(source.hasBeenOptimized_),
515  obj_(NULL),
516  feasibilityProblem_(NULL),
517  jRow_(NULL),
518  jCol_(NULL),
519  jValues_(NULL),
520  nnz_jac(source.nnz_jac),
521  constTypes_(NULL),
522  // constTypesNum_(NULL),
523  nNonLinear_(0),
524  tiny_(source.tiny_),
525  veryTiny_(source.veryTiny_),
526  infty_(source.infty_),
527  exposeWarmStart_(source.exposeWarmStart_),
528  firstSolve_(true),
529  cutStrengthener_(source.cutStrengthener_),
530  oaMessages_(),
531  oaHandler_(NULL),
532  strong_branching_solver_(source.strong_branching_solver_)
533 {
534  if(defaultHandler()){
535  messageHandler()->setLogLevel(source.messageHandler()->logLevel());
536  }
537  //Pass in message handler
538  if(source.messageHandler())
539  passInMessageHandler(source.messageHandler());
540  // Copy options from old application
541  if(IsValid(source.tminlp_)) {
542  problem_ = source.problem_->clone();
543  feasibilityProblem_ = new TNLP2FPNLP
544  (SmartPtr<TNLP>(GetRawPtr(problem_)), source.feasibilityProblem_);
545  if(feasibility_mode_)
546  problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
547  else
548  problem_to_optimize_ = GetRawPtr(problem_);
549  pretendFailIsInfeasible_ = source.pretendFailIsInfeasible_;
550 
551  setAuxiliaryInfo(source.getAuxiliaryInfo());
552  // Copy options from old application
553  app_ = source.app_->clone();
554  for(std::list<Ipopt::SmartPtr<TNLPSolver> >::const_iterator i = source.debug_apps_.begin();
555  i != source.debug_apps_.end() ; i++){
556  debug_apps_.push_back((*i)->clone());
557  }
558  testOthers_ = source.testOthers_;
559  }
560  else {
561  throw SimpleError("Don't know how to copy an empty IpoptInterface.",
562  "copy constructor");
563  }
564 
565  warmstart_ = source.warmstart_ ? source.warmstart_->clone() : NULL;
566 
567  if(source.obj_) {
568  obj_ = new double[source.getNumCols()];
569  CoinCopyN(source.obj_, source.getNumCols(), obj_);
570  }
571 
572 
573  oaHandler_ = new OaMessageHandler(*source.oaHandler_);;
574 
575 }
576 
577 OsiSolverInterface *
578 CouenneMINLPInterface::clone(bool copyData ) const
579 {
580  if(copyData)
581  return new CouenneMINLPInterface(*this);
582  else return new CouenneMINLPInterface;
583 }
584 
586 CouenneMINLPInterface & CouenneMINLPInterface::operator=(const CouenneMINLPInterface& rhs)
587 {
588  if(this!= &rhs) {
589  OsiSolverInterface::operator=(rhs);
590  OsiDualObjectiveLimit_ = rhs.OsiDualObjectiveLimit_;
591  nCallOptimizeTNLP_ = rhs.nCallOptimizeTNLP_;
592  totalNlpSolveTime_ = rhs.nCallOptimizeTNLP_;
593  totalIterations_ = rhs.totalIterations_;
594  maxRandomRadius_ = rhs.maxRandomRadius_;
595  hasVarNamesFile_ = rhs.hasVarNamesFile_;
596  pushValue_ = rhs.pushValue_;
597 
598  delete warmstart_;
599  warmstart_ = NULL;
600 
601  if(IsValid(rhs.tminlp_)) {
602 
603  tminlp_ = rhs.tminlp_;
604  problem_ = new TMINLP2TNLP(tminlp_);
605  problem_to_optimize_ = GetRawPtr(problem_);
606  app_ = rhs.app_->clone();
607 
608  warmstart_ = rhs.warmstart_ ? rhs.warmstart_->clone() : NULL;
609 
610  feasibilityProblem_ = new TNLP2FPNLP
612  nnz_jac = rhs.nnz_jac;
613 
614  if(constTypes_ != NULL) {
615  delete [] constTypes_;
616  constTypes_ = NULL;
617  }
618  if(rhs.constTypes_ != NULL) {
619  constTypes_ = new TNLP::LinearityType[getNumRows()];
620  CoinCopyN(rhs.constTypes_, getNumRows(), constTypes_);
621  }
622  /*
623  if(constTypesNum_ != NULL) {
624  delete [] constTypesNum_;
625  constTypesNum_ = NULL;
626  }
627  if(rhs.constTypesNum_ != NULL) {
628  constTypesNum_ = new int[getNumRows()];
629  CoinCopyN(rhs.constTypesNum_, getNumRows(), constTypesNum_);
630  }
631  */
632  if(rhs.jValues_!=NULL && rhs.jRow_ != NULL && rhs.jCol_ != NULL && nnz_jac>0) {
633  jValues_ = new double [nnz_jac];
634  jCol_ = new Index [nnz_jac];
635  jRow_ = new Index [nnz_jac];
636  CoinCopyN(rhs.jValues_ , nnz_jac,jValues_ );
637  CoinCopyN(rhs.jCol_ , nnz_jac,jCol_ );
638  CoinCopyN(rhs.jRow_ , nnz_jac,jRow_ );
639  }
640  else if(nnz_jac > 0) {
641  throw CoinError("Arrays for storing jacobian are inconsistant.",
642  "copy constructor",
643  "IpoptOAInterface");
644  }
645  tiny_ = rhs.tiny_;
646  veryTiny_ = rhs.veryTiny_;
647  infty_ = rhs.infty_;
648  exposeWarmStart_ = rhs.exposeWarmStart_;
649 
650  }
651  else {
652  tminlp_ =NULL;
653  problem_ = NULL;
654  app_ = NULL;
655  feasibilityProblem_ = NULL;
656  }
657 
658 
659  if(obj_) {
660  delete [] obj_;
661  obj_ = NULL;
662  }
663  if(rhs.obj_) {
664  obj_ = new double[rhs.getNumCols()];
665  CoinCopyN(rhs.obj_, rhs.getNumCols(), obj_);
666  }
667 
668  hasVarNamesFile_ = rhs.hasVarNamesFile_;
669 
670  nCallOptimizeTNLP_ = rhs.nCallOptimizeTNLP_;
671  totalNlpSolveTime_ = rhs.totalNlpSolveTime_;
672  totalIterations_ = rhs.totalIterations_;
673  maxRandomRadius_ = rhs.maxRandomRadius_;
674  pushValue_ = rhs.pushValue_;
675  numRetryInitial_ = rhs.numRetryInitial_;
676  numRetryResolve_ = rhs.numRetryResolve_;
677  numRetryInfeasibles_ = rhs.numRetryInfeasibles_;
678  numRetryUnsolved_ = rhs.numRetryUnsolved_;
679  pretendFailIsInfeasible_ = rhs.pretendFailIsInfeasible_;
680  numIterationSuspect_ = rhs.numIterationSuspect_;
681 
682  hasBeenOptimized_ = rhs.hasBeenOptimized_;
683  cutStrengthener_ = rhs.cutStrengthener_;
684 
685  delete oaHandler_;
686  oaHandler_ = new OaMessageHandler(*rhs.oaHandler_);
687  strong_branching_solver_ = rhs.strong_branching_solver_;
688 
689  freeCachedData();
690  }
691  return *this;
692 }
693 
695 {
696  if(!IsValid(app_)) {
697  messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
698  return NULL;
699  }
700  else
701  return app_->options();
702 }
703 
705 {
706  if(!IsValid(app_)) {
707  messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol;
708  return NULL;
709  }
710  else
711  return app_->options();
712 }
713 
715 CouenneMINLPInterface::~CouenneMINLPInterface ()
716 {
717  freeCachedData();
718  delete [] jRow_;
719  delete [] jCol_;
720  delete [] jValues_;
721  delete [] constTypes_;
722  delete [] obj_;
723  delete oaHandler_;
724  delete warmstart_;
725 }
726 
727 void
728 CouenneMINLPInterface::freeCachedColRim()
729 {
730  if(reducedCosts_!=NULL) {
731  delete [] reducedCosts_;
732  reducedCosts_ = NULL;
733  }
734 
735 }
736 
737 void
738 CouenneMINLPInterface::freeCachedRowRim()
739 {
740  if(rowsense_!=NULL) {
741  delete [] rowsense_;
742  rowsense_ = NULL;
743  }
744  if(rhs_!=NULL) {
745  delete [] rhs_;
746  rhs_ = NULL;
747  }
748  if(rowrange_!=NULL) {
749  delete [] rowrange_;
750  rowrange_ = NULL;
751  }
752  // if(dualsol_!=NULL)
753  // {
754  // delete [] dualsol_; dualsol_ = NULL;
755  // }
756 }
757 
758 void
759 CouenneMINLPInterface::freeCachedData()
760 {
761  freeCachedColRim();
762  freeCachedRowRim();
763 }
764 
765 const char * CouenneMINLPInterface::OPT_SYMB="OPT";
766 const char * CouenneMINLPInterface::FAILED_SYMB="FAILED";
767 const char * CouenneMINLPInterface::UNBOUND_SYMB="UNBOUNDED";
768 const char * CouenneMINLPInterface::INFEAS_SYMB="INFEAS";
770 // WarmStart Information //
772 
773 
774 void
775 CouenneMINLPInterface::resolveForCost(int numsolve, bool keepWarmStart)
776 {
777  // This method assumes that a problem has just been solved and we try for a
778  // different solution. So disregard (in fact, clear out) any warmstart info
779  // we might have, and acquire a new one before returning.
780  delete warmstart_;
781  warmstart_ = NULL;
782 
783  Coin::SmartPtr<SimpleReferencedPtr<CoinWarmStart> > ws_backup = NULL;
784  if(!exposeWarmStart_ && keepWarmStart){
785  //if warm start is not exposed, we need to store the current starting point to
786  //restore it at the end of the method
787  ws_backup = make_referenced(app_->getUsedWarmStart(problem_));
788  }
790  vector<double> point(getNumCols()*3+ getNumRows());
791  double bestBound = getObjValue();
792  CoinCopyN(getColSolution(),
793  getNumCols(), point());
794  CoinCopyN(getRowPrice(),
795  2*getNumCols()+ getNumRows(),
796  point() + getNumCols());
797 
798  if(isProvenOptimal())
799  messageHandler()->message(SOLUTION_FOUND,
800  messages_)
801  <<1<<getObjValue()<<bestBound
802  <<CoinMessageEol;
803  else
804  messageHandler()->message(INFEASIBLE_SOLUTION_FOUND,
805  messages_)
806  <<1
807  <<CoinMessageEol;
808  for(int f = 0; f < numsolve ; f++) {
809  messageHandler()->message(WARNING_RESOLVING,
810  messages_)
811  <<f+1<< CoinMessageEol ;
812  randomStartingPoint();
813  solveAndCheckErrors(0,0,"resolveForCost");
814 
815 
816  char c=' ';
817  //Is solution better than previous
818  if(isProvenOptimal() &&
819  getObjValue()<bestBound) {
820  c='*';
821  messageHandler()->message(BETTER_SOL, messages_)<<getObjValue()<<f+1<< CoinMessageEol;
822  CoinCopyN(getColSolution(),
823  getNumCols(), point());
824  CoinCopyN(getRowPrice(),
825  2*getNumCols()+ getNumRows(),
826  point() + getNumCols());
827  bestBound = getObjValue();
828  }
829 
830  messageHandler()->message(LOG_LINE, messages_)
831  <<c<<f+1<<statusAsString()<<getObjValue()<<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
832 
833 
834  if(isProvenOptimal())
835  messageHandler()->message(SOLUTION_FOUND,
836  messages_)
837  <<f+2<<getObjValue()<<bestBound
838  <<CoinMessageEol;
839  else if(!isAbandoned())
840  messageHandler()->message(UNSOLVED_PROBLEM_FOUND,
841  messages_)
842  <<f+2
843  <<CoinMessageEol;
844  else
845  messageHandler()->message(INFEASIBLE_SOLUTION_FOUND,
846  messages_)
847  <<f+2
848  <<CoinMessageEol;
849  }
850  setColSolution(point());
851  setRowPrice(point() + getNumCols());
852  app_->enableWarmStart();
853 
854  optimizationStatus_ = app_->ReOptimizeTNLP(GetRawPtr(problem_to_optimize_));
855  hasBeenOptimized_ = true;
856 
857  if(!exposeWarmStart_ && keepWarmStart) {
858  app_->setWarmStart(ws_backup->ptr(), problem_);
859  }
860 }
861 
862 void
863 CouenneMINLPInterface::resolveForRobustness(int numsolve)
864 {
865  // This method assumes that a problem has just been solved and we try for a
866  // different solution. So disregard (in fact, clear out) any warmstart info
867  // we might have, and acquire a new one before returning.
868  delete warmstart_;
869  warmstart_ = NULL;
870 
871 
872  CoinWarmStart * ws_backup = NULL;
873  if(!exposeWarmStart_){
874  //if warm start is not exposed, we need to store the current starting point to
875  //restore it at the end of the method
876  ws_backup = app_->getUsedWarmStart(problem_);
877  }
878  //std::cerr<<"Resolving the problem for robustness"<<std::endl;
879  //First remove warm start point and resolve
880  app_->disableWarmStart();
881  problem()->resetStartingPoint();
882  messageHandler()->message(WARNING_RESOLVING,
883  messages_)
884  <<1<< CoinMessageEol ;
885  solveAndCheckErrors(0,0,"resolveForRobustness");
886 
887 
888  char c='*';
889  if(isAbandoned()) {
890  c=' ';
891  }
892  messageHandler()->message(LOG_LINE, messages_)
893  <<c<<1<<statusAsString()<<getObjValue()<<app_->IterationCount()<<
894  app_->CPUTime()<<CoinMessageEol;
895 
896 
897  if(!isAbandoned()) {
898  messageHandler()->message(WARN_SUCCESS_WS, messages_) << CoinMessageEol ;
899  // re-enable warmstart and get it
900  app_->enableWarmStart();
901  if (!exposeWarmStart_) {
902  app_->setWarmStart(ws_backup, problem_);
903  delete ws_backup;
904  }
905  return; //we won go on
906  }
907 
908  //still unsolved try again with different random starting points
909  for(int f = 0; f < numsolve ; f++) {
910  messageHandler()->message(WARNING_RESOLVING,
911  messages_)
912  <<f+2<< CoinMessageEol ;
913 
914  randomStartingPoint();
915  solveAndCheckErrors(0,0,"resolveForRobustness");
916 
917 
918  messageHandler()->message(IPOPT_SUMMARY, messages_)
919  <<"resolveForRobustness"<<optimizationStatus_<<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
920 
921 
922  char c='*';
923  if(isAbandoned()) {
924  c=' ';
925  }
926  messageHandler()->message(LOG_LINE, messages_)
927  <<c<<f+2<<statusAsString()<<getObjValue()
928  <<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
929 
930 
931  if(!isAbandoned()) {
932  messageHandler()->message(WARN_SUCCESS_RANDOM, messages_)
933  << f+2 << CoinMessageEol ;
934  // re-enable warmstart and get it
935  app_->enableWarmStart();
936  if (!exposeWarmStart_) {
937  app_->setWarmStart(ws_backup, problem_);
938  delete ws_backup;
939  }
940 
941  return; //we have found a solution and continue
942  }
943  }
944 
945 
946  if(!exposeWarmStart_){
947  app_->setWarmStart(ws_backup, problem_);
948  delete ws_backup;
949  }
950  if(pretendFailIsInfeasible_) {
951  if(pretendFailIsInfeasible_ == 1) {
952  messageHandler()->message(WARN_CONTINUING_ON_FAILURE,
953  messages_)
954  <<CoinMessageEol;
955  hasContinuedAfterNlpFailure_ = 1;
956  }
957  return;
958  }
959  else {
960  std::string probName;
961  getStrParam(OsiProbName,probName);
962  throw newUnsolvedError(app_->errorCode(), problem_,
963  probName);
964  }
965  // Do NOT get warmstart in other cases
966 }
967 
969 // Problem information methods //
972 int CouenneMINLPInterface::getNumCols() const
973 {
974 
975  return problem_->num_variables();
976 }
977 
978 
980 int
981 CouenneMINLPInterface::getNumRows() const
982 {
983  return problem_->num_constraints();
984 }
985 
986 const double *
987 CouenneMINLPInterface::getColLower() const
988 {
989  return problem_->x_l();
990 }
991 
992 const double *
993 CouenneMINLPInterface::getColUpper() const
994 {
995  return problem_->x_u();
996 }
997 
998 #if 1
999 
1000 
1002 const OsiSolverInterface::OsiNameVec&
1003 CouenneMINLPInterface::getVarNames() {
1004  return getColNames();
1005 }
1006 #endif
1007 
1008 
1009 void CouenneMINLPInterface::extractSenseRhsAndRange() const
1010 {
1011  assert(rowsense_==NULL&&rhs_==NULL&&rowrange_==NULL);
1012  int numrows = problem_->num_constraints();
1013  if(numrows == 0) return;
1014  const double * rowLower = getRowLower();
1015  const double * rowUpper = getRowUpper();
1016  rowsense_ = new char [numrows];
1017  rhs_ = new double [numrows];
1018  rowrange_ = new double [numrows];
1019  for(int i = 0 ; i < numrows ; i++) {
1020  rowrange_[i]=0.;
1021  convertBoundToSense(rowLower[i], rowUpper[i], rowsense_[i], rhs_[i], rowrange_[i]);
1022  }
1023 }
1024 
1034 const char *
1035 CouenneMINLPInterface::getRowSense() const
1036 {
1037  if(rowsense_==NULL) {
1038  extractSenseRhsAndRange();
1039  }
1040  return rowsense_;
1041 }
1042 
1051 const double *
1052 CouenneMINLPInterface::getRightHandSide() const
1053 {
1054  if(rhs_==NULL) {
1055  extractSenseRhsAndRange();
1056  }
1057  return rhs_;
1058 }
1059 
1068 const double *
1069 CouenneMINLPInterface::getRowRange() const
1070 {
1071  if(rowrange_==NULL) {
1072  extractSenseRhsAndRange();
1073  }
1074  return rowrange_;
1075 }
1076 
1077 const double *
1078 CouenneMINLPInterface::getRowLower() const
1079 {
1080  return problem_->g_l();
1081 }
1082 
1083 const double *
1084 CouenneMINLPInterface::getRowUpper() const
1085 {
1086  return problem_->g_u();
1087 }
1088 
1090 bool
1091 CouenneMINLPInterface::isContinuous(int colNumber) const
1092 {
1093  return (problem_->var_types()[colNumber]==TMINLP::CONTINUOUS);
1094 }
1095 
1097 bool
1098 CouenneMINLPInterface::isBinary(int colNumber) const
1099 {
1100  return (problem_->var_types()[colNumber]==TMINLP::BINARY);
1101 }
1102 
1107 bool
1108 CouenneMINLPInterface::isInteger(int colNumber) const
1109 {
1110  return ((problem_->var_types()[colNumber]==TMINLP::BINARY)||
1111  (problem_->var_types()[colNumber]==TMINLP::INTEGER));
1112 }
1113 
1115 bool
1116 CouenneMINLPInterface::isIntegerNonBinary(int colNumber) const
1117 {
1118  return (problem_->var_types()[colNumber]==TMINLP::INTEGER);
1119 }
1121 bool
1122 CouenneMINLPInterface::isFreeBinary(int colNumber) const
1123 {
1124  return ((problem_->var_types()[colNumber]==TMINLP::BINARY)
1125  &&((getColUpper()[colNumber]-getColLower()[colNumber]) > 1 - 1e-09));
1126 }
1127 
1129 double
1130 CouenneMINLPInterface::getInfinity() const
1131 {
1132  return COIN_DBL_MAX;
1133 }
1134 
1136 const double *
1137 CouenneMINLPInterface::getColSolution() const
1138 {
1139  if(hasBeenOptimized_)
1140  return problem_->x_sol();
1141  else
1142  return problem_->x_init();
1143 }
1144 
1146 const double *
1147 CouenneMINLPInterface::getRowPrice() const
1148 {
1149  if(hasBeenOptimized_)
1150  return problem_->duals_sol();
1151  else
1152  return problem_->duals_init();
1153 }
1154 
1156 const double *
1157 CouenneMINLPInterface::getReducedCost() const
1158 {
1159  (*handler_)<<"WARNING : trying to access reduced cost in Ipopt always retrun 0"<<CoinMessageEol;
1160  if(reducedCosts_==NULL) {
1161  reducedCosts_ = new double [getNumCols()];
1162  CoinFillN(reducedCosts_,getNumCols(),0.);
1163  }
1164  return reducedCosts_;
1165 }
1166 
1169 const double *
1170 CouenneMINLPInterface::getRowActivity() const
1171 {
1172  return problem_->g_sol();
1173 }
1174 
1178 int
1179 CouenneMINLPInterface::getIterationCount() const
1180 {
1181  return app_->IterationCount();
1182 }
1183 
1184 
1187 void
1188 CouenneMINLPInterface::setColLower( int elementIndex, double elementValue )
1189 {
1190  // if(fabs(problem_->x_l()[elementIndex]-elementValue)>1e-06)
1191  problem_->SetVariableLowerBound(elementIndex,elementValue);
1192  hasBeenOptimized_ = false;
1193 }
1194 
1197 void
1198 CouenneMINLPInterface::setColUpper( int elementIndex, double elementValue )
1199 {
1200  // if(fabs(problem_->x_u()[elementIndex]-elementValue)>1e-06)
1201  problem_->SetVariableUpperBound(elementIndex,elementValue);
1202  hasBeenOptimized_ = false;
1203 }
1204 
1207 void
1208 CouenneMINLPInterface::setColLower( const double* array )
1209 {
1210  problem_->SetVariablesLowerBounds(problem_->num_variables(),
1211  array);
1212  hasBeenOptimized_ = false;
1213 }
1214 
1217 void
1218 CouenneMINLPInterface::setColUpper( const double* array )
1219 {
1220  problem_->SetVariablesUpperBounds(problem_->num_variables(),
1221  array);
1222  hasBeenOptimized_ = false;
1223 }
1224 
1227 void
1228 CouenneMINLPInterface::setRowLower( int elementIndex, double elementValue )
1229 {
1230  throw SimpleError("Not implemented yet but should be if necessary.",
1231  "setRowLower");
1232  hasBeenOptimized_ = false;
1233 }
1234 
1237 void
1238 CouenneMINLPInterface::setRowUpper( int elementIndex, double elementValue )
1239 {
1240  throw SimpleError("Not implemented yet but should be if necessary.",
1241  "setRowUpper");
1242  hasBeenOptimized_ = false;
1243 }
1244 
1246 void
1247 CouenneMINLPInterface::setRowType(int index, char sense, double rightHandSide,
1248  double range)
1249 {
1250  throw SimpleError("Not implemented yet but should be if necessary.",
1251  "setRowType");
1252  hasBeenOptimized_ = false;
1253 }
1254 
1255 
1258 void
1259 CouenneMINLPInterface::setObjSense(double s)
1260 {
1261  throw SimpleError("Can not change objective sense of an Ipopt problem.",
1262  "setObjSense");
1263  hasBeenOptimized_ = false;
1264 }
1265 
1275 void
1276 CouenneMINLPInterface::setColSolution(const double *colsol)
1277 {
1278  problem_->setxInit(getNumCols(), colsol);
1279  hasBeenOptimized_ = false;
1280 }
1281 
1292 void
1293 CouenneMINLPInterface::setRowPrice(const double * rowprice)
1294 {
1295  problem_->setDualsInit(getNumCols()*2 + getNumRows(), rowprice);
1296  hasBeenOptimized_ = false;
1297 }
1298 
1305 CoinWarmStart *
1306 CouenneMINLPInterface::getEmptyWarmStart () const
1307 {return app_->getEmptyWarmStart();}
1308 
1310 CoinWarmStart*
1311 CouenneMINLPInterface::getWarmStart() const
1312 {
1313  if (exposeWarmStart_) {
1314  return internal_getWarmStart();;
1315  }
1316  else {
1317  return getEmptyWarmStart();
1318  }
1319 }
1322 bool
1323 CouenneMINLPInterface::setWarmStart(const CoinWarmStart* ws)
1324 {
1325  if (exposeWarmStart_) {
1326  return internal_setWarmStart(ws);
1327  }
1328  else {
1329  return true;
1330  }
1331 }
1333 CoinWarmStart*
1334 CouenneMINLPInterface::internal_getWarmStart() const
1335 {
1336  if (exposeWarmStart_ && warmstart_) {
1337  return warmstart_->clone();
1338  }
1339  else {
1340  return getEmptyWarmStart();
1341  }
1342 }
1345 bool
1346 CouenneMINLPInterface::internal_setWarmStart(const CoinWarmStart* ws)
1347 {
1348  delete warmstart_;
1349  warmstart_ = NULL;
1350  hasBeenOptimized_ = false;
1351  if (exposeWarmStart_) {
1352  if (ws == NULL) {
1353  return true;
1354  }
1355  if(app_->warmStartIsValid(ws)) {
1356  warmstart_ = ws->clone();
1357  return true;
1358  }
1359  // See if it is anything else than the CoinWarmStartBasis that all others
1360  // derive from
1361  const CoinWarmStartPrimalDual* pdws =
1362  dynamic_cast<const CoinWarmStartPrimalDual*>(ws);
1363  if (pdws) {
1364  // Must be an IpoptWarmStart, since the others do not derive from this.
1365  // Accept it.
1366  warmstart_ = new IpoptWarmStart(*pdws);
1367  return true;
1368  }
1369  return false;
1370  }
1371  else {
1372  return true;
1373  }
1374 }
1375 
1377 void
1378 CouenneMINLPInterface::setContinuous(int index)
1379 {
1380  problem_->SetVariableType(index, TMINLP::CONTINUOUS);
1381  hasBeenOptimized_ = false;
1382 }
1384 void
1385 CouenneMINLPInterface::setInteger(int index)
1386 {
1387  problem_->SetVariableType(index, TMINLP::INTEGER);
1388  hasBeenOptimized_ = false;
1389 }
1390 
1392 double
1393 CouenneMINLPInterface::getObjValue() const
1394 {
1395  return problem_->obj_value();
1396 }
1397 
1398 //#############################################################################
1399 // Parameter related methods
1400 //#############################################################################
1401 
1402 bool
1403 CouenneMINLPInterface::setIntParam(OsiIntParam key, int value)
1404 {
1405  // debugMessage("OsiCpxSolverInterface::setIntParam(%d, %d)\n", key, value);
1406 
1407  bool retval = false;
1408  switch (key) {
1409  case OsiMaxNumIteration:
1410  retval = false;
1411  break;
1412  case OsiMaxNumIterationHotStart:
1413  if( value >= 0 ) {
1414  retval = false;
1415  }
1416  else
1417  retval = false;
1418  break;
1419  case OsiLastIntParam:
1420  retval = false;
1421  break;
1422  default:
1423  retval = false;
1424  (*handler_)<< "Unhandled case in setIntParam\n"<<CoinMessageEol;
1425  break;
1426  }
1427  return retval;
1428 }
1429 
1430 //-----------------------------------------------------------------------------
1431 
1432 bool
1433 CouenneMINLPInterface::setDblParam(OsiDblParam key, double value)
1434 {
1435  // debugMessage("CouenneMINLPInterface::setDblParam(%d, %g)\n", key, value);
1436 
1437  bool retval = false;
1438  switch (key) {
1439  case OsiDualObjectiveLimit:
1440  OsiDualObjectiveLimit_ = value;
1441  retval = true;
1442  break;
1443  case OsiPrimalObjectiveLimit:
1444  (*handler_)<<"Can not set primal objective limit parameter"<<CoinMessageEol;
1445  retval = false;
1446  break;
1447  case OsiDualTolerance:
1448  (*handler_)<<"Can not set dual tolerance parameter"<<CoinMessageEol;
1449  retval = false;
1450  break;
1451  case OsiPrimalTolerance:
1452  (*handler_)<<"Can not set primal tolerance parameter"<<CoinMessageEol;
1453  retval = false;
1454  case OsiObjOffset:
1455  retval = OsiSolverInterface::setDblParam(key,value);
1456  break;
1457  case OsiLastDblParam:
1458  retval = false;
1459  break;
1460  default:
1461  retval = false;
1462  (*handler_) << "Unhandled case in setDblParam"<<CoinMessageEol;
1463  break;
1464  }
1465  return retval;
1466 }
1467 
1468 
1469 //-----------------------------------------------------------------------------
1470 
1471 bool
1472 CouenneMINLPInterface::setStrParam(OsiStrParam key, const std::string & value)
1473 {
1474  // debugMessage("CouenneMINLPInterface::setStrParam(%d, %s)\n", key, value.c_str());
1475 
1476  bool retval=false;
1477  switch (key) {
1478  case OsiProbName:
1479  OsiSolverInterface::setStrParam(key,value);
1480  return retval = true;
1481  case OsiSolverName:
1482  return false;
1483  case OsiLastStrParam:
1484  return false;
1485  }
1486  return false;
1487 }
1488 
1489 //-----------------------------------------------------------------------------
1490 
1491 bool
1492 CouenneMINLPInterface::getIntParam(OsiIntParam key, int& value) const
1493 {
1494  // debugMessage("CouenneMINLPInterface::getIntParam(%d)\n", key);
1495 
1496  value = -COIN_INT_MAX; // Give a dummy value
1497  bool retval = false;
1498  switch (key) {
1499  case OsiMaxNumIteration:
1500  retval = false;
1501  break;
1502  case OsiMaxNumIterationHotStart:
1503  retval = false;
1504  break;
1505  case OsiLastIntParam:
1506  retval = false;
1507  break;
1508  default:
1509  retval = false;
1510  (*handler_) << "Unhandled case in setIntParam"<<CoinMessageEol;
1511  }
1512  return retval;
1513 }
1514 
1515 //-----------------------------------------------------------------------------
1516 
1517 bool
1518 CouenneMINLPInterface::getDblParam(OsiDblParam key, double& value) const
1519 {
1520  // debugMessage("CouenneMINLPInterface::getDblParam(%d)\n", key);
1521 
1522  bool retval = false;
1523  switch (key) {
1524  case OsiDualObjectiveLimit:
1525  value = OsiDualObjectiveLimit_;
1526  retval = true;
1527  break;
1528  case OsiPrimalObjectiveLimit:
1529  value = getInfinity();
1530  retval = true;
1531  break;
1532  case OsiDualTolerance:
1533  retval = false;
1534  break;
1535  case OsiPrimalTolerance:
1536  options()->GetNumericValue("tol", value,"");
1537  //value = 1e-07;
1538  retval = true;
1539  break;
1540  case OsiObjOffset:
1541  retval = OsiSolverInterface::getDblParam(key, value);
1542  break;
1543  case OsiLastDblParam:
1544  retval = false;
1545  break;
1546  }
1547  return retval;
1548 }
1549 
1550 
1551 //-----------------------------------------------------------------------------
1552 
1553 bool
1554 CouenneMINLPInterface::getStrParam(OsiStrParam key, std::string & value) const
1555 {
1556  // debugMessage("CouenneMINLPInterface::getStrParam(%d)\n", key);
1557 
1558  switch (key) {
1559  case OsiProbName:
1560  OsiSolverInterface::getStrParam(key, value);
1561  break;
1562  case OsiSolverName:
1563  value = "Ipopt";
1564  break;
1565  case OsiLastStrParam:
1566  return false;
1567  }
1568 
1569  return true;
1570 }
1571 
1572 void
1573 CouenneMINLPInterface::randomStartingPoint()
1574 {
1575  int numcols = getNumCols();
1576  const double * colLower = getColLower();
1577  const double * colUpper = getColUpper();
1578  double * sol = new double[numcols];
1579  const Number * x_init = problem_->x_init_user();
1580  const double* perturb_radius = NULL;
1581  if (randomGenerationType_ == perturb_suffix) {
1582  const TMINLP::PerturbInfo* pertubinfo = tminlp_->perturbInfo();
1583  if (pertubinfo) {
1584  perturb_radius = pertubinfo->GetPerturbationArray();
1585  }
1586  if (!perturb_radius) {
1587  throw SimpleError("Can't use perturb_radius if no radii are given.",
1588  "randomStartingPoint");
1589  }
1590  }
1591  for(int i = 0 ; i < numcols ; i++) {
1592  int randomGenerationType = randomGenerationType_;
1593  if(x_init[i] < colLower[i] || x_init[i] > colUpper[i])
1594  randomGenerationType = uniform;
1595  if(randomGenerationType_ == uniform){
1596  double lower = std::min(-maxRandomRadius_,colUpper[i] - maxRandomRadius_);
1597  lower = std::max(colLower[i], lower);
1598  double upper = std::max(maxRandomRadius_,colLower[i] + maxRandomRadius_);
1599  upper = std::min(colUpper[i],upper);
1600  lower = std::min(upper,lower);
1601  upper = std::max(upper, lower);
1602  double interval = upper - lower;
1603  sol[i] = CoinDrand48()*(interval) + lower;}
1604  else if (randomGenerationType_ == perturb){
1605  const double lower = std::max(x_init[i] - max_perturbation_, colLower[i]);
1606  const double upper = std::min(x_init[i] + max_perturbation_, colUpper[i]);
1607  const double interval = upper - lower;
1608  sol[i] = lower + CoinDrand48()*(interval);
1609  }
1610  else if (randomGenerationType_ == perturb_suffix){
1611  const double radius = perturb_radius[i];
1612  const double lower = std::max(x_init[i] - radius*max_perturbation_, colLower[i]);
1613  const double upper = std::min(x_init[i] + radius*max_perturbation_, colUpper[i]);
1614  const double interval = upper - lower;
1615  sol[i] = lower + CoinDrand48()*(interval);
1616  }
1617  }
1618  app_->disableWarmStart();
1619  setColSolution(sol);
1620  delete [] sol;
1621 }
1622 
1623 
1624 
1626 int CouenneMINLPInterface::initializeJacobianArrays()
1627 {
1628  Index n, m, nnz_h_lag;
1629  TNLP::IndexStyleEnum index_style;
1630  tminlp_->get_nlp_info( n, m, nnz_jac, nnz_h_lag, index_style);
1631 
1632  if(jRow_ != NULL) delete jRow_;
1633  if(jCol_ != NULL) delete jCol_;
1634  if(jValues_ != NULL) delete jValues_;
1635 
1636  jRow_ = new Index[nnz_jac];
1637  jCol_ = new Index[nnz_jac];
1638  jValues_ = new Number[nnz_jac];
1639  tminlp_->eval_jac_g(n, NULL, 0, m, nnz_jac, jRow_, jCol_, NULL);
1640  if(index_style == Ipopt::TNLP::FORTRAN_STYLE)//put C-style
1641  {
1642  for(int i = 0 ; i < nnz_jac ; i++){
1643  jRow_[i]--;
1644  jCol_[i]--;
1645  }
1646  }
1647 
1648  if(constTypes_ != NULL) delete [] constTypes_;
1649  // if(constTypesNum_ != NULL) delete [] constTypesNum_;
1650 
1651  constTypes_ = new TNLP::LinearityType[getNumRows()];
1652  tminlp_->get_constraints_linearity(getNumRows(), constTypes_);
1653  // constTypesNum_ = new int[getNumRows()];
1654  for(int i = 0; i < getNumRows() ; i++) {
1655  if(constTypes_[i]==TNLP::NON_LINEAR) {
1656  //constTypesNum_[i] =
1657  nNonLinear_++;
1658  }
1659  }
1660  return nnz_jac;
1661 }
1662 
1663 
1664 double
1665 CouenneMINLPInterface::getConstraintsViolation(const double *x, double &obj)
1666 {
1667  int numcols = getNumCols();
1668  int numrows = getNumRows();
1669  double * g = new double[numrows];
1670  tminlp_->eval_g(numcols, x, 1, numrows, g);
1671  const double * rowLower = getRowLower();
1672  const double * rowUpper = getRowUpper();
1673 
1674 
1675  double norm = 0;
1676  for(int i = 0; i< numrows ; i++) {
1677  if(!constTypes_ || constTypes_[i] == TNLP::NON_LINEAR) {
1678  double rowViolation = 0;
1679  if(rowLower[i] > -1e10)
1680  rowViolation = std::max(0.,rowLower[i] - g[i]);
1681 
1682  if(rowUpper[i] < 1e10);
1683  rowViolation = std::max(rowViolation, g[i] - rowUpper[i]);
1684 
1685  norm = rowViolation > norm ? rowViolation : norm;
1686  }
1687  }
1688  tminlp_->eval_f(numcols, x, 1, obj);
1689  delete [] g;
1690  return norm;
1691 }
1692 
1694 double
1695 CouenneMINLPInterface::getNonLinearitiesViolation(const double *x, const double obj)
1696 {
1697  double f;
1698  double norm = getConstraintsViolation(x, f);
1699  assert((f - obj) > -1e-08);
1700  norm = (f - obj) > norm ? f - obj : norm;
1701  return norm;
1702 }
1703 
1704 
1705 
1706 //A procedure to try to remove small coefficients in OA cuts (or make it non small
1707 static inline
1708 bool cleanNnz(double &value, double colLower, double colUpper,
1709  double rowLower, double rowUpper, double colsol,
1710  double & lb, double &ub, double tiny, double veryTiny)
1711 {
1712  if(fabs(value)>= tiny) return 1;
1713 
1714  if(fabs(value)<veryTiny) return 0;//Take the risk?
1715 
1716  //try and remove
1717  double infty = 1e20;
1718  bool colUpBounded = colUpper < 10000;
1719  bool colLoBounded = colLower > -10000;
1720  bool rowNotLoBounded = rowLower <= - infty;
1721  bool rowNotUpBounded = rowUpper >= infty;
1722  bool pos = value > 0;
1723 
1724  if(colLoBounded && pos && rowNotUpBounded) {
1725  lb += value * (colsol - colLower);
1726  return 0;
1727  }
1728  else
1729  if(colLoBounded && !pos && rowNotLoBounded) {
1730  ub += value * (colsol - colLower);
1731  return 0;
1732  }
1733  else
1734  if(colUpBounded && !pos && rowNotUpBounded) {
1735  lb += value * (colsol - colUpper);
1736  return 0;
1737  }
1738  else
1739  if(colUpBounded && pos && rowNotLoBounded) {
1740  ub += value * (colsol - colUpper);
1741  return 0;
1742  }
1743  //can not remove coefficient increase it to smallest non zero
1744  if(pos) value = tiny;
1745  else
1746  value = - tiny;
1747  return 1;
1748 }
1749 
1752 void
1753 CouenneMINLPInterface::getOuterApproximation(OsiCuts &cs, const double * x, bool getObj, const double * x2, double theta, bool global)
1754 {
1755 
1756  //printf ("this procedure has been called\n");
1757 
1758  int n,m, nnz_jac_g, nnz_h_lag;
1759  TNLP::IndexStyleEnum index_style;
1760  problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
1761  if(jRow_ == NULL || jCol_ == NULL || jValues_ == NULL)
1762  initializeJacobianArrays();
1763  assert(jRow_ != NULL);
1764  assert(jCol_ != NULL);
1765  double * g = new double[m];
1766 
1767  problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
1768  problem_to_optimize_->eval_g(n,x,1,m,g);
1769 
1770  //double *xx = new double [n];
1771 
1772  // x ---> xx
1773  //
1774  //
1775  //
1776 
1777 
1778 
1779 
1780  problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
1781  problem_to_optimize_->eval_g(n,x,1,m,g);
1782  //As jacobian is stored by cols fill OsiCuts with cuts
1783  CoinPackedVector * cuts = new CoinPackedVector[nNonLinear_ + 1];
1784  double * lb = new double[nNonLinear_ + 1];
1785  double * ub = new double[nNonLinear_ + 1];
1786 
1787  int * row2cutIdx = new int[m];//store correspondance between index of row and index of cut (some cuts are not generated for rows because linear, or not binding). -1 if constraint does not generate a cut, otherwise index in cuts.
1788  int numCuts = 0;
1789 
1790  const double * rowLower = getRowLower();
1791  const double * rowUpper = getRowUpper();
1792  const double * colLower = getColLower();
1793  const double * colUpper = getColUpper();
1794  const double * duals = getRowPrice() + 2 * n;
1795 
1796  for (int i=0; i< n; i++)
1797  printf ("variable %d: [%g,%g]\n", i, rowLower [i], rowUpper [i]);
1798 
1799  double infty = getInfinity();
1800  double nlp_infty = infty_;
1801 
1802  for(int rowIdx = 0; rowIdx < m ; rowIdx++) {
1803  if(constTypes_[rowIdx] == TNLP::NON_LINEAR) {
1804 #if 0
1805  if(fabs(duals[rowIdx]) == 0.)
1806  {
1807  row2cutIdx[rowIdx] = -1;
1808 #ifdef NDEBUG
1809  (*handler_)<<"non binding constraint"<<CoinMessageEol;
1810 #endif
1811  continue;
1812  }
1813 #endif
1814  row2cutIdx[rowIdx] = numCuts;
1815  if(rowLower[rowIdx] > - nlp_infty)
1816  lb[numCuts] = rowLower[rowIdx] - g[rowIdx];
1817  else
1818  lb[numCuts] = - infty;
1819  if(rowUpper[rowIdx] < nlp_infty)
1820  ub[numCuts] = rowUpper[rowIdx] - g[rowIdx];
1821  else
1822  ub[numCuts] = infty;
1823  if(rowLower[rowIdx] > -infty && rowUpper[rowIdx] < infty)
1824  {
1825  if(duals[rowIdx] >= 0)// <= inequality
1826  lb[numCuts] = - infty;
1827  if(duals[rowIdx] <= 0)// >= inequality
1828  ub[numCuts] = infty;
1829  }
1830 
1831  numCuts++;
1832  }
1833  else
1834  row2cutIdx[rowIdx] = -1;
1835  }
1836 
1837 
1838  for(int i = 0 ; i < nnz_jac_g ; i++) {
1839  const int &rowIdx = jRow_[i];
1840  const int & cutIdx = row2cutIdx[ rowIdx ];
1841  if(cutIdx != -1) {
1842  const int &colIdx = jCol_[i];
1843  //"clean" coefficient
1844  if(cleanNnz(jValues_[i],colLower[colIdx], colUpper[colIdx],
1845  rowLower[rowIdx], rowUpper[rowIdx],
1846  x[colIdx],
1847  lb[cutIdx],
1848  ub[cutIdx], tiny_, veryTiny_)) {
1849  cuts[cutIdx].insert(colIdx,jValues_[i]);
1850  if(lb[cutIdx] > - infty)
1851  lb[cutIdx] += jValues_[i] * x[colIdx];
1852  if(ub[cutIdx] < infty)
1853  ub[cutIdx] += jValues_[i] * x[colIdx];
1854  }
1855  }
1856  }
1857 
1858  int * cut2rowIdx = NULL;
1859  if (IsValid(cutStrengthener_) || oaHandler_->logLevel() > 0) {
1860  cut2rowIdx = new int [numCuts];// Store correspondance between indices of cut and indices of rows. For each cut
1861  for(int rowIdx = 0 ; rowIdx < m ; rowIdx++){
1862  if(row2cutIdx[rowIdx] >= 0){
1863  cut2rowIdx[row2cutIdx[rowIdx]] = rowIdx;
1864  }
1865  }
1866  }
1867 
1868  for(int cutIdx = 0; cutIdx < numCuts; cutIdx++) {
1869  //Compute cut violation
1870  if(x2 != NULL) {
1871  double rhs = cuts[cutIdx].dotProduct(x2);
1872  double violation = 0.;
1873  violation = std::max(violation, rhs - ub[cutIdx]);
1874  violation = std::max(violation, lb[cutIdx] - rhs);
1875  if(violation < theta) {
1876  if(oaHandler_->logLevel() > 0)
1877  oaHandler_->message(CUT_NOT_VIOLATED_ENOUGH, oaMessages_)<<cut2rowIdx[cutIdx]<<violation<<CoinMessageEol;
1878  continue;}
1879  if(oaHandler_->logLevel() > 0)
1880  oaHandler_->message(VIOLATED_OA_CUT_GENERATED, oaMessages_)<<cut2rowIdx[cutIdx]<<violation<<CoinMessageEol;
1881  }
1882  else if (oaHandler_->logLevel() > 0)
1883  oaHandler_->message(OA_CUT_GENERATED, oaMessages_)<<cut2rowIdx[cutIdx]<<CoinMessageEol;
1884  OsiRowCut newCut;
1885  // if(lb[i]>-1e20) assert (ub[i]>1e20);
1886 
1887  if (IsValid(cutStrengthener_)) {
1888  const int& rowIdx = cut2rowIdx[cutIdx];
1889  bool retval =
1890  cutStrengthener_->ComputeCuts(cs, GetRawPtr(tminlp_),
1891  GetRawPtr(problem_), rowIdx,
1892  cuts[cutIdx], lb[cutIdx], ub[cutIdx], g[rowIdx],
1893  rowLower[rowIdx], rowUpper[rowIdx],
1894  n, x, infty);
1895  if (!retval) {
1896  (*messageHandler()) << "error in cutStrengthener_->ComputeCuts\n";
1897  //exit(-2);
1898  }
1899  }
1900  if(global) {
1901  newCut.setGloballyValidAsInteger(1);
1902  }
1903  newCut.setEffectiveness(99.99e99);
1904  newCut.setLb(lb[cutIdx]);
1905  newCut.setUb(ub[cutIdx]);
1906  newCut.setRow(cuts[cutIdx]);
1907  // CftValidator validator;
1908  // validator(newCut);
1909  if(oaHandler_->logLevel()>2){
1910  oaHandler_->print(newCut);}
1911  cs.insert(newCut);
1912  }
1913 
1914  delete[] g;
1915  delete [] cuts;
1916  delete [] row2cutIdx;
1917  delete [] cut2rowIdx;
1918 
1919  if(getObj && ! problem_->hasLinearObjective()) { // Get the objective cuts
1920  double * obj = new double [n];
1921  problem_to_optimize_->eval_grad_f(n, x, 1,obj);
1922  double f;
1923  problem_to_optimize_->eval_f(n, x, 1, f);
1924 
1925  CoinPackedVector v;
1926  v.reserve(n);
1927  lb[nNonLinear_] = -f;
1928  ub[nNonLinear_] = -f;
1929  //double minCoeff = 1e50;
1930  for(int i = 0; i<n ; i++) {
1931  if(cleanNnz(obj[i],colLower[i], colUpper[i],
1932  -getInfinity(), 0,
1933  x[i],
1934  lb[nNonLinear_],
1935  ub[nNonLinear_],tiny_, 1e-15)) {
1936  // minCoeff = std::min(fabs(obj[i]), minCoeff);
1937  v.insert(i,obj[i]);
1938  lb[nNonLinear_] += obj[i] * x[i];
1939  ub[nNonLinear_] += obj[i] * x[i];
1940  }
1941  }
1942  v.insert(n,-1);
1943  //Compute cut violation
1944  bool genCut = true;
1945  if(x2 != NULL) {
1946  double rhs = v.dotProduct(x2);
1947  double violation = std::max(0., rhs - ub[nNonLinear_]);
1948  if(violation < theta) genCut = false;
1949  }
1950  if(genCut) {
1951  if (IsValid(cutStrengthener_)) {
1952  lb[nNonLinear_] = -infty;
1953  bool retval =
1954  cutStrengthener_->ComputeCuts(cs, GetRawPtr(tminlp_),
1955  GetRawPtr(problem_), -1,
1956  v, lb[nNonLinear_], ub[nNonLinear_],
1957  ub[nNonLinear_], -infty, 0.,
1958  n, x, infty);
1959  if (!retval) {
1960  (*handler_)<< "error in cutStrengthener_->ComputeCuts"<<CoinMessageEol;
1961  //exit(-2);
1962  }
1963  }
1964  OsiRowCut newCut;
1965  if(global)
1966  newCut.setGloballyValidAsInteger(1);
1967  newCut.setEffectiveness(99.99e99);
1968  newCut.setRow(v);
1969  newCut.setLb(-COIN_DBL_MAX/*Infinity*/);
1970  newCut.setUb(ub[nNonLinear_]);
1971  // CftValidator validator;
1972  // validator(newCut);
1973  cs.insert(newCut);
1974  }
1975  delete [] obj;
1976  }
1977 
1978  delete []lb;
1979  delete[]ub;
1980 }
1981 
1982 
1983 
1986 void
1987 CouenneMINLPInterface::getConstraintOuterApproximation(OsiCuts &cs, int rowIdx,
1988  const double * x,
1989  const double * x2, bool global)
1990 {
1991  double g;
1992  int * indices = new int[getNumCols()];
1993  double * values = new double[getNumCols()];
1994  int nnz;
1995  problem_->eval_grad_gi(getNumCols(), x, 1, rowIdx, nnz, indices, values);
1996  problem_->eval_gi(getNumCols(),x,1, rowIdx, g);
1997 
1998  CoinPackedVector cut;
1999  double lb;
2000  double ub;
2001 
2002 
2003  const double rowLower = getRowLower()[rowIdx];
2004  const double rowUpper = getRowUpper()[rowIdx];
2005  const double * colLower = getColLower();
2006  const double * colUpper = getColUpper();
2007  const double dual = (getRowPrice() + 2 * getNumCols())[rowIdx];
2008  double infty = getInfinity();
2009  double nlp_infty = infty_;
2010 
2011  if(rowLower > - nlp_infty)
2012  lb = rowLower - g;
2013  else
2014  lb = - infty;
2015  if(rowUpper < nlp_infty)
2016  ub = rowUpper - g;
2017  else
2018  ub = infty;
2019  if(rowLower > -infty && rowUpper < infty)
2020  {
2021  if(dual >= 0)// <= inequality
2022  lb = - infty;
2023  if(dual <= 0)// >= inequality
2024  ub = infty;
2025  }
2026 
2027  for(int i = 0 ; i < nnz; i++) {
2028  const int &colIdx = indices[i];
2029  //"clean" coefficient
2030  if(cleanNnz(values[i],colLower[colIdx], colUpper[colIdx],
2031  rowLower, rowUpper,
2032  x[colIdx],
2033  lb,
2034  ub, tiny_, veryTiny_)) {
2035  cut.insert(colIdx,values[i]);
2036  if(lb > - infty)
2037  lb += values[i] * x[colIdx];
2038  if(ub < infty)
2039  ub += values[i] * x[colIdx];
2040  }
2041  }
2042 
2043  OsiRowCut newCut;
2044 
2045  if(global) {
2046  newCut.setGloballyValidAsInteger(1);
2047  }
2048  newCut.setEffectiveness(99.99e99);
2049  newCut.setLb(lb);
2050  newCut.setUb(ub);
2051  newCut.setRow(cut);
2052  cs.insert(newCut);
2053 
2054  delete [] indices;
2055  delete [] values;
2056 }
2057 
2058 void
2059 CouenneMINLPInterface::switchToFeasibilityProblem(int n,const double * x_bar,const int *inds,
2060  double a, double s, int L){
2061  if(! IsValid(feasibilityProblem_)) {
2062  throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
2063  }
2064  feasibilityProblem_->set_use_feasibility_pump_objective(true);
2065  feasibilityProblem_->set_dist2point_obj(n,(const Number *) x_bar,(const Index *) inds);
2066  feasibilityProblem_->setLambda(a);
2067  feasibilityProblem_->setSigma(s);
2068  feasibilityProblem_->setNorm(L);
2069  feasibilityProblem_->set_use_cutoff_constraint(false);
2070  feasibilityProblem_->set_use_local_branching_constraint(false);
2071  problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
2072  feasibility_mode_ = true;
2073 }
2074 
2075 void
2076 CouenneMINLPInterface::switchToFeasibilityProblem(int n,const double * x_bar,const int *inds,
2077  double rhs_local_branching_constraint){
2078  if(! IsValid(feasibilityProblem_)) {
2079  throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
2080  }
2081  feasibilityProblem_->set_use_feasibility_pump_objective(false);
2082  feasibilityProblem_->set_dist2point_obj(n,(const Number *) x_bar,(const Index *) inds);
2083  feasibilityProblem_->set_use_cutoff_constraint(false);
2084  feasibilityProblem_->set_use_local_branching_constraint(true);
2085  feasibilityProblem_->set_rhs_local_branching_constraint(rhs_local_branching_constraint);
2086  problem_to_optimize_ = GetRawPtr(feasibilityProblem_);
2087  feasibility_mode_ = true;
2088 }
2089 
2090 void
2091 CouenneMINLPInterface::switchToOriginalProblem(){
2092  problem_to_optimize_ = GetRawPtr(problem_);
2093  feasibility_mode_ = false;
2094 }
2095 
2096 double
2097 CouenneMINLPInterface::solveFeasibilityProblem(int n,const double * x_bar,const int *inds,
2098  double a, double s, int L)
2099 {
2100  if(! IsValid(feasibilityProblem_)) {
2101  throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
2102  }
2103  feasibilityProblem_->set_use_feasibility_pump_objective(true);
2104  feasibilityProblem_->set_dist2point_obj(n,(const Number *) x_bar,(const Index *) inds);
2105  feasibilityProblem_->setLambda(a);
2106  feasibilityProblem_->setSigma(s);
2107  feasibilityProblem_->setNorm(L);
2108  feasibilityProblem_->set_use_cutoff_constraint(false);
2109  feasibilityProblem_->set_use_local_branching_constraint(false);
2110  nCallOptimizeTNLP_++;
2111  totalNlpSolveTime_-=CoinCpuTime();
2112  SmartPtr<TNLPSolver> app2 = app_->clone();
2113  app2->options()->SetIntegerValue("print_level", (Index) 0);
2114  optimizationStatus_ = app2->OptimizeTNLP(GetRawPtr(feasibilityProblem_));
2115  totalNlpSolveTime_+=CoinCpuTime();
2116  hasBeenOptimized_=true;
2117  return getObjValue();
2118 }
2119 
2120 double
2121 CouenneMINLPInterface::solveFeasibilityProblem(int n,const double * x_bar,const int *inds,
2122  int L, double cutoff)
2123 {
2124  if(! IsValid(feasibilityProblem_)) {
2125  throw SimpleError("No feasibility problem","getFeasibilityOuterApproximation");
2126  }
2127  feasibilityProblem_->set_use_feasibility_pump_objective(true);
2128  feasibilityProblem_->set_dist2point_obj(n,(const Number *) x_bar,(const Index *) inds);
2129  feasibilityProblem_->setLambda(1.0);
2130  feasibilityProblem_->setSigma(0.0);
2131  feasibilityProblem_->setNorm(L);
2132  feasibilityProblem_->set_use_cutoff_constraint(true);
2133  feasibilityProblem_->set_cutoff(cutoff);
2134  feasibilityProblem_->set_use_local_branching_constraint(false);
2135  nCallOptimizeTNLP_++;
2136  totalNlpSolveTime_-=CoinCpuTime();
2137  SmartPtr<TNLPSolver> app2 = app_->clone();
2138  app2->options()->SetIntegerValue("print_level", (Index) 0);
2139  optimizationStatus_ = app2->OptimizeTNLP(GetRawPtr(feasibilityProblem_));
2140  totalNlpSolveTime_+=CoinCpuTime();
2141  hasBeenOptimized_=true;
2142  return getObjValue();
2143 }
2144 
2145 double
2146 CouenneMINLPInterface::getFeasibilityOuterApproximation(int n,const double * x_bar,const int *inds, OsiCuts &cs, bool addOnlyViolated, bool global)
2147 {
2148  double ret_val = solveFeasibilityProblem(n, x_bar, inds, 1, 0, 2);
2149  getOuterApproximation(cs, getColSolution(), 0, (addOnlyViolated? x_bar:NULL)
2150  , global);
2151  return ret_val;
2152 }
2153 
2154 
2155 static bool WarnedForNonConvexOa=false;
2156 
2157 void
2158 CouenneMINLPInterface::extractLinearRelaxation(OsiSolverInterface &si,
2159  const double * x, bool getObj)
2160 {
2161  double * rowLow = NULL;
2162  double * rowUp = NULL;
2163 
2164  int n;
2165  int m;
2166  int nnz_jac_g;
2167  int nnz_h_lag;
2168  TNLP::IndexStyleEnum index_style;
2169  //Get problem information
2170  problem_to_optimize_->get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
2171 
2172  //if not allocated allocate spaced for stroring jacobian
2173  if(jRow_ == NULL || jCol_ == NULL || jValues_ == NULL)
2174  initializeJacobianArrays();
2175 
2176  //get Jacobian
2177  problem_to_optimize_->eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL, jValues_);
2178 
2179 
2180  double *g = new double[m];
2181  problem_to_optimize_->eval_g(n, x, 1, m, g);
2182 
2183  rowLow = new double[m];
2184  rowUp = new double[m];
2185  int * nonBindings = new int[m];//store non binding constraints (which are to be removed from OA)
2186  int numNonBindings = 0;
2187  const double * rowLower = getRowLower();
2188  const double * rowUpper = getRowUpper();
2189  const double * colLower = getColLower();
2190  const double * colUpper = getColUpper();
2191  const double * duals = getRowPrice() + 2*n;
2192  assert(m==getNumRows());
2193  double infty = si.getInfinity();
2194  double nlp_infty = infty_;
2195 
2196  for(int i = 0 ; i < m ; i++) {
2197  if(constTypes_[i] == TNLP::NON_LINEAR) {
2198  //If constraint is range not binding prepare to remove it
2199  if(rowLower[i] > -nlp_infty && rowUpper[i] < nlp_infty && fabs(duals[i]) == 0.)
2200  {
2201  nonBindings[numNonBindings++] = i;
2202  continue;
2203  }
2204  else
2205  if(rowLower[i] > - nlp_infty){
2206  rowLow[i] = (rowLower[i] - g[i]) - 1e-07;
2207  if(! WarnedForNonConvexOa && rowUpper[i] < nlp_infty){
2208  messageHandler()->message(WARNING_NON_CONVEX_OA, messages_)<<CoinMessageEol;
2209  WarnedForNonConvexOa = true;
2210  }
2211  }
2212  else
2213  rowLow[i] = - infty;
2214  if(rowUpper[i] < nlp_infty)
2215  rowUp[i] = (rowUpper[i] - g[i]) + 1e-07;
2216  else
2217  rowUp[i] = infty;
2218 
2219  //If equality or ranged constraint only add one side by looking at sign of dual multiplier
2220  if(rowLower[i] > -nlp_infty && rowUpper[i] < nlp_infty)
2221  {
2222  if(duals[i] >= 0.)// <= inequality
2223  rowLow[i] = - infty;
2224  if(duals[i] <= 0.)// >= inequality
2225  rowUp[i] = infty;
2226  }
2227  }
2228  else {
2229  if(rowLower[i] > -nlp_infty){
2230  // printf("Lower %g ", rowLower[i]);
2231  rowLow[i] = (rowLower[i] - g[i]);
2232  }
2233  else
2234  rowLow[i] = - infty;
2235  if(rowUpper[i] < nlp_infty){
2236  // printf("Upper %g ", rowUpper[i]);
2237  rowUp[i] = (rowUpper[i] - g[i]);
2238  }
2239  else
2240  rowUp[i] = infty;
2241  }
2242  }
2243 
2244 
2245 
2246  //Then convert everything to a CoinPackedMatrix
2247  //Go through values, clean coefficients and fix bounds
2248  for(int i = 0 ; i < nnz_jac_g ; i++) {
2249  if(constTypes_[jRow_[i]] != TNLP::LINEAR){//For linear just copy is fine.
2250  if(//For other clean tinys
2251  cleanNnz(jValues_[i],colLower[jCol_[i]], colUpper[jCol_[i]],
2252  rowLower[jRow_[i]], rowUpper[jRow_[i]],
2253  x[jCol_[i]],
2254  rowLow[jRow_[i]],
2255  rowUp[jRow_[i]], tiny_, veryTiny_)) {
2256  rowLow[jRow_[i]] += jValues_[i] * x[jCol_ [i]];
2257  rowUp[jRow_[i]] += jValues_[i] *x[jCol_[i]];
2258  }
2259  }
2260  else {
2261  double value = jValues_[i] * getColSolution()[jCol_[i]];
2262  rowLow[jRow_[i]] += value;
2263  rowUp[jRow_[i]] += value;
2264  }
2265  }
2266  CoinPackedMatrix mat(true, jRow_, jCol_, jValues_, nnz_jac_g);
2267  mat.setDimensions(m,n); // In case matrix was empty, this should be enough
2268 
2269  //remove non-bindings equality constraints
2270  mat.deleteRows(numNonBindings, nonBindings);
2271 
2272  int numcols=getNumCols();
2273  double *obj = new double[numcols];
2274  for(int i = 0 ; i < numcols ; i++)
2275  obj[i] = 0.;
2276 
2277 
2278  si.loadProblem(mat, getColLower(), getColUpper(), obj, rowLow, rowUp);
2279  delete [] rowLow;
2280  delete [] rowUp;
2281  delete [] nonBindings;
2282  delete [] g;
2283  for(int i = 0 ; i < getNumCols() ; i++) {
2284  if(isInteger(i))
2285  si.setInteger(i);
2286  }
2287  if(getObj) {
2288  bool addObjVar = false;
2289  if(problem_->hasLinearObjective()){
2290  //Might be in trouble if objective has a constant part
2291  // for now just check that f(0) = 0.
2292  // If it is not adding a constant term does not seem supported by Osi
2293  // for now
2294  double zero;
2295  problem_to_optimize_->eval_f(n, obj, 1, zero);
2296  si.setDblParam(OsiObjOffset, -zero);
2297  //if(fabs(zero - 0) > 1e-10)
2298  //addObjVar = true;
2299  //else {
2300  //Copy the linear objective and don't create a dummy variable.
2301  problem_to_optimize_->eval_grad_f(n, x, 1,obj);
2302  si.setObjective(obj);
2303  //}
2304  }
2305  else {
2306  addObjVar = true;
2307  }
2308 
2309  if(addObjVar){
2310  //add variable alpha
2311  //(alpha should be empty in the matrix with a coefficient of -1 and unbounded)
2312  CoinPackedVector a;
2313  si.addCol(a,-si.getInfinity(), si.getInfinity(), 1.);
2314 
2315  // Now get the objective cuts
2316  // get the gradient, pack it and add the cut
2317  problem_to_optimize_->eval_grad_f(n, x, 1,obj);
2318  double ub;
2319  problem_to_optimize_->eval_f(n, x, 1, ub);
2320  ub*=-1;
2321  double lb = -1e300;
2322  CoinPackedVector objCut;
2323  CoinPackedVector * v = &objCut;
2324  v->reserve(n);
2325  for(int i = 0; i<n ; i++) {
2326  if(nnz_jac_g)
2327  {
2328  if(cleanNnz(obj[i],colLower[i], colUpper[i],
2329  -getInfinity(), 0,
2330  x[i],
2331  lb,
2332  ub, tiny_, veryTiny_)) {
2333  v->insert(i,obj[i]);
2334  lb += obj[i] * x[i];
2335  ub += obj[i] * x[i];
2336  }
2337  }
2338  else //Unconstrained problem can not put clean coefficient
2339  {
2340  if(cleanNnz(obj[i],colLower[i], colUpper[i],
2341  -getInfinity(), 0,
2342  x[i],
2343  lb,
2344  ub, 1e-03, 1e-08)) {
2345  v->insert(i,obj[i]);
2346  lb += obj[i] * x[i];
2347  ub += obj[i] * x[i];
2348  }
2349  }
2350  }
2351  v->insert(n,-1);
2352  si.addRow(objCut, lb, ub);
2353  }
2354  }
2355  // si.writeMpsNative("OA.mps",NULL, NULL, 1);
2356  delete [] obj;
2357 }
2358 
2360 void
2361 CouenneMINLPInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts)
2362 {
2363  if(numberCuts)
2364  freeCachedRowRim();
2365  const OsiRowCut ** cutsPtrs = new const OsiRowCut*[numberCuts];
2366  for(int i = 0 ; i < numberCuts ; i++)
2367  {
2368  cutsPtrs[i] = &cuts[i];
2369  }
2370  problem_->addCuts(numberCuts, cutsPtrs);
2371  delete [] cutsPtrs;
2372 }
2373 
2374 void
2375 CouenneMINLPInterface::solveAndCheckErrors(bool warmStarted, bool throwOnFailure,
2376  const char * whereFrom)
2377 {
2378  totalNlpSolveTime_-=CoinCpuTime();
2379  if(warmStarted)
2380  optimizationStatus_ = app_->ReOptimizeTNLP(GetRawPtr(problem_to_optimize_));
2381  else
2382  optimizationStatus_ = app_->OptimizeTNLP(GetRawPtr(problem_to_optimize_));
2383  totalNlpSolveTime_+=CoinCpuTime();
2384  nCallOptimizeTNLP_++;
2385  hasBeenOptimized_ = true;
2386 
2387 
2388  //Options should have been printed if not done already turn off Ipopt output
2389  if(!hasPrintedOptions) {
2390  hasPrintedOptions = 1;
2391  //app_->Options()->SetIntegerValue("print_level",0, true, true);
2392  app_->options()->SetStringValue("print_user_options","no", false, true);
2393  }
2394 
2395  bool otherDisagree = false ;
2396 #if 0
2397  if(optimizationStatus_ == TNLPSolver::notEnoughFreedom)//Too few degrees of freedom
2398  {
2399  (*messageHandler())<<"Too few degrees of freedom...."<<CoinMessageEol;
2400  int numrows = getNumRows();
2401  int numcols = getNumCols();
2402 
2403  const double * colLower = getColLower();
2404  const double * colUpper = getColUpper();
2405 
2406 
2407  const double * rowLower = getRowLower();
2408  const double * rowUpper = getRowUpper();
2409 
2410  int numberFixed = 0;
2411  for(int i = 0 ; i < numcols ; i++)
2412  {
2413  if(colUpper[i] - colLower[i] <= INT_BIAS)
2414  {
2415  numberFixed++;
2416  }
2417  }
2418  int numberEqualities = 0;
2419  for(int i = 0 ; i < numrows ; i++)
2420  {
2421  if(rowUpper[i] - rowLower[i] <= INT_BIAS)
2422  {
2423  numberEqualities++;
2424  }
2425  }
2426  if(numcols - numberFixed > numberEqualities || numcols < numberEqualities)
2427  {
2428  std::string probName;
2429  getStrParam(OsiProbName, probName);
2430  throw newUnsolvedError(app_->errorCode(), problem_, probName);
2431  }
2432  double * saveColLow = CoinCopyOfArray(getColLower(), getNumCols());
2433  double * saveColUp = CoinCopyOfArray(getColUpper(), getNumCols());
2434 
2435  for(int i = 0; i < numcols && numcols - numberFixed <= numberEqualities ; i++)
2436  {
2437  if(colUpper[i] - colLower[i] <= INT_BIAS)
2438  {
2439  setColLower(i, saveColLow[i]-1e-06);
2440  setColUpper(i, saveColLow[i]+1e-06);
2441  numberFixed--;
2442  }
2443  }
2444  solveAndCheckErrors(warmStarted, throwOnFailure, whereFrom);
2445  //restore
2446  for(int i = 0; i < numcols && numcols - numberFixed < numrows ; i++)
2447  {
2448  problem_->SetVariableLowerBound(i,saveColLow[i]);
2449  problem_->SetVariableUpperBound(i,saveColUp[i]);
2450  }
2451  delete [] saveColLow;
2452  delete [] saveColUp;
2453  return;
2454  }
2455  else
2456 #endif
2457  if(!app_->isRecoverable(optimizationStatus_))//Solver failed and the error can not be recovered, throw it
2458  {
2459  std::string probName;
2460  getStrParam(OsiProbName, probName);
2461  throw newUnsolvedError(app_->errorCode(), problem_, probName);
2462  }
2463  else if(testOthers_ && !app_->isError(optimizationStatus_)){
2464  Ipopt::SmartPtr<TMINLP2TNLP> problem_copy = problem_->clone();
2465  //Try other solvers and see if they agree
2466  int f =1;
2467  for(std::list<Ipopt::SmartPtr<TNLPSolver> >::iterator i = debug_apps_.begin();
2468  i != debug_apps_.end() ; i++){
2469  TNLPSolver::ReturnStatus otherStatus = (*i)->OptimizeTNLP(GetRawPtr(problem_copy));
2470  messageHandler()->message(LOG_LINE, messages_)
2471  <<'d'<<f++<<statusAsString(otherStatus)<<problem_copy->obj_value()
2472  <<(*i)->IterationCount()<<(*i)->CPUTime()<<CoinMessageEol;
2473  if(!(*i)->isError(otherStatus)){
2474  CoinRelFltEq eq(1e-05);
2475  if(otherStatus != optimizationStatus_){
2476  otherDisagree = true;
2477  messageHandler()->message(SOLVER_DISAGREE_STATUS, messages_)
2478  <<app_->solverName()<<statusAsString()
2479  <<(*i)->solverName()<<statusAsString(otherStatus)<<CoinMessageEol;
2480  }
2481  else if(isProvenOptimal() && !eq(problem_->obj_value(),problem_copy->obj_value()))
2482  {
2483  otherDisagree = true;
2484  messageHandler()->message(SOLVER_DISAGREE_VALUE, messages_)
2485  <<app_->solverName()<<problem_->obj_value()
2486  <<(*i)->solverName()<<problem_copy->obj_value()<<CoinMessageEol;
2487  }
2488  }
2489  }
2490  }
2491  try{
2492  totalIterations_ += app_->IterationCount();
2493  }
2494  catch(SimpleError &E)
2495  {
2496  if (throwOnFailure)//something failed throw
2497  {
2498  throw SimpleError("No statistics available from Ipopt",whereFrom);
2499  }
2500  else {
2501  return;
2502  }
2503  }
2504  if(problem_->hasUpperBoundingObjective()){//Check if solution is integer and recompute objective value using alternative objective function
2505  const double * sol = getColSolution();
2506  bool integerSol = true;
2507  double intTol = 1e-08;
2508  if(objects()){
2509  int nObjects = numberObjects();
2510  OsiObject ** object = objects();
2511  for(int i = 0 ; i< nObjects ; i++){
2512  int dummy;
2513  if(object[i]->infeasibility(this,dummy) > intTol)
2514  {
2515  integerSol=false;
2516  break;
2517  }
2518  }
2519  }
2520  else{//Only works for integer constraints
2521  int numcols = getNumCols();
2522  for(int i = 0 ; i < numcols ; i++){
2523  if(isInteger(i) || isBinary(i)){
2524  if(fabs(sol[i] - floor(sol[i]+0.5)) > intTol){
2525  integerSol = false;
2526  break;
2527  }
2528  }
2529  }
2530  }
2531  if(integerSol&&isProvenOptimal()){
2532  double help= problem_->evaluateUpperBoundingFunction(sol);
2533 
2534 
2535  OsiAuxInfo * auxInfo = getAuxiliaryInfo();
2536  Bonmin::AuxInfo * bonInfo = dynamic_cast<Bonmin::AuxInfo *>(auxInfo);
2537  if(bonInfo!=0)
2538  {
2539 
2540  if(help<bonInfo->bestObj2())
2541  {
2542  bonInfo->setBestObj2(help);
2543  bonInfo->setBestSolution2(getNumCols(), const_cast<double *>(getColSolution()));
2544 
2545  messageHandler()->message(ALTERNATE_OBJECTIVE, messages_)
2546  <<help<<CoinMessageEol;
2547  }
2548  }
2549  else {
2550  printf("\nWARNING: the algorithm selected does not consider the second objective function\n");
2551  }
2552  }
2553  }
2554  messageHandler()->message(IPOPT_SUMMARY, messages_)
2555  <<whereFrom<<optimizationStatus_<<app_->IterationCount()<<app_->CPUTime()<<CoinMessageEol;
2556 
2557  if((nCallOptimizeTNLP_ % 20) == 1)
2558  messageHandler()->message(LOG_HEAD, messages_)<<CoinMessageEol;
2559 
2560 
2561  if ( (numIterationSuspect_ >= 0 && (getIterationCount()>numIterationSuspect_ || isAbandoned())) ||
2562  ( otherDisagree )){
2563  messageHandler()->message(SUSPECT_PROBLEM,
2564  messages_)<<nCallOptimizeTNLP_<<CoinMessageEol;
2565  std::string subProbName;
2566  getStrParam(OsiProbName, subProbName);
2567  std::ostringstream os;
2568  os<<"_"<<nCallOptimizeTNLP_;
2569  subProbName+=os.str();
2570  problem_->outputDiffs(subProbName, NULL/*getVarNames()*/);
2571  }
2572 
2573 }
2574 
2576 // Solve Methods //
2579 void CouenneMINLPInterface::initialSolve()
2580 {
2581  assert(IsValid(app_));
2582  assert(IsValid(problem_));
2583 
2584  // Discard warmstart_ if we had one
2585  delete warmstart_;
2586  warmstart_ = NULL;
2587 
2588  if(!hasPrintedOptions) {
2589  int printOptions;
2590  app_->options()->GetEnumValue("print_user_options",printOptions,"bonmin.");
2591  if(printOptions)
2592  app_->options()->SetStringValue("print_user_options","yes",true,true);
2593  }
2594  if(exposeWarmStart_)
2595  app_->disableWarmStart();
2596  solveAndCheckErrors(0,1,"initialSolve");
2597 
2598  //Options should have been printed if not done already turn off Ipopt output
2599  if(!hasPrintedOptions) {
2600  hasPrintedOptions = 1;
2601  app_->options()->SetStringValue("print_user_options","no");
2602  app_->options()->SetIntegerValue("print_level",0);
2603  }
2604 
2605  messageHandler()->message(LOG_FIRST_LINE, messages_)<<nCallOptimizeTNLP_
2606  <<statusAsString()
2607  <<getObjValue()
2608  <<app_->IterationCount()
2609  <<app_->CPUTime()
2610  <<CoinMessageEol;
2611 
2612  int numRetry = firstSolve_ ? numRetryInitial_ : numRetryResolve_;
2613  if(isAbandoned()) {
2614  resolveForRobustness(numRetryUnsolved_);
2615  }
2616  else if(numRetry)
2617  {
2618  resolveForCost(numRetry, numRetryInitial_ > 0);
2620  numRetryInitial_ = 0;
2621  }
2622  firstSolve_ = false;
2623 
2624  // if warmstart_ is not empty then had to use resolveFor... and that created
2625  // the warmstart at the end, and we have nothing to do here. Otherwise...
2626  if (! warmstart_ && ! isAbandoned()) {
2627  if (exposeWarmStart_) {
2628  warmstart_ = app_->getWarmStart(problem_);
2629  }
2630  }
2631 }
2632 
2635 void
2636 CouenneMINLPInterface::resolve()
2637 {
2638  assert(IsValid(app_));
2639  assert(IsValid(problem_));
2640 
2641  int has_warmstart = warmstart_ == NULL ? 0 : 1;
2642  if(warmstart_ == NULL) has_warmstart = 0;
2643  else if(!app_->warmStartIsValid(warmstart_)) has_warmstart = 1;
2644  else has_warmstart = 2;
2645  if (has_warmstart < 2) {
2646  // empty (or unrecognized) warmstart
2647  initialSolve();
2648  return;
2649  }
2650  app_->setWarmStart(warmstart_, problem_);
2651  delete warmstart_;
2652  warmstart_ = NULL;
2653 
2654  if (INT_BIAS > 0.) {
2655  app_->options()->SetStringValue("warm_start_same_structure", "yes");
2656  }
2657  else {
2658  app_->options()->SetStringValue("warm_start_same_structure", "no");
2659  }
2660 
2661  if(problem_->duals_init() != NULL)
2662  app_->enableWarmStart();
2663  else app_->disableWarmStart();
2664  solveAndCheckErrors(1,1,"resolve");
2665 
2666  messageHandler()->message(LOG_FIRST_LINE, messages_)<<nCallOptimizeTNLP_
2667  <<statusAsString()
2668  <<getObjValue()
2669  <<app_->IterationCount()
2670  <<app_->CPUTime()<<CoinMessageEol;
2671 
2672  if(isAbandoned()) {
2673  resolveForRobustness(numRetryUnsolved_);
2674  }
2675  else if(numRetryResolve_ ||
2676  (numRetryInfeasibles_ && isProvenPrimalInfeasible() ))
2677  resolveForCost(std::max(numRetryResolve_, numRetryInfeasibles_), 0);
2678 
2679  // if warmstart_ is not empty then had to use resolveFor... and that created
2680  // the warmstart at the end, and we have nothing to do here. Otherwise...
2681  if (! warmstart_ && ! isAbandoned()) {
2682  if (exposeWarmStart_) {
2683  warmstart_ = app_->getWarmStart(problem_);
2684  }
2685  }
2686 }
2687 
2688 
2690 // Methods returning info on how the solution process terminated //
2693 bool CouenneMINLPInterface::isAbandoned() const
2694 {
2695  return (
2696  (optimizationStatus_==TNLPSolver::iterationLimit)||
2697  (optimizationStatus_==TNLPSolver::computationError)||
2698  (optimizationStatus_==TNLPSolver::illDefinedProblem)||
2699  (optimizationStatus_==TNLPSolver::illegalOption)||
2700  (optimizationStatus_==TNLPSolver::externalException)|
2701  (optimizationStatus_==TNLPSolver::exception)
2702  );
2703 }
2704 
2706 bool CouenneMINLPInterface::isProvenOptimal() const
2707 {
2708  return (optimizationStatus_==TNLPSolver::solvedOptimal) ||
2709  (optimizationStatus_==TNLPSolver::solvedOptimalTol);
2710 }
2712 bool CouenneMINLPInterface::isProvenPrimalInfeasible() const
2713 {
2714  return (optimizationStatus_ == TNLPSolver::provenInfeasible);
2715 }
2717 bool CouenneMINLPInterface::isProvenDualInfeasible() const
2718 {
2719  return (optimizationStatus_ == TNLPSolver::unbounded);
2720 }
2722 bool CouenneMINLPInterface::isPrimalObjectiveLimitReached() const
2723 {
2724  (*handler_)<<"Warning : isPrimalObjectiveLimitReached not implemented yet"<<CoinMessageEol;
2725  return 0;
2726 }
2728 bool CouenneMINLPInterface::isDualObjectiveLimitReached() const
2729 {
2730  // (*messageHandler_)<<"Warning : isDualObjectiveLimitReached not implemented yet"<<CoinMessageEol;
2731  return (optimizationStatus_==TNLPSolver::unbounded);
2732 
2733 }
2735 bool CouenneMINLPInterface::isIterationLimitReached() const
2736 {
2737  return (optimizationStatus_==TNLPSolver::iterationLimit);
2738 }
2739 
2740 void
2741 CouenneMINLPInterface::extractInterfaceParams()
2742 {
2743  if (IsValid(app_)) {
2744  int logLevel;
2745  app_->options()->GetIntegerValue("nlp_log_level", logLevel,"bonmin.");
2746  messageHandler()->setLogLevel(logLevel);
2747 
2748 #ifdef COIN_HAS_FILTERSQP
2749  FilterSolver * filter = dynamic_cast<FilterSolver *>(GetRawPtr(app_));
2750 
2751  bool is_given =
2752 #endif
2753  app_->options()->GetNumericValue("max_random_point_radius",maxRandomRadius_,"bonmin.");
2754 
2755 #ifdef COIN_HAS_FILTERSQP
2756  if(filter && !is_given){
2757  // overwriting default for filter
2758  maxRandomRadius_ = 10.;
2759  }
2760 #endif
2761 
2762  int oaCgLogLevel = 0;
2763  app_->options()->GetIntegerValue("oa_cuts_log_level", oaCgLogLevel,"bonmin.");
2764  oaHandler_->setLogLevel(oaCgLogLevel);
2765 
2766  int exposeWs = false;
2767  app_->options()->GetEnumValue("warm_start", exposeWs, "bonmin.");
2768  setExposeWarmStart(exposeWs > 0);
2769 
2770  app_->options()->GetIntegerValue("num_retry_unsolved_random_point", numRetryUnsolved_,"bonmin.");
2771  app_->options()->GetIntegerValue("num_resolve_at_root", numRetryInitial_,"bonmin.");
2772  app_->options()->GetIntegerValue("num_resolve_at_node", numRetryResolve_,"bonmin.");
2773  app_->options()->GetIntegerValue("num_resolve_at_infeasibles", numRetryInfeasibles_,"bonmin.");
2774  app_->options()->GetIntegerValue("num_iterations_suspect", numIterationSuspect_,"bonmin.");
2775  app_->options()->GetEnumValue("nlp_failure_behavior",pretendFailIsInfeasible_,"bonmin.");
2776  app_->options()->GetNumericValue
2777  ("warm_start_bound_frac" ,pushValue_,"bonmin.");
2778  app_->options()->GetNumericValue("tiny_element",tiny_,"bonmin.");
2779  app_->options()->GetNumericValue("very_tiny_element",veryTiny_,"bonmin.");
2780  app_->options()->GetNumericValue("random_point_perturbation_interval",max_perturbation_,"bonmin.");
2781  app_->options()->GetEnumValue("random_point_type",randomGenerationType_,"bonmin.");
2782  int cut_strengthening_type;
2783  app_->options()->GetEnumValue("cut_strengthening_type", cut_strengthening_type,"bonmin.");
2784 
2785  if (cut_strengthening_type != CS_None) {
2786  // TNLP solver to be used in the cut strengthener
2787  cutStrengthener_ = new CutStrengthener(app_->clone(), app_->options());
2788  }
2789  }
2790 }
2791 
2792 void
2793 CouenneMINLPInterface::SetStrongBrachingSolver(SmartPtr<StrongBranchingSolver> strong_branching_solver)
2794 {
2795  strong_branching_solver_ = strong_branching_solver;
2796 }
2797 
2798 //#define STRONG_COMPARE
2799 #ifdef STRONG_COMPARE
2800 static double objorig;
2801 #endif
2802 
2803 void
2804 CouenneMINLPInterface::markHotStart()
2805 {
2806  if (IsValid(strong_branching_solver_)) {
2807 #ifdef STRONG_COMPARE
2808  // AWDEBUG
2809  OsiSolverInterface::markHotStart();
2810  objorig = getObjValue();
2811 #endif
2812  optimizationStatusBeforeHotStart_ = optimizationStatus_;
2813  strong_branching_solver_->markHotStart(this);
2814  }
2815  else {
2816  // Default Implementation
2817  OsiSolverInterface::markHotStart();
2818  }
2819 }
2820 
2821 void
2822 CouenneMINLPInterface::solveFromHotStart()
2823 {
2824  if (IsValid(strong_branching_solver_)) {
2825 #ifdef STRONG_COMPARE
2826  // AWDEBUG
2827  OsiSolverInterface::solveFromHotStart();
2828  double obj_nlp = getObjValue() - objorig;
2829 #endif
2830  optimizationStatus_ = strong_branching_solver_->solveFromHotStart(this);
2831  hasBeenOptimized_ = true;
2832 #ifdef STRONG_COMPARE
2833  double obj_other = getObjValue() - objorig;
2834  printf("AWDEBUG: Strong Branching results: NLP = %15.8e Other = %15.8e\n",
2835  obj_nlp, obj_other);
2836 #endif
2837  }
2838  else {
2839  // Default Implementation
2840  OsiSolverInterface::solveFromHotStart();
2841  }
2842 }
2843 
2844 void
2845 CouenneMINLPInterface::unmarkHotStart()
2846 {
2847  if (IsValid(strong_branching_solver_)) {
2848 #ifdef STRONG_COMPARE
2849  // AWDEBUG
2850  OsiSolverInterface::unmarkHotStart();
2851 #endif
2852  strong_branching_solver_->unmarkHotStart(this);
2853  optimizationStatus_ = optimizationStatusBeforeHotStart_;
2854  }
2855  else {
2856  // Default Implementation
2857  OsiSolverInterface::unmarkHotStart();
2858  }
2859 }
2860 
2861 const double * CouenneMINLPInterface::getObjCoefficients() const
2862 {
2863  const int n = getNumCols();
2864  delete [] obj_;
2865  obj_ = NULL;
2866  obj_ = new double[n];
2867 
2868  bool new_x = true;
2869  const double* x_sol = problem_->x_sol();
2870  bool retval = problem_->eval_grad_f(n, x_sol, new_x, obj_);
2871 
2872  if (!retval) {
2873  // Let's see if that happens - it will cause a crash
2874  fprintf(stderr, "ERROR WHILE EVALUATING GRAD_F in CouenneMINLPInterface::getObjCoefficients()\n");
2875  delete [] obj_;
2876  obj_ = NULL;
2877  }
2878 
2879  return obj_;
2880 }
2881 
2882 
2883 }
2885 #endif
double * values
CouNumber solve(CouNumber *solution)
solves and returns the optimal objective function and the solution
void setBestSolution2(int n, double *d)
Definition: BonAuxInfos.hpp:86
ULong L
Definition: OSdtoa.cpp:1816
pos
position where the operator should be printed when printing the expression
ULong x2
Definition: OSdtoa.cpp:1776
void setInitSol(const CouNumber *sol)
sets the initial solution for the NLP solver
void fint fint fint real * a
bool IsValid(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:465
int std_m(int n)
Definition: BonMsgUtils.hpp:10
Ipopt interior point algorithm
void setBestObj2(double o)
Set an alternate objective value.
Definition: BonAuxInfos.hpp:82
CouenneProblem * problem() const
return pointer to Couenne problem
Solver
Solvers for solving nonlinear programs.
The IpoptSolver class solves problems using Ipopt.
void fint fint fint real fint real real real real * f
Ipopt::OptionsList * options() const
return pointer to options
SimpleReferenced< X > * make_referenced(X other)
Definition: BonTypes.hpp:87
void fint fint fint real fint real real real real real real real real real * e
filterSQP Sequential Quadratic Programming algorithm
#define INT_BIAS
CouenneProblem * clone() const
Clone method (for use within CouenneCutGenerator::clone)
Use all solvers.
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
static int
Definition: OSdtoa.cpp:2173
#define INTEGER
static bool WarnedForNonConvexOa
U * GetRawPtr(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:452
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
double CouNumber
main number type in Couenne
static bool cleanNnz(double &value, double colLower, double colUpper, double rowLower, double rowUpper, double colsol, double &lb, double &ub, double tiny, double veryTiny)
#define ADD_MSG(Id, Type, Level, MSG)
Definition: BonMsgUtils.hpp:7
static void register_OA_options(SmartPtr< RegisteredOptions > roptions)
int warn_m(int n)
Definition: BonMsgUtils.hpp:11
void fint fint fint real fint real real real real real real * g
void fint * m
CouenneProblem * problem_
Symbolic representation of the problem.
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
static void register_general_options(SmartPtr< RegisteredOptions > roptions)
Register options.
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
void fint * n
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonAuxInfos.hpp:23
real c
real infty
void fint fint fint real fint real * x
bool isInteger(CouNumber x)
is this number integer?