Scippy

SCIP

Solving Constraint Integer Programs

nlpi_ipopt.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file nlpi_ipopt.cpp
17  * @ingroup NLPIS
18  * @brief Ipopt NLP interface
19  * @author Stefan Vigerske
20  * @author Benjamin Müller
21  *
22  * @todo warm starts
23  * @todo use new_x: Ipopt sets new_x = false if any function has been evaluated for the current x already, while oracle allows new_x to be false only if the current function has been evaluated for the current x before
24  *
25  * This file can only be compiled if Ipopt is available.
26  * Otherwise, to resolve public functions, use nlpi_ipopt_dummy.c.
27  * Since the dummy code is C instead of C++, it has been moved into a separate file.
28  */
29 
30 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
31 
32 #include "nlpi/nlpi_ipopt.h"
33 
34 #include "nlpi/nlpi.h"
35 #include "nlpi/nlpioracle.h"
36 #include "nlpi/exprinterpret.h"
37 #include "scip/interrupt.h"
38 #include "scip/pub_misc.h"
39 
40 #include <new> /* for std::bad_alloc */
41 #include <sstream>
42 
43 #ifdef __GNUC__
44 #pragma GCC diagnostic ignored "-Wshadow"
45 #endif
46 #include "IpoptConfig.h"
47 #include "IpIpoptApplication.hpp"
48 #include "IpIpoptCalculatedQuantities.hpp"
49 #include "IpSolveStatistics.hpp"
50 #include "IpJournalist.hpp"
51 #include "IpIpoptData.hpp"
52 #include "IpTNLPAdapter.hpp"
53 #include "IpOrigIpoptNLP.hpp"
54 #include "IpLapack.hpp"
55 #ifdef __GNUC__
56 #pragma GCC diagnostic warning "-Wshadow"
57 #endif
58 
59 using namespace Ipopt;
60 
61 #define NLPI_NAME "ipopt" /**< short concise name of solver */
62 #define NLPI_DESC "Ipopt interface" /**< description of solver */
63 #define NLPI_PRIORITY 0 /**< priority */
64 
65 #ifdef SCIP_DEBUG
66 #define DEFAULT_PRINTLEVEL J_WARNING /**< default print level of Ipopt */
67 #else
68 #define DEFAULT_PRINTLEVEL J_STRONGWARNING /**< default print level of Ipopt */
69 #endif
70 #define DEFAULT_MAXITER 3000 /**< default iteration limit for Ipopt */
71 
72 #define MAXPERTURB 0.01 /**< maximal perturbation of bounds in starting point heuristic */
73 #define FEASTOLFACTOR 0.05 /**< factor for user-given feasibility tolerance to get feasibility tolerance that is actually passed to Ipopt */
74 
75 #define DEFAULT_RANDSEED 71 /**< initial random seed */
76 
77 /* Convergence check (see ScipNLP::intermediate_callback)
78  *
79  * If the fastfail option is enabled, then we stop Ipopt if the reduction in
80  * primal infeasibility is not sufficient for a consecutive number of iterations.
81  * With the parameters as given below, we require Ipopt to
82  * - not increase the primal infeasibility after 5 iterations
83  * - reduce the primal infeasibility by at least 50% within 10 iterations
84  * - reduce the primal infeasibility by at least 90% within 30 iterations
85  * The targets are updated once they are reached and the limit on allowed iterations to reach the new target is reset.
86  *
87  * In certain situations, it is allowed to exceed an iteration limit:
88  * - If we are in the first 10 (convcheck_startiter) iterations.
89  * - If we are within 10 (convcheck_startiter) iterations after the restoration phase ended.
90  * The reason for this is that during feasibility restoration phase Ipopt aims completely on
91  * reducing constraint violation, completely forgetting the objective function.
92  * When returning from feasibility restoration and considering the original objective again,
93  * it is unlikely that Ipopt will continue to decrease primal infeasibility, since it may now target on
94  * more on optimality again. Thus, we do not check convergence for a number of iterations.
95  * - If the target on dual infeasibility reduction has been achieved, we are below twice the iteration limit, and
96  * we are not in restoration mode.
97  * The reason for this is that if Ipopt makes good progress towards optimality,
98  * we want to allow some more iterations where primal infeasibility is not reduced.
99  * However, in restoration mode, dual infeasibility does not correspond to the original problem and
100  * the complete aim is to restore primal infeasibility.
101  */
102 static const int convcheck_nchecks = 3; /**< number of convergence checks */
103 static const int convcheck_startiter = 10; /**< iteration where to start convergence checking */
104 static const int convcheck_maxiter[convcheck_nchecks] = { 5, 15, 30 }; /**< maximal number of iterations to achieve each convergence check */
105 static const SCIP_Real convcheck_minred[convcheck_nchecks] = { 1.0, 0.5, 0.1 }; /**< minimal required infeasibility reduction in each convergence check */
106 
107 class ScipNLP;
108 
109 struct SCIP_NlpiData
110 {
111 public:
112  BMS_BLKMEM* blkmem; /**< block memory */
113  SCIP_MESSAGEHDLR* messagehdlr; /**< message handler */
114  SCIP_Real infinity; /**< initial value for infinity */
115  std::string defoptions; /**< modified default options for Ipopt */
116 
117  /** constructor */
118  explicit SCIP_NlpiData(
119  BMS_BLKMEM* blkmem_ /**< block memory */
120  )
121  : blkmem(blkmem_),
122  messagehdlr(NULL),
124  { }
125 };
126 
128 {
129 public:
130  SCIP_NLPIORACLE* oracle; /**< Oracle-helper to store and evaluate NLP */
131 
132  SmartPtr<IpoptApplication> ipopt; /**< Ipopt application */
133  SmartPtr<ScipNLP> nlp; /**< NLP in Ipopt form */
134  std::string optfile; /**< name of options file */
135  bool storeintermediate;/**< whether to store intermediate solutions */
136  bool fastfail; /**< whether to stop Ipopt if convergence seems slow */
137 
138  SCIP_Bool firstrun; /**< whether the next NLP solve will be the first one (with the current problem structure) */
139  SCIP_Real* initguess; /**< initial values for primal variables, or NULL if not known */
140 
141  SCIP_NLPSOLSTAT lastsolstat; /**< solution status from last run */
142  SCIP_NLPTERMSTAT lasttermstat; /**< termination status from last run */
143  SCIP_Real* lastsolprimals; /**< primal solution values from last run, if available */
144  SCIP_Real* lastsoldualcons; /**< dual solution values of constraints from last run, if available */
145  SCIP_Real* lastsoldualvarlb; /**< dual solution values of variable lower bounds from last run, if available */
146  SCIP_Real* lastsoldualvarub; /**< dual solution values of variable upper bounds from last run, if available */
147  SCIP_Real lastsolinfeas;/**< infeasibility (constraint violation) of solution stored in lastsolprimals */
148  int lastniter; /**< number of iterations in last run */
149  SCIP_Real lasttime; /**< time spend in last run */
150 
151  /** constructor */
153  : oracle(NULL),
154  storeintermediate(false), fastfail(false),
155  firstrun(TRUE), initguess(NULL),
156  lastsolstat(SCIP_NLPSOLSTAT_UNKNOWN), lasttermstat(SCIP_NLPTERMSTAT_OTHER),
157  lastsolprimals(NULL), lastsoldualcons(NULL), lastsoldualvarlb(NULL), lastsoldualvarub(NULL),
158  lastniter(-1), lasttime(-1.0)
159  { }
160 };
161 
162 /** TNLP implementation for SCIPs NLP */
163 class ScipNLP : public TNLP
164 {
165 private:
166  SCIP_NLPIPROBLEM* nlpiproblem; /**< NLPI problem data */
167  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
168 
169  SCIP_Real conv_prtarget[convcheck_nchecks]; /**< target primal infeasibility for each convergence check */
170  SCIP_Real conv_dutarget[convcheck_nchecks]; /**< target dual infeasibility for each convergence check */
171  int conv_iterlim[convcheck_nchecks]; /**< iteration number where target primal infeasibility should to be achieved */
172  int conv_lastrestoiter; /**< last iteration number in restoration mode, or -1 if none */
173 
174 public:
175  bool approxhessian; /**< do we tell Ipopt to approximate the hessian? (may also be false if user set to approx. hessian via option file) */
176 
177  // cppcheck-suppress uninitMemberVar
178  /** constructor */
179  ScipNLP(
180  SCIP_NLPIPROBLEM* nlpiproblem_ = NULL,/**< NLPI problem data */
181  BMS_BLKMEM* blkmem = NULL /**< block memory */
182  )
183  : nlpiproblem(nlpiproblem_), randnumgen(NULL), approxhessian(false)
184  {
185  assert(blkmem != NULL);
187  }
188 
189  /** destructor */
190  ~ScipNLP()
191  {
192  assert(randnumgen != NULL);
193  SCIPrandomFree(&randnumgen);
194  }
195 
196  /** sets NLPI data structure */
197  void setNLPIPROBLEM(SCIP_NLPIPROBLEM* nlpiproblem_)
198  {
199  assert(nlpiproblem_ != NULL);
200  nlpiproblem = nlpiproblem_;
201  }
202 
203  /** Method to return some info about the nlp */
204  bool get_nlp_info(
205  Index& n, /**< place to store number of variables */
206  Index& m, /**< place to store number of constraints */
207  Index& nnz_jac_g, /**< place to store number of nonzeros in jacobian */
208  Index& nnz_h_lag, /**< place to store number of nonzeros in hessian */
209  IndexStyleEnum& index_style /**< place to store used index style (0-based or 1-based) */
210  );
211 
212  /** Method to return the bounds for my problem */
213  bool get_bounds_info(
214  Index n, /**< number of variables */
215  Number* x_l, /**< buffer to store lower bounds on variables */
216  Number* x_u, /**< buffer to store upper bounds on variables */
217  Index m, /**< number of constraints */
218  Number* g_l, /**< buffer to store lower bounds on constraints */
219  Number* g_u /**< buffer to store lower bounds on constraints */
220  );
221 
222  /** Method to return the starting point for the algorithm */
223  bool get_starting_point(
224  Index n, /**< number of variables */
225  bool init_x, /**< whether initial values for primal values are requested */
226  Number* x, /**< buffer to store initial primal values */
227  bool init_z, /**< whether initial values for dual values of variable bounds are requested */
228  Number* z_L, /**< buffer to store dual values for variable lower bounds */
229  Number* z_U, /**< buffer to store dual values for variable upper bounds */
230  Index m, /**< number of constraints */
231  bool init_lambda, /**< whether initial values for dual values of constraints are required */
232  Number* lambda /**< buffer to store dual values of constraints */
233  );
234 
235  /** Method to return the variables linearity. */
236  bool get_variables_linearity(
237  Index n, /**< number of variables */
238  LinearityType* var_types /**< buffer to store linearity types of variables */
239  );
240 
241  /** Method to return the constraint linearity. */
242  bool get_constraints_linearity(
243  Index m, /**< number of constraints */
244  LinearityType* const_types /**< buffer to store linearity types of constraints */
245  );
246 
247  /** Method to return the number of nonlinear variables. */
248  Index get_number_of_nonlinear_variables();
249 
250  /** Method to return the indices of the nonlinear variables */
251  bool get_list_of_nonlinear_variables(
252  Index num_nonlin_vars, /**< number of nonlinear variables */
253  Index* pos_nonlin_vars /**< array to fill with indices of nonlinear variables */
254  );
255 
256  /** Method to return metadata about variables and constraints */
257  bool get_var_con_metadata(
258  Index n, /**< number of variables */
259  StringMetaDataMapType& var_string_md, /**< variable meta data of string type */
260  IntegerMetaDataMapType& var_integer_md,/**< variable meta data of integer type */
261  NumericMetaDataMapType& var_numeric_md,/**< variable meta data of numeric type */
262  Index m, /**< number of constraints */
263  StringMetaDataMapType& con_string_md, /**< constraint meta data of string type */
264  IntegerMetaDataMapType& con_integer_md,/**< constraint meta data of integer type */
265  NumericMetaDataMapType& con_numeric_md /**< constraint meta data of numeric type */
266  );
267 
268  /** Method to return the objective value */
269  bool eval_f(
270  Index n, /**< number of variables */
271  const Number* x, /**< point to evaluate */
272  bool new_x, /**< whether some function evaluation method has been called for this point before */
273  Number& obj_value /**< place to store objective function value */
274  );
275 
276  /** Method to return the gradient of the objective */
277  bool eval_grad_f(
278  Index n, /**< number of variables */
279  const Number* x, /**< point to evaluate */
280  bool new_x, /**< whether some function evaluation method has been called for this point before */
281  Number* grad_f /**< buffer to store objective gradient */
282  );
283 
284  /** Method to return the constraint residuals */
285  bool eval_g(
286  Index n, /**< number of variables */
287  const Number* x, /**< point to evaluate */
288  bool new_x, /**< whether some function evaluation method has been called for this point before */
289  Index m, /**< number of constraints */
290  Number* g /**< buffer to store constraint function values */
291  );
292 
293  /** Method to return:
294  * 1) The structure of the jacobian (if "values" is NULL)
295  * 2) The values of the jacobian (if "values" is not NULL)
296  */
297  bool eval_jac_g(
298  Index n, /**< number of variables */
299  const Number* x, /**< point to evaluate */
300  bool new_x, /**< whether some function evaluation method has been called for this point before */
301  Index m, /**< number of constraints */
302  Index nele_jac, /**< number of nonzero entries in jacobian */
303  Index* iRow, /**< buffer to store row indices of nonzero jacobian entries, or NULL if values
304  * are requested */
305  Index* jCol, /**< buffer to store column indices of nonzero jacobian entries, or NULL if values
306  * are requested */
307  Number* values /**< buffer to store values of nonzero jacobian entries, or NULL if structure is
308  * requested */
309  );
310 
311  /** Method to return:
312  * 1) The structure of the hessian of the lagrangian (if "values" is NULL)
313  * 2) The values of the hessian of the lagrangian (if "values" is not NULL)
314  */
315  bool eval_h(
316  Index n, /**< number of variables */
317  const Number* x, /**< point to evaluate */
318  bool new_x, /**< whether some function evaluation method has been called for this point before */
319  Number obj_factor, /**< weight for objective function */
320  Index m, /**< number of constraints */
321  const Number* lambda, /**< weights for constraint functions */
322  bool new_lambda, /**< whether the hessian has been evaluated for these values of lambda before */
323  Index nele_hess, /**< number of nonzero entries in hessian */
324  Index* iRow, /**< buffer to store row indices of nonzero hessian entries, or NULL if values
325  * are requested */
326  Index* jCol, /**< buffer to store column indices of nonzero hessian entries, or NULL if values
327  * are requested */
328  Number* values /**< buffer to store values of nonzero hessian entries, or NULL if structure is requested */
329  );
330 
331  /** Method called by the solver at each iteration.
332  *
333  * Checks whether Ctrl-C was hit.
334  */
335  bool intermediate_callback(
336  AlgorithmMode mode, /**< current mode of algorithm */
337  Index iter, /**< current iteration number */
338  Number obj_value, /**< current objective value */
339  Number inf_pr, /**< current primal infeasibility */
340  Number inf_du, /**< current dual infeasibility */
341  Number mu, /**< current barrier parameter */
342  Number d_norm, /**< current gradient norm */
343  Number regularization_size,/**< current size of regularization */
344  Number alpha_du, /**< current dual alpha */
345  Number alpha_pr, /**< current primal alpha */
346  Index ls_trials, /**< current number of linesearch trials */
347  const IpoptData* ip_data, /**< pointer to Ipopt Data */
348  IpoptCalculatedQuantities* ip_cq /**< pointer to current calculated quantities */
349  );
350 
351  /** This method is called when the algorithm is complete so the TNLP can store/write the solution. */
352  void finalize_solution(
353  SolverReturn status, /**< solve and solution status */
354  Index n, /**< number of variables */
355  const Number* x, /**< primal solution values */
356  const Number* z_L, /**< dual values of variable lower bounds */
357  const Number* z_U, /**< dual values of variable upper bounds */
358  Index m, /**< number of constraints */
359  const Number* g, /**< values of constraints */
360  const Number* lambda, /**< dual values of constraints */
361  Number obj_value, /**< objective function value */
362  const IpoptData* data, /**< pointer to Ipopt Data */
363  IpoptCalculatedQuantities* cq /**< pointer to calculated quantities */
364  );
365 };
366 
367 /** A particular Ipopt::Journal implementation that uses the SCIP message routines for output. */
368 class ScipJournal : public Ipopt::Journal {
369 private:
370  /** reference to message handler pointer in NLPI data */
371  SCIP_MESSAGEHDLR*& messagehdlr;
372 
373 public:
374  ScipJournal(
375  const char* name, /**< name of journal */
376  Ipopt::EJournalLevel default_level, /**< default verbosity level */
377  SCIP_MESSAGEHDLR*& messagehdlr_ /**< pointer where to get message handler from */
378  )
379  : Ipopt::Journal(name, default_level),
380  messagehdlr(messagehdlr_)
381  { }
382 
383  ~ScipJournal() { }
384 
385 protected:
386  void PrintImpl(
387  Ipopt::EJournalCategory category, /**< category of message */
388  Ipopt::EJournalLevel level, /**< verbosity level of message */
389  const char* str /**< message to print */
390  )
391  {
392  if( level == J_ERROR )
393  {
395  }
396  else
397  {
398  SCIPmessagePrintInfo(messagehdlr, str);
399  }
400  }
401 
402  void PrintfImpl(
403  Ipopt::EJournalCategory category, /**< category of message */
404  Ipopt::EJournalLevel level, /**< verbosity level of message */
405  const char* pformat, /**< message printing format */
406  va_list ap /**< arguments of message */
407  )
408  {
409  if( level == J_ERROR )
410  {
411  SCIPmessageVPrintError(pformat, ap);
412  }
413  else
414  {
415  SCIPmessageVPrintInfo(messagehdlr, pformat, ap);
416  }
417  }
418 
419  void FlushBufferImpl() { }
420 };
421 
422 /** clears the last solution arrays and sets the solstat and termstat to unknown and other, resp. */
423 static
425  SCIP_NLPIPROBLEM* problem /**< data structure of problem */
426  )
427 {
428  assert(problem != NULL);
429 
436  problem->lastsolinfeas = SCIP_INVALID;
437 }
438 
439 /** sets feasibility tolerance parameters in Ipopt
440  *
441  * Sets tol and constr_viol_tol to FEASTOLFACTOR*feastol and acceptable_tol and acceptable_viol_tol to feastol.
442  * Since the users and Ipopts conception of feasibility may differ, we let Ipopt try to compute solutions
443  * that are more accurate (w.r.t. constraint violation) than requested by the user.
444  * Only if Ipopt has problems to achieve this accuracy, we also accept solutions that are accurate w.r.t. feastol only.
445  * The additional effort for computing a more accurate solution should be small if one can assume fast convergence when close to a local minimizer.
446  */
447 static
449  SCIP_NLPIPROBLEM* nlpiproblem,
450  SCIP_Real feastol
451  )
452 {
453  nlpiproblem->ipopt->Options()->SetNumericValue("tol", FEASTOLFACTOR * feastol);
454  nlpiproblem->ipopt->Options()->SetNumericValue("constr_viol_tol", FEASTOLFACTOR * feastol);
455 
456  nlpiproblem->ipopt->Options()->SetNumericValue("acceptable_tol", feastol);
457  nlpiproblem->ipopt->Options()->SetNumericValue("acceptable_constr_viol_tol", feastol);
458 
459  /* It seem to be better to let Ipopt relax bounds a bit to ensure that a relative interior exists.
460  * However, if we relax the bounds too much, then the solutions tend to be slightly infeasible.
461  * If the user wants to set a tight feasibility tolerance, then (s)he has probably difficulties to compute accurate enough solutions.
462  * Thus, we turn off the bound_relax_factor completely if it would be below its default value of 1e-8.
463  */
464  nlpiproblem->ipopt->Options()->SetNumericValue("bound_relax_factor", feastol < 1e-8/FEASTOLFACTOR ? 0.0 : FEASTOLFACTOR * feastol);
465 }
466 
467 /** copy method of NLP interface (called when SCIP copies plugins)
468  *
469  * input:
470  * - blkmem block memory of target SCIP
471  * - sourcenlpi the NLP interface to copy
472  * - targetnlpi buffer to store pointer to copy of NLP interface
473  */
474 static
475 SCIP_DECL_NLPICOPY(nlpiCopyIpopt)
476 {
477  SCIP_NLPIDATA* sourcedata;
478  SCIP_NLPIDATA* targetdata;
479 
480  assert(sourcenlpi != NULL);
481  assert(targetnlpi != NULL);
482 
483  sourcedata = SCIPnlpiGetData(sourcenlpi);
484  assert(sourcedata != NULL);
485 
486  SCIP_CALL( SCIPcreateNlpSolverIpopt(blkmem, targetnlpi) );
487  assert(*targetnlpi != NULL);
488 
489  SCIP_CALL( SCIPnlpiSetRealPar(*targetnlpi, NULL, SCIP_NLPPAR_INFINITY, sourcedata->infinity) );
490  SCIP_CALL( SCIPnlpiSetMessageHdlr(*targetnlpi, sourcedata->messagehdlr) );
491 
492  targetdata = SCIPnlpiGetData(*targetnlpi);
493  assert(targetdata != NULL);
494 
495  targetdata->defoptions = sourcedata->defoptions;
496 
497  return SCIP_OKAY;
498 }
499 
500 /** destructor of NLP interface to free nlpi data
501  *
502  * input:
503  * - nlpi datastructure for solver interface
504  */
505 static
506 SCIP_DECL_NLPIFREE(nlpiFreeIpopt)
507 {
508  SCIP_NLPIDATA* data;
509 
510  assert(nlpi != NULL);
511 
512  data = SCIPnlpiGetData(nlpi);
513  assert(data != NULL);
514 
515  delete data;
516 
517  return SCIP_OKAY;
518 }
519 
520 /** gets pointer for NLP solver to do dirty stuff
521  *
522  * input:
523  * - nlpi datastructure for solver interface
524  *
525  * return: void pointer to solver
526  */
527 static
528 SCIP_DECL_NLPIGETSOLVERPOINTER(nlpiGetSolverPointerIpopt)
529 {
530  assert(nlpi != NULL);
531 
532  return NULL;
533 }
534 
535 /** creates a problem instance
536  *
537  * input:
538  * - nlpi datastructure for solver interface
539  * - problem pointer to store the problem data
540  * - name name of problem, can be NULL
541  */
542 static
543 SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemIpopt)
544 {
545  SCIP_NLPIDATA* data;
546 
547  assert(nlpi != NULL);
548  assert(problem != NULL);
549 
550  data = SCIPnlpiGetData(nlpi);
551  assert(data != NULL);
552 
553  *problem = new SCIP_NLPIPROBLEM;
554  if( *problem == NULL )
555  return SCIP_NOMEMORY;
556 
557  SCIP_CALL( SCIPnlpiOracleCreate(data->blkmem, &(*problem)->oracle) );
558  SCIP_CALL( SCIPnlpiOracleSetInfinity((*problem)->oracle, data->infinity) );
559  SCIP_CALL( SCIPnlpiOracleSetProblemName((*problem)->oracle, name) );
560 
561  try
562  {
563  /* initialize IPOPT without default journal */
564  (*problem)->ipopt = new IpoptApplication(false);
565  if( IsNull((*problem)->ipopt) )
566  throw std::bad_alloc();
567 
568  /* plugin our journal to get output through SCIP message handler */
569  SmartPtr<Journal> jrnl = new ScipJournal("console", J_ITERSUMMARY, data->messagehdlr);
570  if( IsNull(jrnl) )
571  throw std::bad_alloc();
572  jrnl->SetPrintLevel(J_DBG, J_NONE);
573  if( !(*problem)->ipopt->Jnlst()->AddJournal(jrnl) )
574  {
575  SCIPerrorMessage("Failed to register ScipJournal for IPOPT output.");
576  }
577 
578  /* initialize Ipopt/SCIP NLP interface */
579  (*problem)->nlp = new ScipNLP(*problem, data->blkmem);
580  if( IsNull((*problem)->nlp) )
581  throw std::bad_alloc();
582  }
583  catch( std::bad_alloc )
584  {
585  SCIPerrorMessage("Not enough memory to initialize Ipopt.\n");
586  return SCIP_NOMEMORY;
587  }
588 
589  /* modify Ipopt's default settings to what we believe is appropriate */
590  (*problem)->ipopt->RegOptions()->AddStringOption2("store_intermediate", "whether to store the most feasible intermediate solutions", "no", "yes", "", "no", "", "useful when Ipopt looses a once found feasible solution and then terminates with an infeasible point");
591  (*problem)->ipopt->Options()->SetIntegerValue("print_level", DEFAULT_PRINTLEVEL);
592  /* (*problem)->ipopt->Options()->SetStringValue("print_timing_statistics", "yes"); */
593  (*problem)->ipopt->Options()->SetStringValue("mu_strategy", "adaptive");
594  (*problem)->ipopt->Options()->SetStringValue("expect_infeasible_problem", "yes");
595  (*problem)->ipopt->Options()->SetIntegerValue("max_iter", DEFAULT_MAXITER);
596  (*problem)->ipopt->Options()->SetNumericValue("nlp_lower_bound_inf", -data->infinity, false);
597  (*problem)->ipopt->Options()->SetNumericValue("nlp_upper_bound_inf", data->infinity, false);
598  (*problem)->ipopt->Options()->SetNumericValue("diverging_iterates_tol", data->infinity, false);
599  /* (*problem)->ipopt->Options()->SetStringValue("dependency_detector", "ma28"); */
600  /* if the expression interpreter does not give hessians, tell Ipopt to approximate hessian */
601 #ifdef SCIP_DEBUG
602  (*problem)->ipopt->Options()->SetStringValue("derivative_test", "second-order");
603 #endif
604  setFeastol(*problem, SCIP_DEFAULT_FEASTOL);
605 
606  /* apply user's given modifications to Ipopt's default settings */
607  if( data->defoptions.length() > 0 )
608  {
609  std::istringstream is(data->defoptions);
610 
611 #if (IPOPT_VERSION_MAJOR > 3) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR > 12) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR == 12 && IPOPT_VERSION_RELEASE >= 5)
612  if( !(*problem)->ipopt->Options()->ReadFromStream(*(*problem)->ipopt->Jnlst(), is, true) )
613 #else
614  if( !(*problem)->ipopt->Options()->ReadFromStream(*(*problem)->ipopt->Jnlst(), is) )
615 #endif
616  {
617  SCIPerrorMessage("Error when modifiying Ipopt options using options string\n%s\n", data->defoptions.c_str());
618  return SCIP_ERROR;
619  }
620  }
621 
622  /* apply user's given options file (this one is NLPI problem specific) */
623  if( (*problem)->ipopt->Initialize((*problem)->optfile) != Solve_Succeeded )
624  {
625  SCIPerrorMessage("Error during initialization of Ipopt using optionfile \"%s\"\n", (*problem)->optfile.c_str());
626  return SCIP_ERROR;
627  }
628 
629 
630  return SCIP_OKAY;
631 }
632 
633 /** free a problem instance
634  *
635  * input:
636  * - nlpi datastructure for solver interface
637  * - problem pointer where problem data is stored
638  */
639 static
640 SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemIpopt)
641 {
642  assert(nlpi != NULL);
643  assert(problem != NULL);
644  assert(*problem != NULL);
645 
646  if( (*problem)->oracle != NULL )
647  {
648  SCIP_CALL( SCIPnlpiOracleFree(&(*problem)->oracle) );
649  }
650 
651  BMSfreeMemoryArrayNull(&(*problem)->initguess);
652  BMSfreeMemoryArrayNull(&(*problem)->lastsolprimals);
653  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualcons);
654  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualvarlb);
655  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualvarub);
656 
657  delete *problem;
658  *problem = NULL;
659 
660  return SCIP_OKAY;
661 }
662 
663 /** gets pointer to solver-internal problem instance to do dirty stuff
664  *
665  * input:
666  * - nlpi datastructure for solver interface
667  * - problem datastructure for problem instance
668  *
669  * return: void pointer to problem instance
670  */
671 SCIP_DECL_NLPIGETPROBLEMPOINTER(nlpiGetProblemPointerIpopt)
672 {
673  assert(nlpi != NULL);
674  assert(problem != NULL);
675 
676  return GetRawPtr(problem->nlp);
677 }
678 
679 /** add variables
680  *
681  * input:
682  * - nlpi datastructure for solver interface
683  * - problem datastructure for problem instance
684  * - nvars number of variables
685  * - lbs lower bounds of variables, can be NULL if -infinity
686  * - ubs upper bounds of variables, can be NULL if +infinity
687  * - varnames names of variables, can be NULL
688  */
689 static
690 SCIP_DECL_NLPIADDVARS(nlpiAddVarsIpopt)
691 {
692  assert(nlpi != NULL);
693  assert(problem != NULL);
694  assert(problem->oracle != NULL);
695 
696  SCIP_CALL( SCIPnlpiOracleAddVars(problem->oracle, nvars, lbs, ubs, varnames) );
697 
698  problem->firstrun = TRUE;
699  BMSfreeMemoryArrayNull(&problem->initguess);
700  invalidateSolution(problem);
701 
702  return SCIP_OKAY;
703 }
704 
705 /** add constraints
706  *
707  * quadratic coefficiens: row oriented matrix for each constraint
708  *
709  * input:
710  * - nlpi datastructure for solver interface
711  * - problem datastructure for problem instance
712  * - ncons number of added constraints
713  * - lhss left hand sides of constraints
714  * - rhss right hand sides of constraints
715  * - linoffsets start index of each constraints linear coefficients in lininds and linvals
716  * length: ncons + 1, linoffsets[ncons] gives length of lininds and linvals
717  * may be NULL in case of no linear part
718  * - lininds variable indices
719  * may be NULL in case of no linear part
720  * - linvals coefficient values
721  * may be NULL in case of no linear part
722  * - nquadelems number of quadratic elements for each constraint
723  * may be NULL in case of no quadratic part
724  * - quadelems quadratic elements for each constraint
725  * may be NULL in case of no quadratic part
726  * - exprvaridxs indices of variables in expression tree, maps variable indices in expression tree to indices in nlp
727  * entry of array may be NULL in case of no expression tree
728  * may be NULL in case of no expression tree in any constraint
729  * - exprtrees expression tree for nonquadratic part of constraints
730  * entry of array may be NULL in case of no nonquadratic part
731  * may be NULL in case of no nonquadratic part in any constraint
732  * - names of constraints, may be NULL or entries may be NULL
733  */
734 static
735 SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsIpopt)
736 {
737  assert(nlpi != NULL);
738  assert(problem != NULL);
739  assert(problem->oracle != NULL);
740 
741  SCIP_CALL( SCIPnlpiOracleAddConstraints(problem->oracle,
742  ncons, lhss, rhss,
743  nlininds, lininds, linvals,
744  nquadelems, quadelems,
745  exprvaridxs, exprtrees, names) );
746 
747  problem->firstrun = TRUE;
748  invalidateSolution(problem);
749 
750  return SCIP_OKAY;
751 }
752 
753 /** sets or overwrites objective, a minimization problem is expected
754  *
755  * May change sparsity pattern.
756  *
757  * input:
758  * - nlpi datastructure for solver interface
759  * - problem datastructure for problem instance
760  * - nlins number of linear variables
761  * - lininds variable indices
762  * may be NULL in case of no linear part
763  * - linvals coefficient values
764  * may be NULL in case of no linear part
765  * - nquadelems number of elements in matrix of quadratic part
766  * - quadelems elements of quadratic part
767  * may be NULL in case of no quadratic part
768  * - exprvaridxs indices of variables in expression tree, maps variable indices in expression tree to indices in nlp
769  * may be NULL in case of no expression tree
770  * - exprtree expression tree for nonquadratic part of objective function
771  * may be NULL in case of no nonquadratic part
772  * - constant objective value offset
773  */
774 static
775 SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveIpopt)
776 {
777  assert(nlpi != NULL);
778  assert(problem != NULL);
779  assert(problem->oracle != NULL);
780 
781  SCIP_CALL( SCIPnlpiOracleSetObjective(problem->oracle,
782  constant, nlins, lininds, linvals,
783  nquadelems, quadelems,
784  exprvaridxs, exprtree) );
785 
786  problem->firstrun = TRUE;
787  invalidateSolution(problem);
788 
789  return SCIP_OKAY;
790 }
791 
792 /** change variable bounds
793  *
794  * input:
795  * - nlpi datastructure for solver interface
796  * - problem datastructure for problem instance
797  * - nvars number of variables to change bounds
798  * - indices indices of variables to change bounds
799  * - lbs new lower bounds
800  * - ubs new upper bounds
801  */
802 static
803 SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsIpopt)
804 {
805  int i;
806 
807  assert(nlpi != NULL);
808  assert(problem != NULL);
809  assert(problem->oracle != NULL);
810 
811  /* If some variable is fixed or unfixed, then better don't reoptimize the NLP in the next solve.
812  * Calling Optimize instead of ReOptimize should remove fixed variables from the problem that is solved by Ipopt.
813  * This way, the variable fixing is satisfied exactly in a solution, see also #1254.
814  */
815  for( i = 0; i < nvars && !problem->firstrun; ++i )
816  if( (SCIPnlpiOracleGetVarLbs(problem->oracle)[indices[i]] == SCIPnlpiOracleGetVarUbs(problem->oracle)[indices[i]]) != (lbs[i] == ubs[i]) )
817  problem->firstrun = TRUE;
818 
819  SCIP_CALL( SCIPnlpiOracleChgVarBounds(problem->oracle, nvars, indices, lbs, ubs) );
820 
821  invalidateSolution(problem);
822 
823  return SCIP_OKAY;
824 }
825 
826 /** change constraint bounds
827  *
828  * input:
829  * - nlpi datastructure for solver interface
830  * - problem datastructure for problem instance
831  * - nconss number of constraints to change sides
832  * - indices indices of constraints to change sides
833  * - lhss new left hand sides
834  * - rhss new right hand sides
835  */
836 static
837 SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesIpopt)
838 {
839  assert(nlpi != NULL);
840  assert(problem != NULL);
841  assert(problem->oracle != NULL);
842 
843  SCIP_CALL( SCIPnlpiOracleChgConsSides(problem->oracle, nconss, indices, lhss, rhss) );
844 
845  invalidateSolution(problem);
846 
847  return SCIP_OKAY;
848 }
849 
850 /** delete a set of variables
851  *
852  * input:
853  * - nlpi datastructure for solver interface
854  * - problem datastructure for problem instance
855  * - nlpi datastructure for solver interface
856  * - dstats deletion status of vars; 1 if var should be deleted, 0 if not
857  *
858  * output:
859  * - dstats new position of var, -1 if var was deleted
860  */
861 static
862 SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetIpopt)
863 {
864  assert(nlpi != NULL);
865  assert(problem != NULL);
866  assert(problem->oracle != NULL);
867 
868  SCIP_CALL( SCIPnlpiOracleDelVarSet(problem->oracle, dstats) );
869 
870  problem->firstrun = TRUE;
871  BMSfreeMemoryArrayNull(&problem->initguess); // @TODO keep initguess for remaining variables
872 
873  invalidateSolution(problem);
874 
875  return SCIP_OKAY;
876 }
877 
878 /** delete a set of constraints
879  *
880  * input:
881  * - nlpi datastructure for solver interface
882  * - problem datastructure for problem instance
883  * - dstats deletion status of rows; 1 if row should be deleted, 0 if not
884  *
885  * output:
886  * - dstats new position of row, -1 if row was deleted
887  */
888 static
889 SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetIpopt)
890 {
891  assert(nlpi != NULL);
892  assert(problem != NULL);
893  assert(problem->oracle != NULL);
894 
895  SCIP_CALL( SCIPnlpiOracleDelConsSet(problem->oracle, dstats) );
896 
897  problem->firstrun = TRUE;
898 
899  invalidateSolution(problem);
900 
901  return SCIP_OKAY;
902 }
903 
904 /** change one linear coefficient in a constraint or objective
905  *
906  * input:
907  * - nlpi datastructure for solver interface
908  * - problem datastructure for problem instance
909  * - idx index of constraint or -1 for objective
910  * - nvals number of values in linear constraint
911  * - varidxs indices of variable
912  * - vals new values for coefficient
913  *
914  * return: Error if coefficient did not exist before
915  */
916 static
917 SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsIpopt)
918 {
919  assert(nlpi != NULL);
920  assert(problem != NULL);
921  assert(problem->oracle != NULL);
922 
923  SCIP_CALL( SCIPnlpiOracleChgLinearCoefs(problem->oracle, idx, nvals, varidxs, vals) );
924  invalidateSolution(problem);
925 
926  return SCIP_OKAY;
927 }
928 
929 /** change one coefficient in the quadratic part of a constraint or objective
930  *
931  * input:
932  * - nlpi datastructure for solver interface
933  * - problem datastructure for problem instance
934  * - idx index of constraint or -1 for objective
935  * - nquadelems number of entries in quadratic matrix to change
936  * - quadelems new elements in quadratic matrix (replacing already existing ones or adding new ones)
937  *
938  * return: Error if coefficient did not exist before
939  */
940 static
941 SCIP_DECL_NLPICHGQUADCOEFS(nlpiChgQuadraticCoefsIpopt)
942 {
943  assert(nlpi != NULL);
944  assert(problem != NULL);
945  assert(problem->oracle != NULL);
946 
947  SCIP_CALL( SCIPnlpiOracleChgQuadCoefs(problem->oracle, idx, nquadelems, quadelems) );
948  invalidateSolution(problem);
949 
950  return SCIP_OKAY;
951 }
952 
953 /** replaces the expression tree of a constraint or objective
954  *
955  * input:
956  * - nlpi datastructure for solver interface
957  * - problem datastructure for problem instance
958  * - idxcons index of constraint or -1 for objective
959  * - exprtree new expression tree for constraint or objective, or NULL to only remove previous tree
960  */
961 static
962 SCIP_DECL_NLPICHGEXPRTREE(nlpiChgExprtreeIpopt)
963 {
964  assert(nlpi != NULL);
965  assert(problem != NULL);
966  assert(problem->oracle != NULL);
967 
968  SCIP_CALL( SCIPnlpiOracleChgExprtree(problem->oracle, idxcons, exprvaridxs, exprtree) );
969  invalidateSolution(problem);
970 
971  return SCIP_OKAY;
972 }
973 
974 /** change the value of one parameter in the nonlinear part
975  *
976  * input:
977  * - nlpi datastructure for solver interface
978  * - problem datastructure for problem instance
979  * - idxcons index of constraint or -1 for objective
980  * - idxparam index of parameter
981  * - value new value for nonlinear parameter
982  *
983  * return: Error if parameter does not exist
984  */
985 static
986 SCIP_DECL_NLPICHGNONLINCOEF(nlpiChgNonlinCoefIpopt)
987 {
988  assert(nlpi != NULL);
989  assert(problem != NULL);
990  assert(problem->oracle != NULL);
991 
992  SCIP_CALL( SCIPnlpiOracleChgExprParam(problem->oracle, idxcons, idxparam, value) );
993  invalidateSolution(problem);
994 
995  return SCIP_OKAY;
996 }
997 
998 /** change the constant offset in the objective
999  *
1000  * input:
1001  * - nlpi datastructure for solver interface
1002  * - problem datastructure for problem instance
1003  * - objconstant new value for objective constant
1004  */
1005 static
1006 SCIP_DECL_NLPICHGOBJCONSTANT( nlpiChgObjConstantIpopt )
1007 {
1008  assert(nlpi != NULL);
1009  assert(problem != NULL);
1010  assert(problem->oracle != NULL);
1011 
1012  SCIP_CALL( SCIPnlpiOracleChgObjConstant(problem->oracle, objconstant) );
1013 
1014  return SCIP_OKAY;
1015 }
1016 
1017 /** sets initial guess for primal variables
1018  *
1019  * input:
1020  * - nlpi datastructure for solver interface
1021  * - problem datastructure for problem instance
1022  * - primalvalues initial primal values for variables, or NULL to clear previous values
1023  * - consdualvalues initial dual values for constraints, or NULL to clear previous values
1024  * - varlbdualvalues initial dual values for variable lower bounds, or NULL to clear previous values
1025  * - varubdualvalues initial dual values for variable upper bounds, or NULL to clear previous values
1026  */
1027 static
1028 SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessIpopt)
1029 {
1030  assert(nlpi != NULL);
1031  assert(problem != NULL);
1032  assert(problem->oracle != NULL);
1033 
1034  if( primalvalues != NULL )
1035  {
1036  if( !problem->initguess )
1037  {
1038  if( BMSduplicateMemoryArray(&problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle)) == NULL )
1039  return SCIP_NOMEMORY;
1040  }
1041  else
1042  {
1043  BMScopyMemoryArray(problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle));
1044  }
1045  }
1046  else
1047  {
1048  BMSfreeMemoryArrayNull(&problem->initguess);
1049  }
1050 
1051  return SCIP_OKAY;
1052 }
1053 
1054 /** tries to solve NLP
1055  *
1056  * input:
1057  * - nlpi datastructure for solver interface
1058  * - problem datastructure for problem instance
1059  */
1060 static
1061 SCIP_DECL_NLPISOLVE(nlpiSolveIpopt)
1062 {
1063  ApplicationReturnStatus status;
1064 
1065  assert(nlpi != NULL);
1066  assert(problem != NULL);
1067  assert(problem->oracle != NULL);
1068 
1069  assert(IsValid(problem->ipopt));
1070  assert(IsValid(problem->nlp));
1071 
1072  problem->nlp->setNLPIPROBLEM(problem);
1073 
1074  problem->lastniter = -1;
1075  problem->lasttime = -1.0;
1076  problem->lastsolinfeas = SCIP_INVALID;
1077 
1078  try
1079  {
1080  SmartPtr<SolveStatistics> stats;
1081 
1082  if( problem->firstrun )
1083  {
1085 
1086  cap = SCIPexprintGetCapability() & SCIPnlpiOracleGetEvalCapability(problem->oracle);
1087 
1088  /* if the expression interpreter or some user expression do not support function values and gradients and Hessians, and the problem is not at most quadratic,
1089  * change NLP parameters or give an error
1090  */
1092  && SCIPnlpiOracleGetMaxDegree(problem->oracle) > 2 )
1093  {
1094  /* @todo could enable Jacobian approximation in Ipopt */
1097  {
1098  SCIPerrorMessage("Do not have expression interpreter that can compute function values and gradients. Cannot solve NLP with Ipopt.\n");
1099  problem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
1100  problem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
1101  return SCIP_OKAY;
1102  }
1103 
1104  /* enable Hessian approximation if we are nonquadratic and the expression interpreter or user expression do not support Hessians */
1105  if( !(cap & SCIP_EXPRINTCAPABILITY_HESSIAN) )
1106  {
1107  problem->ipopt->Options()->SetStringValue("hessian_approximation", "limited-memory");
1108  problem->nlp->approxhessian = true;
1109  }
1110  else
1111  problem->nlp->approxhessian = false;
1112  }
1113 
1114  status = problem->ipopt->OptimizeTNLP(GetRawPtr(problem->nlp));
1115  }
1116  else
1117  {
1118  status = problem->ipopt->ReOptimizeTNLP(GetRawPtr(problem->nlp));
1119  }
1120 
1121  // catch the very bad status codes
1122  switch( status ) {
1123  case Invalid_Problem_Definition:
1124  case Invalid_Option:
1125  case Unrecoverable_Exception:
1126  case NonIpopt_Exception_Thrown:
1127  case Internal_Error:
1128  SCIPerrorMessage("Ipopt returned with application return status %d\n", status);
1129  return SCIP_ERROR;
1130  case Insufficient_Memory:
1131  SCIPerrorMessage("Ipopt returned with status \"Insufficient Memory\"\n");
1132  return SCIP_NOMEMORY;
1133  case Invalid_Number_Detected:
1134  SCIPdebugMessage("Ipopt failed because of an invalid number in function or derivative value\n");
1135  invalidateSolution(problem);
1136  problem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
1137  problem->lasttermstat = SCIP_NLPTERMSTAT_EVALERR;
1138  default: ;
1139  }
1140 
1141  stats = problem->ipopt->Statistics();
1142  if( IsValid(stats) )
1143  {
1144  problem->lastniter = stats->IterationCount();
1145  problem->lasttime = stats->TotalCPUTime();
1146  }
1147  }
1148  catch( IpoptException& except )
1149  {
1150  SCIPerrorMessage("Ipopt returned with exception: %s\n", except.Message().c_str());
1151  return SCIP_ERROR;
1152  }
1153 
1154  problem->firstrun = FALSE;
1155 
1156  return SCIP_OKAY;
1157 }
1158 
1159 /** gives solution status
1160  *
1161  * input:
1162  * - nlpi datastructure for solver interface
1163  * - problem datastructure for problem instance
1164  *
1165  * return: Solution Status
1166  */
1167 static
1168 SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatIpopt)
1169 {
1170  assert(nlpi != NULL);
1171  assert(problem != NULL);
1172 
1173  return problem->lastsolstat;
1174 }
1175 
1176 /** gives termination reason
1177  *
1178  * input:
1179  * - nlpi datastructure for solver interface
1180  * - problem datastructure for problem instance
1181  *
1182  * return: Termination Status
1183  */
1184 static
1185 SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatIpopt)
1186 {
1187  assert(nlpi != NULL);
1188  assert(problem != NULL);
1189 
1190  return problem->lasttermstat;
1191 }
1192 
1193 /** gives primal and dual solution values
1194  *
1195  * input:
1196  * - nlpi datastructure for solver interface
1197  * - problem datastructure for problem instance
1198  * - primalvalues buffer to store pointer to array to primal values, or NULL if not needed
1199  * - consdualvalues buffer to store pointer to array to dual values of constraints, or NULL if not needed
1200  * - varlbdualvalues buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed
1201  * - varubdualvalues buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed
1202  */
1203 static
1204 SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionIpopt)
1205 {
1206  assert(nlpi != NULL);
1207  assert(problem != NULL);
1208 
1209  if( primalvalues != NULL )
1210  *primalvalues = problem->lastsolprimals;
1211 
1212  if( consdualvalues != NULL )
1213  *consdualvalues = problem->lastsoldualcons;
1214 
1215  if( varlbdualvalues != NULL )
1216  *varlbdualvalues = problem->lastsoldualvarlb;
1217 
1218  if( varubdualvalues != NULL )
1219  *varubdualvalues = problem->lastsoldualvarub;
1220 
1221  return SCIP_OKAY;
1222 }
1223 
1224 /** gives solve statistics
1225  *
1226  * input:
1227  * - nlpi datastructure for solver interface
1228  * - problem datastructure for problem instance
1229  * - statistics pointer to store statistics
1230  *
1231  * output:
1232  * - statistics solve statistics
1233  */
1234 static
1235 SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsIpopt)
1236 {
1237  assert(nlpi != NULL);
1238  assert(problem != NULL);
1239 
1240  SCIPnlpStatisticsSetNIterations(statistics, problem->lastniter);
1241  SCIPnlpStatisticsSetTotalTime (statistics, problem->lasttime);
1242 
1243  return SCIP_OKAY;
1244 }
1245 
1246 /** gives required size of a buffer to store a warmstart object
1247  *
1248  * input:
1249  * - nlpi datastructure for solver interface
1250  * - problem datastructure for problem instance
1251  * - size pointer to store required size for warmstart buffer
1252  *
1253  * output:
1254  * - size required size for warmstart buffer
1255  */
1256 static
1257 SCIP_DECL_NLPIGETWARMSTARTSIZE(nlpiGetWarmstartSizeIpopt)
1258 {
1259  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1260  return SCIP_ERROR;
1261 }
1262 
1263 /** stores warmstart information in buffer
1264  *
1265  * Required size of buffer should have been obtained by SCIPnlpiGetWarmstartSize before.
1266  *
1267  * input:
1268  * - nlpi datastructure for solver interface
1269  * - problem datastructure for problem instance
1270  * - buffer memory to store warmstart information
1271  *
1272  * output:
1273  * - buffer warmstart information in solver specific data structure
1274  */
1275 static
1276 SCIP_DECL_NLPIGETWARMSTARTMEMO(nlpiGetWarmstartMemoIpopt)
1277 {
1278  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1279  return SCIP_ERROR;
1280 }
1281 
1282 /** sets warmstart information in solver
1283  *
1284  * Write warmstart to buffer.
1285  *
1286  * input:
1287  * - nlpi datastructure for solver interface
1288  * - problem datastructure for problem instance
1289  * - buffer warmstart information
1290  */
1291 static
1292 SCIP_DECL_NLPISETWARMSTARTMEMO(nlpiSetWarmstartMemoIpopt)
1293 {
1294  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1295  SCIPABORT();
1296  return SCIP_OKAY;
1297 }
1298 
1299 /** gets integer parameter of NLP
1300  *
1301  * input:
1302  * - nlpi datastructure for solver interface
1303  * - problem datastructure for problem instance
1304  * - type parameter number
1305  * - ival pointer to store the parameter value
1306  *
1307  * output:
1308  * - ival parameter value
1309  */
1310 static
1311 SCIP_DECL_NLPIGETINTPAR(nlpiGetIntParIpopt)
1312 {
1313  assert(nlpi != NULL);
1314  assert(ival != NULL);
1315  assert(problem != NULL);
1316  assert(IsValid(problem->ipopt));
1317 
1318  //@TODO try-catch block for Ipopt exceptions
1319  switch( type )
1320  {
1322  {
1323  *ival = 1;
1324  break;
1325  }
1326 
1327  case SCIP_NLPPAR_VERBLEVEL:
1328  {
1329  int printlevel;
1330  problem->ipopt->Options()->GetIntegerValue("print_level", printlevel, "");
1331  if( printlevel <= J_STRONGWARNING )
1332  *ival = 0;
1333  else if( printlevel >= J_DETAILED )
1334  *ival = printlevel - J_ITERSUMMARY + 1;
1335  else /* J_SUMMARY or J_WARNING or J_ITERSUMMARY */
1336  *ival = 1;
1337  break;
1338  }
1339 
1340  case SCIP_NLPPAR_FEASTOL:
1341  {
1342  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1343  return SCIP_PARAMETERWRONGTYPE;
1344  }
1345 
1346  case SCIP_NLPPAR_RELOBJTOL:
1347  {
1348  SCIPerrorMessage("relative objective tolerance parameter is of type real.\n");
1349  return SCIP_PARAMETERWRONGTYPE;
1350  }
1351 
1352  case SCIP_NLPPAR_LOBJLIM:
1353  {
1354  SCIPerrorMessage("objective limit parameter is of type real.\n");
1355  return SCIP_PARAMETERWRONGTYPE;
1356  }
1357 
1358  case SCIP_NLPPAR_INFINITY:
1359  {
1360  SCIPerrorMessage("infinity parameter is of type real.\n");
1361  return SCIP_PARAMETERWRONGTYPE;
1362  }
1363 
1364  case SCIP_NLPPAR_ITLIM:
1365  {
1366  problem->ipopt->Options()->GetIntegerValue("max_iter", *ival, "");
1367  break;
1368  }
1369 
1370  case SCIP_NLPPAR_TILIM:
1371  {
1372  SCIPerrorMessage("time limit parameter is of type real.\n");
1373  return SCIP_PARAMETERWRONGTYPE;
1374  }
1375 
1376  case SCIP_NLPPAR_OPTFILE:
1377  {
1378  SCIPerrorMessage("optfile parameter is of type string.\n");
1379  return SCIP_PARAMETERWRONGTYPE;
1380  }
1381 
1382  case SCIP_NLPPAR_FASTFAIL:
1383  {
1384  *ival = problem->fastfail ? 1 : 0;
1385  break;
1386  }
1387 
1388  default:
1389  {
1390  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1391  return SCIP_PARAMETERUNKNOWN;
1392  }
1393  }
1394 
1395  return SCIP_OKAY;
1396 }
1397 
1398 /** sets integer parameter of NLP
1399  *
1400  * input:
1401  * - nlpi datastructure for solver interface
1402  * - problem datastructure for problem instance
1403  * - type parameter number
1404  * - ival parameter value
1405  */
1406 static
1407 SCIP_DECL_NLPISETINTPAR(nlpiSetIntParIpopt)
1408 {
1409  assert(nlpi != NULL);
1410  assert(problem != NULL);
1411  assert(IsValid(problem->ipopt));
1412 
1413  switch( type )
1414  {
1416  {
1417  if( ival == 0 || ival == 1 )
1418  {
1419  SCIP_NLPIDATA* data;
1420 
1421  data = SCIPnlpiGetData(nlpi);
1422  assert(data != NULL);
1423 
1424  SCIPmessagePrintWarning(data->messagehdlr, "from scratch parameter not supported by Ipopt interface yet. Ignored.\n");
1425  }
1426  else
1427  {
1428  SCIPerrorMessage("Value %d for parameter from scratch out of range {0, 1}\n", ival);
1429  return SCIP_PARAMETERWRONGVAL;
1430  }
1431  break;
1432  }
1433 
1434  case SCIP_NLPPAR_VERBLEVEL:
1435  {
1436  switch( ival )
1437  {
1438  case 0:
1439  problem->ipopt->Options()->SetIntegerValue("print_level", J_STRONGWARNING);
1440  break;
1441  case 1:
1442  problem->ipopt->Options()->SetIntegerValue("print_level", J_ITERSUMMARY);
1443  break;
1444  case 2:
1445  problem->ipopt->Options()->SetIntegerValue("print_level", J_DETAILED);
1446  break;
1447  default:
1448  if( ival > 2 )
1449  {
1450  problem->ipopt->Options()->SetIntegerValue("print_level", MIN(J_ITERSUMMARY + (ival-1), J_ALL));
1451  break;
1452  }
1453  else
1454  {
1455  SCIPerrorMessage("Value %d for parameter from verbosity level out of range {0, 1, 2}\n", ival);
1456  return SCIP_PARAMETERWRONGVAL;
1457  }
1458  }
1459  break;
1460  }
1461 
1462  case SCIP_NLPPAR_FEASTOL:
1463  {
1464  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1465  return SCIP_PARAMETERWRONGTYPE;
1466  }
1467 
1468  case SCIP_NLPPAR_RELOBJTOL:
1469  {
1470  SCIPerrorMessage("relative objective tolerance parameter is of type real.\n");
1471  return SCIP_PARAMETERWRONGTYPE;
1472  }
1473 
1474  case SCIP_NLPPAR_LOBJLIM:
1475  {
1476  SCIPerrorMessage("objective limit parameter is of type real.\n");
1477  return SCIP_PARAMETERWRONGTYPE;
1478  }
1479 
1480  case SCIP_NLPPAR_INFINITY:
1481  {
1482  SCIPerrorMessage("infinity parameter is of type real.\n");
1483  return SCIP_PARAMETERWRONGTYPE;
1484  }
1485 
1486  case SCIP_NLPPAR_ITLIM:
1487  {
1488  if( ival >= 0 )
1489  {
1490  problem->ipopt->Options()->SetIntegerValue("max_iter", ival);
1491  }
1492  else
1493  {
1494  SCIPerrorMessage("Value %d for parameter iteration limit is negative\n", ival);
1495  return SCIP_PARAMETERWRONGVAL;
1496  }
1497  break;
1498  }
1499 
1500  case SCIP_NLPPAR_TILIM:
1501  {
1502  SCIPerrorMessage("time limit parameter is of type real.\n");
1503  return SCIP_PARAMETERWRONGTYPE;
1504  }
1505 
1506  case SCIP_NLPPAR_OPTFILE:
1507  {
1508  SCIPerrorMessage("optfile parameter is of type string.\n");
1509  return SCIP_PARAMETERWRONGTYPE;
1510  }
1511 
1512  case SCIP_NLPPAR_FASTFAIL:
1513  {
1514  if( ival == 0 || ival == 1 )
1515  {
1516  problem->fastfail = (bool)ival;
1517  problem->storeintermediate = (bool)ival;
1518  }
1519  else
1520  {
1521  SCIPerrorMessage("Value %d for parameter fastfail out of range {0, 1}\n", ival);
1522  return SCIP_PARAMETERWRONGVAL;
1523  }
1524  break;
1525  }
1526 
1527  default:
1528  {
1529  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1530  return SCIP_PARAMETERUNKNOWN;
1531  }
1532  }
1533 
1534  return SCIP_OKAY;
1535 }
1536 
1537 /** gets floating point parameter of NLP
1538  *
1539  * input:
1540  * - nlpi datastructure for solver interface
1541  * - problem datastructure for problem instance, can be NULL only if type == SCIP_NLPPAR_INFINITY
1542  * - type parameter number
1543  * - dval pointer to store the parameter value
1544  *
1545  * output:
1546  * - dval parameter value
1547  */
1548 static
1549 SCIP_DECL_NLPIGETREALPAR(nlpiGetRealParIpopt)
1550 {
1551  assert(nlpi != NULL);
1552  assert(dval != NULL);
1553  assert(type == SCIP_NLPPAR_INFINITY || problem != NULL);
1554  assert(type == SCIP_NLPPAR_INFINITY || IsValid(problem->ipopt));
1555 
1556  switch( type )
1557  {
1559  {
1560  SCIPerrorMessage("from scratch parameter is of type int.\n");
1561  return SCIP_PARAMETERWRONGTYPE;
1562  }
1563 
1564  case SCIP_NLPPAR_VERBLEVEL:
1565  {
1566  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1567  return SCIP_PARAMETERWRONGTYPE;
1568  }
1569 
1570  case SCIP_NLPPAR_FEASTOL:
1571  {
1572  problem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", *dval, "");
1573  break;
1574  }
1575 
1576  case SCIP_NLPPAR_RELOBJTOL:
1577  {
1578  problem->ipopt->Options()->GetNumericValue("dual_inf_tol", *dval, "");
1579  break;
1580  }
1581 
1582  case SCIP_NLPPAR_LOBJLIM:
1583  {
1584  *dval = -SCIPnlpiOracleGetInfinity(problem->oracle);
1585  break;
1586  }
1587 
1588  case SCIP_NLPPAR_INFINITY:
1589  {
1590  if( problem )
1591  {
1592  *dval = SCIPnlpiOracleGetInfinity(problem->oracle);
1593  }
1594  else
1595  {
1596  SCIP_NLPIDATA* data = SCIPnlpiGetData(nlpi);
1597  assert(data != NULL);
1598  *dval = data->infinity;
1599  }
1600  break;
1601  }
1602 
1603  case SCIP_NLPPAR_ITLIM:
1604  {
1605  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1606  return SCIP_PARAMETERWRONGTYPE;
1607  }
1608 
1609  case SCIP_NLPPAR_TILIM:
1610  {
1611  problem->ipopt->Options()->GetNumericValue("max_cpu_time", *dval, "");
1612  break;
1613  }
1614 
1615  case SCIP_NLPPAR_OPTFILE:
1616  {
1617  SCIPerrorMessage("option file parameter is of type string.\n");
1618  return SCIP_PARAMETERWRONGTYPE;
1619  }
1620 
1621  case SCIP_NLPPAR_FASTFAIL:
1622  {
1623  SCIPerrorMessage("fastfail parameter is of type int.\n");
1624  return SCIP_PARAMETERWRONGTYPE;
1625  }
1626 
1627  default:
1628  {
1629  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1630  return SCIP_PARAMETERUNKNOWN;
1631  }
1632  }
1633 
1634  return SCIP_OKAY;
1635 }
1636 
1637 /** sets floating point parameter of NLP
1638  *
1639  * input:
1640  * - nlpi datastructure for solver interface
1641  * - problem datastructure for problem instance, can be NULL only if type == SCIP_NLPPAR_INFINITY
1642  * - type parameter number
1643  * - dval parameter value
1644  */
1645 static
1646 SCIP_DECL_NLPISETREALPAR(nlpiSetRealParIpopt)
1647 {
1648  assert(nlpi != NULL);
1649  assert(type == SCIP_NLPPAR_INFINITY || problem != NULL);
1650  assert(type == SCIP_NLPPAR_INFINITY || IsValid(problem->ipopt));
1651 
1652  switch( type )
1653  {
1655  {
1656  SCIPerrorMessage("from scratch parameter is of type int.\n");
1657  return SCIP_PARAMETERWRONGTYPE;
1658  }
1659 
1660  case SCIP_NLPPAR_VERBLEVEL:
1661  {
1662  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1663  return SCIP_PARAMETERWRONGTYPE;
1664  }
1665 
1666  case SCIP_NLPPAR_FEASTOL:
1667  {
1668  if( dval >= 0 )
1669  {
1670  setFeastol(problem, dval);
1671  }
1672  else
1673  {
1674  SCIPerrorMessage("Value %g for parameter feasibility tolerance is negative\n", dval);
1675  return SCIP_PARAMETERWRONGVAL;
1676  }
1677  break;
1678  }
1679 
1680  case SCIP_NLPPAR_RELOBJTOL:
1681  {
1682  if( dval >= 0 )
1683  {
1684  problem->ipopt->Options()->SetNumericValue("dual_inf_tol", dval);
1685  }
1686  else
1687  {
1688  SCIPerrorMessage("Value %g for parameter relative objective tolerance is negative\n", dval);
1689  return SCIP_PARAMETERWRONGVAL;
1690  }
1691  break;
1692  }
1693 
1694  case SCIP_NLPPAR_LOBJLIM:
1695  {
1696  SCIP_NLPIDATA* data;
1697 
1698  data = SCIPnlpiGetData(nlpi);
1699  assert(data != NULL);
1700 
1701  SCIPmessagePrintWarning(data->messagehdlr, "Parameter lower objective limit not supported by Ipopt interface yet. Ignored.\n");
1702  break;
1703  }
1704 
1705  case SCIP_NLPPAR_INFINITY:
1706  {
1707  if( dval < 0.0 )
1708  return SCIP_PARAMETERWRONGVAL;
1709  if( problem )
1710  {
1711  problem->ipopt->Options()->SetNumericValue("diverging_iterates_tol", dval);
1712  problem->ipopt->Options()->SetNumericValue("nlp_lower_bound_inf", -dval);
1713  problem->ipopt->Options()->SetNumericValue("nlp_upper_bound_inf", dval);
1714  SCIPnlpiOracleSetInfinity(problem->oracle, dval);
1715  }
1716  else
1717  {
1718  SCIP_NLPIDATA* data = SCIPnlpiGetData(nlpi);
1719  assert(data != NULL);
1720  data->infinity = dval;
1721  }
1722  break;
1723  }
1724 
1725  case SCIP_NLPPAR_ITLIM:
1726  {
1727  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1728  return SCIP_PARAMETERWRONGTYPE;
1729  }
1730 
1731  case SCIP_NLPPAR_TILIM:
1732  {
1733  if( dval >= 0 )
1734  {
1735  problem->ipopt->Options()->SetNumericValue("max_cpu_time", dval);
1736  }
1737  else
1738  {
1739  SCIPerrorMessage("Value %g for parameter time limit is negative\n", dval);
1740  return SCIP_PARAMETERWRONGVAL;
1741  }
1742  break;
1743  }
1744 
1745  case SCIP_NLPPAR_OPTFILE:
1746  {
1747  SCIPerrorMessage("option file parameter is of type string.\n");
1748  return SCIP_PARAMETERWRONGTYPE;
1749  }
1750 
1751  case SCIP_NLPPAR_FASTFAIL:
1752  {
1753  SCIPerrorMessage("fastfail parameter is of type int.\n");
1754  return SCIP_PARAMETERWRONGTYPE;
1755  }
1756 
1757  default:
1758  {
1759  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1760  return SCIP_PARAMETERUNKNOWN;
1761  }
1762  }
1763 
1764  return SCIP_OKAY;
1765 }
1766 
1767 /** gets string parameter of NLP
1768  *
1769  * input:
1770  * - nlpi NLP interface structure
1771  * - problem datastructure for problem instance
1772  * - type parameter number
1773  * - sval pointer to store the string value, the user must not modify the string
1774  *
1775  * output:
1776  * - sval parameter value
1777  */
1778 static
1779 SCIP_DECL_NLPIGETSTRINGPAR( nlpiGetStringParIpopt )
1780 {
1781  assert(nlpi != NULL);
1782  assert(problem != NULL);
1783 
1784  switch( type )
1785  {
1787  {
1788  SCIPerrorMessage("from scratch parameter is of type int.\n");
1789  return SCIP_PARAMETERWRONGTYPE;
1790  }
1791 
1792  case SCIP_NLPPAR_VERBLEVEL:
1793  {
1794  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1795  return SCIP_PARAMETERWRONGTYPE;
1796  }
1797 
1798  case SCIP_NLPPAR_FEASTOL:
1799  {
1800  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1801  return SCIP_PARAMETERWRONGTYPE;
1802  }
1803 
1804  case SCIP_NLPPAR_RELOBJTOL:
1805  {
1806  SCIPerrorMessage("objective tolerance parameter is of type real.\n");
1807  return SCIP_PARAMETERWRONGTYPE;
1808  }
1809 
1810  case SCIP_NLPPAR_LOBJLIM:
1811  {
1812  SCIPerrorMessage("objective limit parameter is of type real.\n");
1813  return SCIP_PARAMETERWRONGTYPE;
1814  }
1815 
1816  case SCIP_NLPPAR_INFINITY:
1817  {
1818  SCIPerrorMessage("infinity parameter is of type real.\n");
1819  return SCIP_PARAMETERWRONGTYPE;
1820  }
1821 
1822  case SCIP_NLPPAR_ITLIM:
1823  {
1824  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1825  return SCIP_PARAMETERWRONGTYPE;
1826  }
1827 
1828  case SCIP_NLPPAR_TILIM:
1829  {
1830  SCIPerrorMessage("time limit parameter is of type real.\n");
1831  return SCIP_PARAMETERWRONGTYPE;
1832  }
1833 
1834  case SCIP_NLPPAR_OPTFILE:
1835  {
1836  if( !problem->optfile.empty() )
1837  *sval = problem->optfile.c_str();
1838  else
1839  *sval = NULL;
1840  return SCIP_OKAY;
1841  }
1842 
1843  case SCIP_NLPPAR_FASTFAIL:
1844  {
1845  SCIPerrorMessage("fastfail parameter is of type int.\n");
1846  return SCIP_PARAMETERWRONGTYPE;
1847  }
1848 
1849  default:
1850  {
1851  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1852  return SCIP_PARAMETERUNKNOWN;
1853  }
1854  }
1855 
1856  return SCIP_OKAY;
1857 }
1858 
1859 /** sets string parameter of NLP
1860  *
1861  * input:
1862  * - nlpi NLP interface structure
1863  * - problem datastructure for problem instance
1864  * - type parameter number
1865  * - sval parameter value
1866  */
1867 static
1868 SCIP_DECL_NLPISETSTRINGPAR( nlpiSetStringParIpopt )
1869 {
1870  assert(nlpi != NULL);
1871  assert(problem != NULL);
1872 
1873  switch( type )
1874  {
1876  {
1877  SCIPerrorMessage("from scratch parameter is of type int.\n");
1878  return SCIP_PARAMETERWRONGTYPE;
1879  }
1880 
1881  case SCIP_NLPPAR_VERBLEVEL:
1882  {
1883  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1884  return SCIP_PARAMETERWRONGTYPE;
1885  }
1886 
1887  case SCIP_NLPPAR_FEASTOL:
1888  {
1889  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1890  return SCIP_PARAMETERWRONGTYPE;
1891  }
1892 
1893  case SCIP_NLPPAR_RELOBJTOL:
1894  {
1895  SCIPerrorMessage("objective tolerance parameter is of type real.\n");
1896  return SCIP_PARAMETERWRONGTYPE;
1897  }
1898 
1899  case SCIP_NLPPAR_LOBJLIM:
1900  {
1901  SCIPerrorMessage("objective limit parameter is of type real.\n");
1902  return SCIP_PARAMETERWRONGTYPE;
1903  }
1904 
1905  case SCIP_NLPPAR_INFINITY:
1906  {
1907  SCIPerrorMessage("infinity parameter is of type real.\n");
1908  return SCIP_PARAMETERWRONGTYPE;
1909  }
1910 
1911  case SCIP_NLPPAR_ITLIM:
1912  {
1913  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1914  return SCIP_PARAMETERWRONGTYPE;
1915  }
1916 
1917  case SCIP_NLPPAR_TILIM:
1918  {
1919  SCIPerrorMessage("time limit parameter is of type real.\n");
1920  return SCIP_PARAMETERWRONGTYPE;
1921  }
1922 
1923  case SCIP_NLPPAR_OPTFILE:
1924  {
1925  if( sval != NULL )
1926  problem->optfile = sval;
1927  else
1928  problem->optfile.clear();
1929 
1930  if( problem->ipopt->Initialize(problem->optfile) != Solve_Succeeded )
1931  {
1932  SCIPerrorMessage("Error initializing Ipopt using optionfile \"%s\"\n", problem->optfile.c_str());
1933  return SCIP_ERROR;
1934  }
1935  problem->ipopt->Options()->GetBoolValue("store_intermediate", problem->storeintermediate, "");
1936  problem->firstrun = TRUE;
1937 
1938  return SCIP_OKAY;
1939  }
1940 
1941  case SCIP_NLPPAR_FASTFAIL:
1942  {
1943  SCIPerrorMessage("fastfail parameter is of type int.\n");
1944  return SCIP_PARAMETERWRONGTYPE;
1945  }
1946 
1947  default:
1948  {
1949  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1950  return SCIP_PARAMETERUNKNOWN;
1951  }
1952  }
1953 
1954  return SCIP_OKAY;
1955 }
1956 
1957 /** sets message handler for message output
1958  *
1959  * input:
1960  * - nlpi NLP interface structure
1961  * - messagehdlr SCIP message handler, or NULL to suppress all output
1962  */
1963 static
1964 SCIP_DECL_NLPISETMESSAGEHDLR( nlpiSetMessageHdlrIpopt )
1965 {
1966  SCIP_NLPIDATA* nlpidata;
1967 
1968  assert(nlpi != NULL);
1969 
1970  nlpidata = SCIPnlpiGetData(nlpi);
1971  assert(nlpidata != NULL);
1972 
1973  nlpidata->messagehdlr = messagehdlr;
1974 
1975  return SCIP_OKAY; /*lint !e527*/
1976 } /*lint !e715*/
1977 
1978 /** create solver interface for Ipopt solver */
1980  BMS_BLKMEM* blkmem, /**< block memory data structure */
1981  SCIP_NLPI** nlpi /**< pointer to buffer for nlpi address */
1982  )
1983 {
1984  SCIP_NLPIDATA* nlpidata;
1985 
1986  assert(blkmem != NULL);
1987  assert(nlpi != NULL);
1988 
1989  SCIP_ALLOC( nlpidata = new SCIP_NLPIDATA(blkmem) );
1990 
1991  SCIP_CALL( SCIPnlpiCreate(nlpi,
1993  nlpiCopyIpopt, nlpiFreeIpopt, nlpiGetSolverPointerIpopt,
1994  nlpiCreateProblemIpopt, nlpiFreeProblemIpopt, nlpiGetProblemPointerIpopt,
1995  nlpiAddVarsIpopt, nlpiAddConstraintsIpopt, nlpiSetObjectiveIpopt,
1996  nlpiChgVarBoundsIpopt, nlpiChgConsSidesIpopt, nlpiDelVarSetIpopt, nlpiDelConstraintSetIpopt,
1997  nlpiChgLinearCoefsIpopt, nlpiChgQuadraticCoefsIpopt, nlpiChgExprtreeIpopt, nlpiChgNonlinCoefIpopt,
1998  nlpiChgObjConstantIpopt, nlpiSetInitialGuessIpopt, nlpiSolveIpopt, nlpiGetSolstatIpopt, nlpiGetTermstatIpopt,
1999  nlpiGetSolutionIpopt, nlpiGetStatisticsIpopt,
2000  nlpiGetWarmstartSizeIpopt, nlpiGetWarmstartMemoIpopt, nlpiSetWarmstartMemoIpopt,
2001  nlpiGetIntParIpopt, nlpiSetIntParIpopt, nlpiGetRealParIpopt, nlpiSetRealParIpopt,
2002  nlpiGetStringParIpopt, nlpiSetStringParIpopt, nlpiSetMessageHdlrIpopt,
2003  nlpidata) );
2004 
2005  return SCIP_OKAY;
2006 }
2007 
2008 /** gets string that identifies Ipopt (version number) */
2009 const char* SCIPgetSolverNameIpopt(void)
2010 {
2011  return "Ipopt " IPOPT_VERSION;
2012 }
2013 
2014 /** gets string that describes Ipopt (version number) */
2015 const char* SCIPgetSolverDescIpopt(void)
2016 {
2017  return "Interior Point Optimizer developed by A. Waechter et.al. (www.coin-or.org/Ipopt)";
2018 }
2019 
2020 /** returns whether Ipopt is available, i.e., whether it has been linked in */
2022 {
2023  return TRUE;
2024 }
2025 
2026 /** gives a pointer to the IpoptApplication object stored in Ipopt-NLPI's NLPI problem data structure */
2028  SCIP_NLPIPROBLEM* nlpiproblem /**< NLP problem of Ipopt-NLPI */
2029  )
2030 {
2031  assert(nlpiproblem != NULL);
2032 
2033  return (void*)GetRawPtr(nlpiproblem->ipopt);
2034 }
2035 
2036 /** gives a pointer to the NLPIORACLE object stored in Ipopt-NLPI's NLPI problem data structure */
2038  SCIP_NLPIPROBLEM* nlpiproblem /**< NLP problem of Ipopt-NLPI */
2039  )
2040 {
2041  assert(nlpiproblem != NULL);
2042 
2043  return nlpiproblem->oracle;
2044 }
2045 
2046 /** sets modified default settings that are used when setting up an Ipopt problem
2047  *
2048  * Do not forget to add a newline after the last option in optionsstring.
2049  */
2051  SCIP_NLPI* nlpi, /**< Ipopt NLP interface */
2052  const char* optionsstring /**< string with options as in Ipopt options file */
2053  )
2054 {
2055  SCIP_NLPIDATA* data;
2056 
2057  assert(nlpi != NULL);
2058 
2059  data = SCIPnlpiGetData(nlpi);
2060  assert(data != NULL);
2061 
2062  data->defoptions = optionsstring;
2063 }
2064 
2065 /** Method to return some info about the nlp */
2066 bool ScipNLP::get_nlp_info(
2067  Index& n, /**< place to store number of variables */
2068  Index& m, /**< place to store number of constraints */
2069  Index& nnz_jac_g, /**< place to store number of nonzeros in jacobian */
2070  Index& nnz_h_lag, /**< place to store number of nonzeros in hessian */
2071  IndexStyleEnum& index_style /**< place to store used index style (0-based or 1-based) */
2072  )
2073 {
2074  const int* offset;
2075  SCIP_RETCODE retcode;
2076 
2077  assert(nlpiproblem != NULL);
2078  assert(nlpiproblem->oracle != NULL);
2079 
2080  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2081  m = SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle);
2082 
2083  retcode = SCIPnlpiOracleGetJacobianSparsity(nlpiproblem->oracle, &offset, NULL);
2084  if( retcode != SCIP_OKAY )
2085  return false;
2086  assert(offset != NULL);
2087  nnz_jac_g = offset[m];
2088 
2089  if( !approxhessian )
2090  {
2091  retcode = SCIPnlpiOracleGetHessianLagSparsity(nlpiproblem->oracle, &offset, NULL);
2092  if( retcode != SCIP_OKAY )
2093  return false;
2094  assert(offset != NULL);
2095  nnz_h_lag = offset[n];
2096  }
2097  else
2098  {
2099  nnz_h_lag = 0;
2100  }
2101 
2102  index_style = TNLP::C_STYLE;
2103 
2104  return true;
2105 }
2106 
2107 /** Method to return the bounds for my problem */
2108 bool ScipNLP::get_bounds_info(
2109  Index n, /**< number of variables */
2110  Number* x_l, /**< buffer to store lower bounds on variables */
2111  Number* x_u, /**< buffer to store upper bounds on variables */
2112  Index m, /**< number of constraints */
2113  Number* g_l, /**< buffer to store lower bounds on constraints */
2114  Number* g_u /**< buffer to store lower bounds on constraints */
2115  )
2116 {
2117  assert(nlpiproblem != NULL);
2118  assert(nlpiproblem->oracle != NULL);
2119 
2120  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2121  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2122 
2123  assert(SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle) != NULL);
2124  assert(SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle) != NULL);
2125 
2126  BMScopyMemoryArray(x_l, SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle), n);
2127  BMScopyMemoryArray(x_u, SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle), n);
2128 #ifndef NDEBUG
2129  for( int i = 0; i < n; ++i )
2130  assert(x_l[i] <= x_u[i]);
2131 #endif
2132 
2133  for( int i = 0; i < m; ++i )
2134  {
2135  g_l[i] = SCIPnlpiOracleGetConstraintLhs(nlpiproblem->oracle, i);
2136  g_u[i] = SCIPnlpiOracleGetConstraintRhs(nlpiproblem->oracle, i);
2137  assert(g_l[i] <= g_u[i]);
2138  }
2139 
2140  return true;
2141 }
2142 
2143 /** Method to return the starting point for the algorithm */
2144 bool ScipNLP::get_starting_point(
2145  Index n, /**< number of variables */
2146  bool init_x, /**< whether initial values for primal values are requested */
2147  Number* x, /**< buffer to store initial primal values */
2148  bool init_z, /**< whether initial values for dual values of variable bounds are requested */
2149  Number* z_L, /**< buffer to store dual values for variable lower bounds */
2150  Number* z_U, /**< buffer to store dual values for variable upper bounds */
2151  Index m, /**< number of constraints */
2152  bool init_lambda, /**< whether initial values for dual values of constraints are required */
2153  Number* lambda /**< buffer to store dual values of constraints */
2154  )
2155 {
2156  assert(nlpiproblem != NULL);
2157  assert(nlpiproblem->oracle != NULL);
2158 
2159  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2160  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2161 
2162  if( init_x )
2163  {
2164  if( nlpiproblem->initguess )
2165  {
2166  BMScopyMemoryArray(x, nlpiproblem->initguess, n);
2167  }
2168  else
2169  {
2170  SCIP_Real lb, ub;
2171 
2172  SCIPdebugMessage("Ipopt started without intial primal values; make up starting guess by projecting 0 onto variable bounds\n");
2173 
2174  for( int i = 0; i < n; ++i )
2175  {
2176  lb = SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle)[i];
2177  ub = SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle)[i];
2178  if( lb > 0.0 )
2179  x[i] = SCIPrandomGetReal(randnumgen, lb, lb + MAXPERTURB*MIN(1.0, ub-lb));
2180  else if( ub < 0.0 )
2181  x[i] = SCIPrandomGetReal(randnumgen, ub - MAXPERTURB*MIN(1.0, ub-lb), ub);
2182  else
2183  x[i] = SCIPrandomGetReal(randnumgen, MAX(lb, -MAXPERTURB*MIN(1.0, ub-lb)), MIN(ub, MAXPERTURB*MIN(1.0, ub-lb)));
2184  }
2185  }
2186  }
2187  if( init_z || init_lambda )
2188  return false;
2189 
2190  return true;
2191 }
2192 
2193 /** Method to return the variables linearity. */
2194 bool ScipNLP::get_variables_linearity(
2195  Index n, /**< number of variables */
2196  LinearityType* var_types /**< buffer to store linearity types of variables */
2197  )
2198 {
2199  assert(nlpiproblem != NULL);
2200  assert(nlpiproblem->oracle != NULL);
2201 
2202  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2203 
2204  for( int i = 0; i < n; ++i )
2205  var_types[i] = (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) <= 1 ? LINEAR : NON_LINEAR);
2206 
2207  return true;
2208 }
2209 
2210 /** Method to return the constraint linearity. */
2211 bool ScipNLP::get_constraints_linearity(
2212  Index m, /**< number of constraints */
2213  LinearityType* const_types /**< buffer to store linearity types of constraints */
2214  )
2215 {
2216  int i;
2217 
2218  assert(nlpiproblem != NULL);
2219  assert(nlpiproblem->oracle != NULL);
2220 
2221  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2222 
2223  for( i = 0; i < m; ++i )
2224  const_types[i] = (SCIPnlpiOracleGetConstraintDegree(nlpiproblem->oracle, i) <= 1 ? LINEAR : NON_LINEAR);
2225 
2226  return true;
2227 }
2228 
2229 /** Method to return the number of nonlinear variables. */
2230 Index ScipNLP::get_number_of_nonlinear_variables()
2231 {
2232  int count;
2233  int n;
2234 
2235  assert(nlpiproblem != NULL);
2236  assert(nlpiproblem->oracle != NULL);
2237 
2238  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2239 
2240  count = 0;
2241  for( int i = 0; i < n; ++i )
2242  if (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) > 1)
2243  ++count;
2244 
2245  return count;
2246 }
2247 
2248 /** Method to return the indices of the nonlinear variables */
2249 bool ScipNLP::get_list_of_nonlinear_variables(
2250  Index num_nonlin_vars, /**< number of nonlinear variables */
2251  Index* pos_nonlin_vars /**< array to fill with indices of nonlinear variables */
2252  )
2253 {
2254  int count;
2255  int n;
2256 
2257  assert(nlpiproblem != NULL);
2258  assert(nlpiproblem->oracle != NULL);
2259 
2260  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2261 
2262  count = 0;
2263  for( int i = 0; i < n; ++i )
2264  if (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) > 1)
2265  {
2266  assert(count < num_nonlin_vars);
2267  pos_nonlin_vars[count++] = i;
2268  }
2269 
2270  assert(count == num_nonlin_vars);
2271 
2272  return true;
2273 }
2274 
2275 /** Method to return metadata about variables and constraints */
2276 bool ScipNLP::get_var_con_metadata(
2277  Index n, /**< number of variables */
2278  StringMetaDataMapType& var_string_md, /**< variable meta data of string type */
2279  IntegerMetaDataMapType& var_integer_md,/**< variable meta data of integer type */
2280  NumericMetaDataMapType& var_numeric_md,/**< variable meta data of numeric type */
2281  Index m, /**< number of constraints */
2282  StringMetaDataMapType& con_string_md, /**< constraint meta data of string type */
2283  IntegerMetaDataMapType& con_integer_md,/**< constraint meta data of integer type */
2284  NumericMetaDataMapType& con_numeric_md /**< constraint meta data of numeric type */
2285  )
2286 {
2287  assert(nlpiproblem != NULL);
2288  assert(nlpiproblem->oracle != NULL);
2289  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2290  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2291 
2292  char** varnames = SCIPnlpiOracleGetVarNames(nlpiproblem->oracle);
2293  if( varnames != NULL )
2294  {
2295  std::vector<std::string>& varnamesvec(var_string_md["idx_names"]);
2296  varnamesvec.reserve(n);
2297  for( int i = 0; i < n; ++i )
2298  {
2299  if( varnames[i] != NULL )
2300  {
2301  varnamesvec.push_back(varnames[i]);
2302  }
2303  else
2304  {
2305  char buffer[20];
2306  sprintf(buffer, "nlpivar%8d", i);
2307  varnamesvec.push_back(buffer);
2308  }
2309  }
2310  }
2311 
2312  std::vector<std::string>& consnamesvec(con_string_md["idx_names"]);
2313  consnamesvec.reserve(m);
2314  for( int i = 0; i < m; ++i )
2315  {
2316  if( SCIPnlpiOracleGetConstraintName(nlpiproblem->oracle, i) != NULL )
2317  {
2318  consnamesvec.push_back(SCIPnlpiOracleGetConstraintName(nlpiproblem->oracle, i));
2319  }
2320  else
2321  {
2322  char buffer[20];
2323  sprintf(buffer, "nlpicons%8d", i);
2324  consnamesvec.push_back(buffer);
2325  }
2326  }
2327 
2328  return true;
2329 }
2330 
2331 /** Method to return the objective value */
2332 bool ScipNLP::eval_f(
2333  Index n, /**< number of variables */
2334  const Number* x, /**< point to evaluate */
2335  bool new_x, /**< whether some function evaluation method has been called for this point before */
2336  Number& obj_value /**< place to store objective function value */
2337  )
2338 {
2339  assert(nlpiproblem != NULL);
2340  assert(nlpiproblem->oracle != NULL);
2341 
2342  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2343 
2344  return SCIPnlpiOracleEvalObjectiveValue(nlpiproblem->oracle, x, &obj_value) == SCIP_OKAY;
2345 }
2346 
2347 /** Method to return the gradient of the objective */
2348 bool ScipNLP::eval_grad_f(
2349  Index n, /**< number of variables */
2350  const Number* x, /**< point to evaluate */
2351  bool new_x, /**< whether some function evaluation method has been called for this point before */
2352  Number* grad_f /**< buffer to store objective gradient */
2353  )
2354 {
2355  SCIP_Real dummy;
2356 
2357  assert(nlpiproblem != NULL);
2358  assert(nlpiproblem->oracle != NULL);
2359 
2360  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2361 
2362  return SCIPnlpiOracleEvalObjectiveGradient(nlpiproblem->oracle, x, TRUE, &dummy, grad_f) == SCIP_OKAY;
2363 }
2364 
2365 /** Method to return the constraint residuals */
2366 bool ScipNLP::eval_g(
2367  Index n, /**< number of variables */
2368  const Number* x, /**< point to evaluate */
2369  bool new_x, /**< whether some function evaluation method has been called for this point before */
2370  Index m, /**< number of constraints */
2371  Number* g /**< buffer to store constraint function values */
2372  )
2373 {
2374  assert(nlpiproblem != NULL);
2375  assert(nlpiproblem->oracle != NULL);
2376 
2377  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2378 
2379  return SCIPnlpiOracleEvalConstraintValues(nlpiproblem->oracle, x, g) == SCIP_OKAY;
2380 }
2381 
2382 /** Method to return:
2383  * 1) The structure of the jacobian (if "values" is NULL)
2384  * 2) The values of the jacobian (if "values" is not NULL)
2385  */
2386 bool ScipNLP::eval_jac_g(
2387  Index n, /**< number of variables */
2388  const Number* x, /**< point to evaluate */
2389  bool new_x, /**< whether some function evaluation method has been called for this point before */
2390  Index m, /**< number of constraints */
2391  Index nele_jac, /**< number of nonzero entries in jacobian */
2392  Index* iRow, /**< buffer to store row indices of nonzero jacobian entries, or NULL if values are requested */
2393  Index* jCol, /**< buffer to store column indices of nonzero jacobian entries, or NULL if values are requested */
2394  Number* values /**< buffer to store values of nonzero jacobian entries, or NULL if structure is requested */
2395  )
2396 {
2397  assert(nlpiproblem != NULL);
2398  assert(nlpiproblem->oracle != NULL);
2399 
2400  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2401  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2402 
2403  if( values == NULL )
2404  { /* Ipopt wants to know sparsity structure */
2405  const int* jacoffset;
2406  const int* jaccol;
2407  int j;
2408  int i;
2409 
2410  assert(iRow != NULL);
2411  assert(jCol != NULL);
2412 
2413  if( SCIPnlpiOracleGetJacobianSparsity(nlpiproblem->oracle, &jacoffset, &jaccol) != SCIP_OKAY )
2414  return false;
2415 
2416  assert(jacoffset[0] == 0);
2417  assert(jacoffset[m] == nele_jac);
2418  j = jacoffset[0];
2419  for( i = 0; i < m; ++i )
2420  for( ; j < jacoffset[i+1]; ++j )
2421  iRow[j] = i;
2422 
2423  BMScopyMemoryArray(jCol, jaccol, nele_jac);
2424  }
2425  else
2426  {
2427  if( SCIPnlpiOracleEvalJacobian(nlpiproblem->oracle, x, TRUE, NULL, values) != SCIP_OKAY )
2428  return false;
2429  }
2430 
2431  return true;
2432 }
2433 
2434 /** Method to return:
2435  * 1) The structure of the hessian of the lagrangian (if "values" is NULL)
2436  * 2) The values of the hessian of the lagrangian (if "values" is not NULL)
2437  */
2438 bool ScipNLP::eval_h(
2439  Index n, /**< number of variables */
2440  const Number* x, /**< point to evaluate */
2441  bool new_x, /**< whether some function evaluation method has been called for this point before */
2442  Number obj_factor, /**< weight for objective function */
2443  Index m, /**< number of constraints */
2444  const Number* lambda, /**< weights for constraint functions */
2445  bool new_lambda, /**< whether the hessian has been evaluated for these values of lambda before */
2446  Index nele_hess, /**< number of nonzero entries in hessian */
2447  Index* iRow, /**< buffer to store row indices of nonzero hessian entries, or NULL if values are requested */
2448  Index* jCol, /**< buffer to store column indices of nonzero hessian entries, or NULL if values are requested */
2449  Number* values /**< buffer to store values of nonzero hessian entries, or NULL if structure is requested */
2450  )
2451 {
2452  assert(nlpiproblem != NULL);
2453  assert(nlpiproblem->oracle != NULL);
2454 
2455  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2456  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2457 
2458  if( values == NULL )
2459  { /* Ipopt wants to know sparsity structure */
2460  const int* heslagoffset;
2461  const int* heslagcol;
2462  int j;
2463  int i;
2464 
2465  assert(iRow != NULL);
2466  assert(jCol != NULL);
2467 
2468  if( SCIPnlpiOracleGetHessianLagSparsity(nlpiproblem->oracle, &heslagoffset, &heslagcol) != SCIP_OKAY )
2469  return false;
2470 
2471  assert(heslagoffset[0] == 0);
2472  assert(heslagoffset[n] == nele_hess);
2473  j = heslagoffset[0];
2474  for( i = 0; i < n; ++i )
2475  for( ; j < heslagoffset[i+1]; ++j )
2476  iRow[j] = i;
2477 
2478  BMScopyMemoryArray(jCol, heslagcol, nele_hess);
2479  }
2480  else
2481  {
2482  if( SCIPnlpiOracleEvalHessianLag(nlpiproblem->oracle, x, TRUE, obj_factor, lambda, values) != SCIP_OKAY )
2483  return false;
2484  }
2485 
2486  return true;
2487 }
2488 
2489 /** Method called by the solver at each iteration.
2490  *
2491  * Checks whether Ctrl-C was hit.
2492  */
2493 bool ScipNLP::intermediate_callback(
2494  AlgorithmMode mode, /**< current mode of algorithm */
2495  Index iter, /**< current iteration number */
2496  Number obj_value, /**< current objective value */
2497  Number inf_pr, /**< current primal infeasibility */
2498  Number inf_du, /**< current dual infeasibility */
2499  Number mu, /**< current barrier parameter */
2500  Number d_norm, /**< current gradient norm */
2501  Number regularization_size,/**< current size of regularization */
2502  Number alpha_du, /**< current dual alpha */
2503  Number alpha_pr, /**< current primal alpha */
2504  Index ls_trials, /**< current number of linesearch trials */
2505  const IpoptData* ip_data, /**< pointer to Ipopt Data */
2506  IpoptCalculatedQuantities* ip_cq /**< pointer to current calculated quantities */
2507  )
2508 {
2509  if( nlpiproblem->storeintermediate && mode == RegularMode && inf_pr < nlpiproblem->lastsolinfeas )
2510  {
2511  Ipopt::TNLPAdapter* tnlp_adapter;
2512 
2513  tnlp_adapter = NULL;
2514  if( ip_cq != NULL )
2515  {
2516  Ipopt::OrigIpoptNLP* orignlp;
2517 
2518  orignlp = dynamic_cast<OrigIpoptNLP*>(GetRawPtr(ip_cq->GetIpoptNLP()));
2519  if( orignlp != NULL )
2520  tnlp_adapter = dynamic_cast<TNLPAdapter*>(GetRawPtr(orignlp->nlp()));
2521  }
2522 
2523  if( tnlp_adapter != NULL && ip_data != NULL && IsValid(ip_data->curr()) )
2524  {
2525  SCIPdebugMessage("update lastsol: inf_pr old = %g -> new = %g\n", nlpiproblem->lastsolinfeas, inf_pr);
2526 
2527  if( nlpiproblem->lastsolprimals == NULL )
2528  {
2529  assert(nlpiproblem->lastsoldualcons == NULL);
2530  assert(nlpiproblem->lastsoldualvarlb == NULL);
2531  assert(nlpiproblem->lastsoldualvarub == NULL);
2532  if( BMSallocMemoryArray(&nlpiproblem->lastsolprimals, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL ||
2533  BMSallocMemoryArray(&nlpiproblem->lastsoldualcons, SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle)) == NULL ||
2534  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarlb, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL ||
2535  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarub, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL )
2536  {
2537  SCIPerrorMessage("out-of-memory in ScipNLP::intermediate_callback()\n");
2538  return TRUE;
2539  }
2540  }
2541 
2542  assert(IsValid(ip_data->curr()->x()));
2543  tnlp_adapter->ResortX(*ip_data->curr()->x(), nlpiproblem->lastsolprimals);
2544  nlpiproblem->lastsolinfeas = inf_pr;
2545 
2546  assert(IsValid(ip_data->curr()->y_c()));
2547  assert(IsValid(ip_data->curr()->y_d()));
2548  tnlp_adapter->ResortG(*ip_data->curr()->y_c(), *ip_data->curr()->y_d(), nlpiproblem->lastsoldualcons);
2549 
2550  // need to clear arrays first because ResortBnds only sets values for non-fixed variables
2551  BMSclearMemoryArray(nlpiproblem->lastsoldualvarlb, SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2552  BMSclearMemoryArray(nlpiproblem->lastsoldualvarub, SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2553  assert(IsValid(ip_data->curr()->z_L()));
2554  assert(IsValid(ip_data->curr()->z_U()));
2555  tnlp_adapter->ResortBnds(*ip_data->curr()->z_L(), nlpiproblem->lastsoldualvarlb, *ip_data->curr()->z_U(), nlpiproblem->lastsoldualvarub);
2556 
2557  }
2558  }
2559 
2560  /* do convergence test if fastfail is enabled */
2561  if( nlpiproblem->fastfail )
2562  {
2563  int i;
2564 
2565  if( iter == 0 )
2566  {
2567  conv_lastrestoiter = -1;
2568  }
2569  else if( mode == RestorationPhaseMode )
2570  {
2571  conv_lastrestoiter = iter;
2572  }
2573  else if( conv_lastrestoiter == iter-1 )
2574  {
2575  /* just switched back from restoration mode, reset dual reduction targets */
2576  for( i = 0; i < convcheck_nchecks; ++i )
2577  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2578  }
2579 
2580  if( iter == convcheck_startiter )
2581  {
2582  /* define initial targets and iteration limits */
2583  for( i = 0; i < convcheck_nchecks; ++i )
2584  {
2585  conv_prtarget[i] = convcheck_minred[i] * inf_pr;
2586  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2587  conv_iterlim[i] = iter + convcheck_maxiter[i];
2588  }
2589  }
2590  else if( iter > convcheck_startiter )
2591  {
2592  /* check if we should stop */
2593  for( i = 0; i < convcheck_nchecks; ++i )
2594  {
2595  if( inf_pr <= conv_prtarget[i] )
2596  {
2597  /* sufficient reduction w.r.t. primal infeasibility target
2598  * reset target w.r.t. current infeasibilities
2599  */
2600  conv_prtarget[i] = convcheck_minred[i] * inf_pr;
2601  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2602  conv_iterlim[i] = iter + convcheck_maxiter[i];
2603  }
2604  else if( iter >= conv_iterlim[i] )
2605  {
2606  /* we hit a limit, should we really stop? */
2607  SCIPdebugMessage("convcheck %d: inf_pr = %e > target %e; inf_du = %e target %e: ",
2608  i, inf_pr, conv_prtarget[i], inf_du, conv_dutarget[i]);
2609  if( mode == RegularMode && iter <= conv_lastrestoiter + convcheck_startiter )
2610  {
2611  /* if we returned from feasibility restoration recently, we allow some more iterations,
2612  * because Ipopt may go for optimality for some iterations, at the costs of infeasibility
2613  */
2614  SCIPdebugPrintf("continue, because restoration phase only %d iters ago\n", iter - conv_lastrestoiter);
2615  }
2616  else if( mode == RegularMode && inf_du <= conv_dutarget[i] && iter < conv_iterlim[i] + convcheck_maxiter[i] )
2617  {
2618  /* if dual reduction is sufficient, we allow for twice the number of iterations to reach primal infeas reduction */
2619  SCIPdebugPrintf("continue, because dual infeas. red. sufficient and only %d iters above limit\n", iter - conv_iterlim[i]);
2620  }
2621  else
2622  {
2623  SCIPdebugPrintf("abort\n");
2624  return false;
2625  }
2626  }
2627  }
2628  }
2629  }
2630 
2631  return (SCIPinterrupted() == FALSE);
2632 }
2633 
2634 /** This method is called when the algorithm is complete so the TNLP can store/write the solution. */
2635 void ScipNLP::finalize_solution(
2636  SolverReturn status, /**< solve and solution status */
2637  Index n, /**< number of variables */
2638  const Number* x, /**< primal solution values */
2639  const Number* z_L, /**< dual values of variable lower bounds */
2640  const Number* z_U, /**< dual values of variable upper bounds */
2641  Index m, /**< number of constraints */
2642  const Number* g, /**< values of constraints */
2643  const Number* lambda, /**< dual values of constraints */
2644  Number obj_value, /**< objective function value */
2645  const IpoptData* data, /**< pointer to Ipopt Data */
2646  IpoptCalculatedQuantities* cq /**< pointer to calculated quantities */
2647  )
2648 {
2649  assert(nlpiproblem != NULL);
2650  assert(nlpiproblem->oracle != NULL);
2651 
2652  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2653  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2654 
2655  bool check_feasibility = false; // whether we should check x for feasibility, if not NULL
2656  switch( status )
2657  {
2658  case SUCCESS:
2659  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCOPT;
2660  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2661  assert(x != NULL);
2662  break;
2663 
2664  case STOP_AT_ACCEPTABLE_POINT:
2665  /* if stop at acceptable point, then dual infeasibility can be arbitrary large, so claim only feasibility */
2666  case FEASIBLE_POINT_FOUND:
2667  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2668  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2669  assert(x != NULL);
2670  break;
2671 
2672  case MAXITER_EXCEEDED:
2673  check_feasibility = true;
2674  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2675  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_ITLIM;
2676  break;
2677 
2678  case CPUTIME_EXCEEDED:
2679  check_feasibility = true;
2680  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2681  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_TILIM;
2682  break;
2683 
2684  case STOP_AT_TINY_STEP:
2685  case RESTORATION_FAILURE:
2686  case ERROR_IN_STEP_COMPUTATION:
2687  check_feasibility = true;
2688  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2689  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_NUMERR;
2690  break;
2691 
2692  case LOCAL_INFEASIBILITY:
2693  /* still check feasibility, since we let Ipopt solve with higher tolerance than actually required */
2694  check_feasibility = true;
2695  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2696  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2697  break;
2698 
2699  case DIVERGING_ITERATES:
2700  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNBOUNDED;
2701  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_UOBJLIM;
2702  break;
2703 
2704  case INVALID_NUMBER_DETECTED:
2705  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2706  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_EVALERR;
2707  break;
2708 
2709  case USER_REQUESTED_STOP:
2710  check_feasibility = true;
2711  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2712  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2713  break;
2714 
2715  case TOO_FEW_DEGREES_OF_FREEDOM:
2716  case INTERNAL_ERROR:
2717  case INVALID_OPTION:
2718  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2719  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
2720  break;
2721 
2722  case OUT_OF_MEMORY:
2723  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2724  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_MEMERR;
2725  break;
2726 
2727  default:
2728  SCIPerrorMessage("Ipopt returned with unknown solution status %d\n", status);
2729  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2730  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
2731  break;
2732  }
2733 
2734  /* if Ipopt reports its solution as locally infeasible or we don't know feasibility, then report the intermediate point with lowest constraint violation, if available */
2735  if( (x == NULL || nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE || nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_UNKNOWN) && nlpiproblem->lastsolinfeas != SCIP_INVALID )
2736  {
2737  /* if infeasibility of lastsol is not invalid, then lastsol values should exist */
2738  assert(nlpiproblem->lastsolprimals != NULL);
2739  assert(nlpiproblem->lastsoldualcons != NULL);
2740  assert(nlpiproblem->lastsoldualvarlb != NULL);
2741  assert(nlpiproblem->lastsoldualvarub != NULL);
2742 
2743  /* check if lastsol is feasible */
2744  Number constrvioltol;
2745  nlpiproblem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", constrvioltol, "");
2746  if( nlpiproblem->lastsolinfeas <= constrvioltol )
2747  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2748  else
2749  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2750 
2751  SCIPdebugMessage("drop Ipopt's final point and report intermediate locally %sfeasible solution with infeas %g instead (acceptable: %g)\n",
2752  nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE ? "in" : "", nlpiproblem->lastsolinfeas, constrvioltol);
2753  }
2754  else
2755  {
2756  assert(x != NULL);
2757  assert(lambda != NULL);
2758  assert(z_L != NULL);
2759  assert(z_U != NULL);
2760 
2761  if( nlpiproblem->lastsolprimals == NULL )
2762  {
2763  assert(nlpiproblem->lastsoldualcons == NULL);
2764  assert(nlpiproblem->lastsoldualvarlb == NULL);
2765  assert(nlpiproblem->lastsoldualvarub == NULL);
2766  BMSallocMemoryArray(&nlpiproblem->lastsolprimals, n);
2767  BMSallocMemoryArray(&nlpiproblem->lastsoldualcons, m);
2768  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarlb, n);
2769  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarub, n);
2770 
2771  if( nlpiproblem->lastsolprimals == NULL || nlpiproblem->lastsoldualcons == NULL ||
2772  nlpiproblem->lastsoldualvarlb == NULL || nlpiproblem->lastsoldualvarub == NULL )
2773  {
2774  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2775  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_MEMERR;
2776  return;
2777  }
2778  }
2779 
2780  BMScopyMemoryArray(nlpiproblem->lastsolprimals, x, n);
2781  BMScopyMemoryArray(nlpiproblem->lastsoldualcons, lambda, m);
2782  BMScopyMemoryArray(nlpiproblem->lastsoldualvarlb, z_L, n);
2783  BMScopyMemoryArray(nlpiproblem->lastsoldualvarub, z_U, n);
2784 
2785  if( check_feasibility && cq != NULL )
2786  {
2787  Number constrviol;
2788  Number constrvioltol;
2789 
2790  constrviol = cq->curr_constraint_violation();
2791 
2792  nlpiproblem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", constrvioltol, "");
2793  if( constrviol <= constrvioltol )
2794  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2795  else
2796  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2797  }
2798  }
2799 }
2800 
2801 /** Calls Lapacks Dsyev routine to compute eigenvalues and eigenvectors of a dense matrix.
2802  *
2803  * It's here, because we use Ipopt's interface to Lapack.
2804  */
2806  SCIP_Bool computeeigenvectors,/**< should also eigenvectors should be computed ? */
2807  int N, /**< dimension */
2808  SCIP_Real* a, /**< matrix data on input (size N*N); eigenvectors on output if computeeigenvectors == TRUE */
2809  SCIP_Real* w /**< buffer to store eigenvalues (size N) */
2810  )
2811 {
2812  int info;
2813 
2814  IpLapackDsyev(computeeigenvectors, N, a, N, w, info);
2815 
2816  if( info != 0 )
2817  {
2818  SCIPerrorMessage("There was an error when calling DSYEV. INFO = %d\n", info);
2819  return SCIP_ERROR;
2820  }
2821 
2822  return SCIP_OKAY;
2823 }
2824 
2825 /** solves a linear problem of the form Ax = b for a regular matrix 3*3 A */
2826 static
2828  SCIP_Real* A, /**< matrix data on input (size 3*3); filled column-wise */
2829  SCIP_Real* b, /**< right hand side vector (size 3) */
2830  SCIP_Real* x, /**< buffer to store solution (size 3) */
2831  SCIP_Bool* success /**< pointer to store if the solving routine was successful */
2832  )
2833 {
2834  SCIP_Real Acopy[9];
2835  SCIP_Real bcopy[3];
2836  int pivotcopy[3];
2837  const int N = 3;
2838  int info;
2839 
2840  assert(A != NULL);
2841  assert(b != NULL);
2842  assert(x != NULL);
2843  assert(success != NULL);
2844 
2845  BMScopyMemoryArray(Acopy, A, N*N);
2846  BMScopyMemoryArray(bcopy, b, N);
2847 
2848  /* compute the LU factorization */
2849  IpLapackDgetrf(N, Acopy, pivotcopy, N, info);
2850 
2851  if( info != 0 )
2852  {
2853  SCIPerrorMessage("There was an error when calling Dgetrf. INFO = %d\n", info);
2854  *success = FALSE;
2855  }
2856  else
2857  {
2858  *success = TRUE;
2859 
2860  /* solve linear problem */
2861  IpLapackDgetrs(N, 1, Acopy, N, pivotcopy, bcopy, N);
2862 
2863  /* copy the solution */
2864  BMScopyMemoryArray(x, bcopy, N);
2865  }
2866 
2867  return SCIP_OKAY;
2868 }
2869 
2870 /** solves a linear problem of the form Ax = b for a regular matrix A
2871  *
2872  * Calls Lapacks IpLapackDgetrf routine to calculate a LU factorization and uses this factorization to solve
2873  * the linear problem Ax = b.
2874  * It's here, because Ipopt is linked against Lapack.
2875  */
2877  int N, /**< dimension */
2878  SCIP_Real* A, /**< matrix data on input (size N*N); filled column-wise */
2879  SCIP_Real* b, /**< right hand side vector (size N) */
2880  SCIP_Real* x, /**< buffer to store solution (size N) */
2881  SCIP_Bool* success /**< pointer to store if the solving routine was successful */
2882  )
2883 {
2884  SCIP_Real* Acopy;
2885  SCIP_Real* bcopy;
2886  int* pivotcopy;
2887  int info;
2888 
2889  assert(N > 0);
2890  assert(A != NULL);
2891  assert(b != NULL);
2892  assert(x != NULL);
2893  assert(success != NULL);
2894 
2895  /* call SCIPsolveLinearProb3() for performance reasons */
2896  if( N == 3 )
2897  {
2898  SCIP_CALL( SCIPsolveLinearProb3(A, b, x, success) );
2899  return SCIP_OKAY;
2900  }
2901 
2902  Acopy = NULL;
2903  bcopy = NULL;
2904  pivotcopy = NULL;
2905 
2906  SCIP_ALLOC( BMSduplicateMemoryArray(&Acopy, A, N*N) );
2907  SCIP_ALLOC( BMSduplicateMemoryArray(&bcopy, b, N) );
2908  SCIP_ALLOC( BMSallocMemoryArray(&pivotcopy, N) );
2909 
2910  /* compute the LU factorization */
2911  IpLapackDgetrf(N, Acopy, pivotcopy, N, info);
2912 
2913  if( info != 0 )
2914  {
2915  SCIPerrorMessage("There was an error when calling Dgetrf. INFO = %d\n", info);
2916  *success = FALSE;
2917  }
2918  else
2919  {
2920  *success = TRUE;
2921 
2922  /* solve linear problem */
2923  IpLapackDgetrs(N, 1, Acopy, N, pivotcopy, bcopy, N);
2924 
2925  /* copy the solution */
2926  BMScopyMemoryArray(x, bcopy, N);
2927  }
2928 
2929  BMSfreeMemoryArray(&pivotcopy);
2930  BMSfreeMemoryArray(&bcopy);
2931  BMSfreeMemoryArray(&Acopy);
2932 
2933  return SCIP_OKAY;
2934 }
SCIP_Bool SCIPisIpoptAvailableIpopt(void)
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:8693
SCIP_RETCODE SCIPnlpiOracleEvalConstraintValues(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Real *convals)
Definition: nlpioracle.c:2430
enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
Definition: type_nlpi.h:85
void * SCIPgetNlpiOracleIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
SCIP_Real * lastsoldualvarlb
Definition: nlpi_ipopt.cpp:145
const SCIP_Real * SCIPnlpiOracleGetVarUbs(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2220
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:107
methods to interpret (evaluate) an expression tree "fast"
SCIP_RETCODE SCIPnlpiOracleGetJacobianSparsity(SCIP_NLPIORACLE *oracle, const int **offset, const int **col)
Definition: nlpioracle.c:2499
SCIP_EXPRINTCAPABILITY SCIPnlpiOracleGetEvalCapability(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2370
SmartPtr< ScipNLP > nlp
Definition: nlpi_ipopt.cpp:133
void SCIPsetModifiedDefaultSettingsIpopt(SCIP_NLPI *nlpi, const char *optionsstring)
SCIP_RETCODE SCIPnlpiOracleGetHessianLagSparsity(SCIP_NLPIORACLE *oracle, const int **offset, const int **col)
Definition: nlpioracle.c:2777
SCIP_NLPSOLSTAT lastsolstat
Definition: nlpi_ipopt.cpp:141
static SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemIpopt)
Definition: nlpi_ipopt.cpp:543
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2190
#define infinity
Definition: gastrans.c:71
static SCIP_DECL_NLPIGETWARMSTARTMEMO(nlpiGetWarmstartMemoIpopt)
static SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemIpopt)
Definition: nlpi_ipopt.cpp:640
#define NLPI_NAME
Definition: nlpi_ipopt.cpp:61
struct SCIP_NlpiProblem SCIP_NLPIPROBLEM
Definition: type_nlpi.h:39
internal methods for NLPI solver interfaces
SCIP_RETCODE SCIPnlpiOracleSetObjective(SCIP_NLPIORACLE *oracle, const SCIP_Real constant, int nlin, const int *lininds, const SCIP_Real *linvals, int nquadelems, const SCIP_QUADELEM *quadelems, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree)
Definition: nlpioracle.c:1602
methods to store an NLP and request function, gradient, and hessian values
SCIP_Real lasttime
Definition: nlpi_ipopt.cpp:149
#define FALSE
Definition: def.h:64
SCIP_Real SCIPnlpiOracleGetConstraintLhs(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2271
static SCIP_DECL_NLPIFREE(nlpiFreeIpopt)
Definition: nlpi_ipopt.cpp:506
static SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionIpopt)
#define NLPI_DESC
Definition: nlpi_ipopt.cpp:62
#define FEASTOLFACTOR
Definition: nlpi_ipopt.cpp:73
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define DEFAULT_PRINTLEVEL
Definition: nlpi_ipopt.cpp:68
SCIP_RETCODE SCIPnlpiOracleEvalObjectiveValue(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Real *objval)
Definition: nlpioracle.c:2392
static SCIP_DECL_NLPIGETINTPAR(nlpiGetIntParIpopt)
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:82
static SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessIpopt)
void SCIPmessageVPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr, va_list ap)
Definition: message.c:598
#define SCIP_CALL_ABORT_QUIET(x)
Definition: def.h:290
static SCIP_DECL_NLPISETINTPAR(nlpiSetIntParIpopt)
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPnlpiSetMessageHdlr(SCIP_NLPI *nlpi, SCIP_MESSAGEHDLR *messagehdlr)
Definition: nlpi.c:717
unsigned int SCIP_EXPRINTCAPABILITY
SCIP_RETCODE SCIPnlpiOracleEvalObjectiveGradient(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *objval, SCIP_Real *objgrad)
Definition: nlpioracle.c:2453
static SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveIpopt)
Definition: nlpi_ipopt.cpp:775
SCIP_RETCODE SCIPnlpiOracleDelConsSet(SCIP_NLPIORACLE *oracle, int *delstats)
Definition: nlpioracle.c:1819
SCIP_RETCODE SCIPnlpiOracleChgObjConstant(SCIP_NLPIORACLE *oracle, SCIP_Real objconstant)
Definition: nlpioracle.c:2174
static SCIP_DECL_NLPISETSTRINGPAR(nlpiSetStringParIpopt)
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2200
std::string optfile
Definition: nlpi_ipopt.cpp:134
SCIP_Real * lastsoldualvarub
Definition: nlpi_ipopt.cpp:146
#define DEFAULT_RANDSEED
Definition: nlpi_ipopt.cpp:75
SCIP_Real lastsolinfeas
Definition: nlpi_ipopt.cpp:147
#define DEFAULT_MAXITER
Definition: nlpi_ipopt.cpp:70
void SCIPmessageVPrintError(const char *formatstr, va_list ap)
Definition: message.c:794
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen)
Definition: misc.c:8710
static SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsIpopt)
SCIP_DECL_NLPIGETPROBLEMPOINTER(nlpiGetProblemPointerIpopt)
Definition: nlpi_ipopt.cpp:671
int SCIPnlpiOracleGetConstraintDegree(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2312
const char * SCIPgetSolverNameIpopt(void)
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:106
SCIP_RETCODE SCIPnlpiOracleChgExprtree(SCIP_NLPIORACLE *oracle, int considx, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree)
Definition: nlpioracle.c:2092
static SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantIpopt)
SCIP_RETCODE SCIPnlpiOracleCreate(BMS_BLKMEM *blkmem, SCIP_NLPIORACLE **oracle)
Definition: nlpioracle.c:1320
SCIP_Bool firstrun
Definition: nlpi_ipopt.cpp:138
void SCIPmessagePrintError(const char *formatstr,...)
Definition: message.c:781
#define SCIPerrorMessage
Definition: pub_message.h:45
#define NLPI_PRIORITY
Definition: nlpi_ipopt.cpp:63
#define SCIPdebugPrintf
Definition: pub_message.h:80
const SCIP_Real * SCIPnlpiOracleGetVarLbs(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2210
SCIP_RETCODE SCIPnlpiOracleChgVarBounds(SCIP_NLPIORACLE *oracle, int nvars, const int *indices, const SCIP_Real *lbs, const SCIP_Real *ubs)
Definition: nlpioracle.c:1639
struct SCIP_NlpiData SCIP_NLPIDATA
Definition: type_nlpi.h:38
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
static SCIP_DECL_NLPICHGQUADCOEFS(nlpiChgQuadraticCoefsIpopt)
Definition: nlpi_ipopt.cpp:941
static SCIP_DECL_NLPICHGNONLINCOEF(nlpiChgNonlinCoefIpopt)
Definition: nlpi_ipopt.cpp:986
SCIP_RETCODE SCIPnlpiOracleAddVars(SCIP_NLPIORACLE *oracle, int nvars, const SCIP_Real *lbs, const SCIP_Real *ubs, const char **varnames)
Definition: nlpioracle.c:1439
static SCIP_DECL_NLPIGETREALPAR(nlpiGetRealParIpopt)
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define NULL
Definition: lpi_spx1.cpp:137
static void invalidateSolution(SCIP_NLPIPROBLEM *problem)
Definition: nlpi_ipopt.cpp:424
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Real * lastsolprimals
Definition: nlpi_ipopt.cpp:143
#define SCIP_DEFAULT_FEASTOL
Definition: def.h:153
static SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsIpopt)
Definition: nlpi_ipopt.cpp:803
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:584
SCIP_EXPRINTCAPABILITY SCIPexprintGetCapability(void)
static SCIP_DECL_NLPICOPY(nlpiCopyIpopt)
Definition: nlpi_ipopt.cpp:475
SCIP_RETCODE LapackDsyev(SCIP_Bool computeeigenvectors, int N, SCIP_Real *a, SCIP_Real *w)
SCIP_Real SCIPnlpiOracleGetConstraintRhs(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2284
SCIP_Real SCIPnlpiOracleGetInfinity(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:1392
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:102
SCIP_RETCODE SCIPnlpiOracleFree(SCIP_NLPIORACLE **oracle)
Definition: nlpioracle.c:1347
static const int convcheck_nchecks
Definition: nlpi_ipopt.cpp:102
methods for catching the user CTRL-C interrupt
Ipopt NLP interface.
SmartPtr< IpoptApplication > ipopt
Definition: nlpi_ipopt.cpp:132
SCIP_RETCODE SCIPnlpiCreate(SCIP_NLPI **nlpi, const char *name, const char *description, int priority, SCIP_DECL_NLPICOPY((*nlpicopy)), SCIP_DECL_NLPIFREE((*nlpifree)), SCIP_DECL_NLPIGETSOLVERPOINTER((*nlpigetsolverpointer)), SCIP_DECL_NLPICREATEPROBLEM((*nlpicreateproblem)), SCIP_DECL_NLPIFREEPROBLEM((*nlpifreeproblem)), SCIP_DECL_NLPIGETPROBLEMPOINTER((*nlpigetproblempointer)), SCIP_DECL_NLPIADDVARS((*nlpiaddvars)), SCIP_DECL_NLPIADDCONSTRAINTS((*nlpiaddconstraints)), SCIP_DECL_NLPISETOBJECTIVE((*nlpisetobjective)), SCIP_DECL_NLPICHGVARBOUNDS((*nlpichgvarbounds)), SCIP_DECL_NLPICHGCONSSIDES((*nlpichgconssides)), SCIP_DECL_NLPIDELVARSET((*nlpidelvarset)), SCIP_DECL_NLPIDELCONSSET((*nlpidelconsset)), SCIP_DECL_NLPICHGLINEARCOEFS((*nlpichglinearcoefs)), SCIP_DECL_NLPICHGQUADCOEFS((*nlpichgquadcoefs)), SCIP_DECL_NLPICHGEXPRTREE((*nlpichgexprtree)), SCIP_DECL_NLPICHGNONLINCOEF((*nlpichgnonlincoef)), SCIP_DECL_NLPICHGOBJCONSTANT((*nlpichgobjconstant)), SCIP_DECL_NLPISETINITIALGUESS((*nlpisetinitialguess)), SCIP_DECL_NLPISOLVE((*nlpisolve)), SCIP_DECL_NLPIGETSOLSTAT((*nlpigetsolstat)), SCIP_DECL_NLPIGETTERMSTAT((*nlpigettermstat)), SCIP_DECL_NLPIGETSOLUTION((*nlpigetsolution)), SCIP_DECL_NLPIGETSTATISTICS((*nlpigetstatistics)), SCIP_DECL_NLPIGETWARMSTARTSIZE((*nlpigetwarmstartsize)), SCIP_DECL_NLPIGETWARMSTARTMEMO((*nlpigetwarmstartmemo)), SCIP_DECL_NLPISETWARMSTARTMEMO((*nlpisetwarmstartmemo)), SCIP_DECL_NLPIGETINTPAR((*nlpigetintpar)), SCIP_DECL_NLPISETINTPAR((*nlpisetintpar)), SCIP_DECL_NLPIGETREALPAR((*nlpigetrealpar)), SCIP_DECL_NLPISETREALPAR((*nlpisetrealpar)), SCIP_DECL_NLPIGETSTRINGPAR((*nlpigetstringpar)), SCIP_DECL_NLPISETSTRINGPAR((*nlpisetstringpar)), SCIP_DECL_NLPISETMESSAGEHDLR((*nlpisetmessagehdlr)), SCIP_NLPIDATA *nlpidata)
Definition: nlpi.c:40
public data structures and miscellaneous methods
#define SCIP_EXPRINTCAPABILITY_HESSIAN
static SCIP_DECL_NLPISETWARMSTARTMEMO(nlpiSetWarmstartMemoIpopt)
#define SCIP_Bool
Definition: def.h:61
SCIP_Bool SCIPinterrupted(void)
Definition: interrupt.c:147
#define MAXPERTURB
Definition: nlpi_ipopt.cpp:72
SCIP_RETCODE SCIPnlpiOracleSetProblemName(SCIP_NLPIORACLE *oracle, const char *name)
Definition: nlpioracle.c:1404
static void setFeastol(SCIP_NLPIPROBLEM *nlpiproblem, SCIP_Real feastol)
Definition: nlpi_ipopt.cpp:448
SCIP_RETCODE SCIPnlpiOracleAddConstraints(SCIP_NLPIORACLE *oracle, int nconss, const SCIP_Real *lhss, const SCIP_Real *rhss, const int *nlininds, int *const *lininds, SCIP_Real *const *linvals, const int *nquadelems, SCIP_QUADELEM *const *quadelems, int *const *exprvaridxs, SCIP_EXPRTREE *const *exprtrees, const char **consnames)
Definition: nlpioracle.c:1524
static SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsIpopt)
Definition: nlpi_ipopt.cpp:917
void SCIPnlpStatisticsSetNIterations(SCIP_NLPSTATISTICS *statistics, int niterations)
Definition: nlpi.c:830
static const int convcheck_startiter
Definition: nlpi_ipopt.cpp:103
static SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatIpopt)
#define MAX(x, y)
Definition: tclique_def.h:75
void SCIPnlpStatisticsSetTotalTime(SCIP_NLPSTATISTICS *statistics, SCIP_Real totaltime)
Definition: nlpi.c:840
static SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatIpopt)
SCIP_RETCODE SCIPnlpiOracleChgLinearCoefs(SCIP_NLPIORACLE *oracle, int considx, int nentries, const int *varidxs, const SCIP_Real *newcoefs)
Definition: nlpioracle.c:1897
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:93
static SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsIpopt)
Definition: nlpi_ipopt.cpp:735
SCIP_RETCODE SCIPnlpiOracleChgQuadCoefs(SCIP_NLPIORACLE *oracle, int considx, int nquadelems, const SCIP_QUADELEM *quadelems)
Definition: nlpioracle.c:1994
SCIP_RETCODE SCIPcreateNlpSolverIpopt(BMS_BLKMEM *blkmem, SCIP_NLPI **nlpi)
SCIP_RETCODE SCIPnlpiOracleChgConsSides(SCIP_NLPIORACLE *oracle, int nconss, const int *indices, const SCIP_Real *lhss, const SCIP_Real *rhss)
Definition: nlpioracle.c:1675
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:8745
SCIP_RETCODE SCIPnlpiOracleDelVarSet(SCIP_NLPIORACLE *oracle, int *delstats)
Definition: nlpioracle.c:1709
static SCIP_DECL_NLPIGETSOLVERPOINTER(nlpiGetSolverPointerIpopt)
Definition: nlpi_ipopt.cpp:528
SCIP_RETCODE SCIPsolveLinearProb(int N, SCIP_Real *A, SCIP_Real *b, SCIP_Real *x, SCIP_Bool *success)
char * SCIPnlpiOracleGetConstraintName(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2297
#define SCIP_DEFAULT_INFINITY
Definition: def.h:150
#define SCIP_EXPRINTCAPABILITY_FUNCVALUE
void * SCIPgetIpoptApplicationPointerIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
SCIP_RETCODE SCIPnlpiOracleChgExprParam(SCIP_NLPIORACLE *oracle, int considx, int paramidx, SCIP_Real paramval)
Definition: nlpioracle.c:2149
int SCIPnlpiOracleGetVarDegree(SCIP_NLPIORACLE *oracle, int varidx)
Definition: nlpioracle.c:2242
SCIP_NLPIDATA * SCIPnlpiGetData(SCIP_NLPI *nlpi)
Definition: nlpi.c:730
static SCIP_DECL_NLPIGETWARMSTARTSIZE(nlpiGetWarmstartSizeIpopt)
SCIP_RETCODE SCIPnlpiOracleEvalHessianLag(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real objfactor, const SCIP_Real *lambda, SCIP_Real *hessian)
Definition: nlpioracle.c:2874
const char * SCIPgetSolverDescIpopt(void)
static SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetIpopt)
Definition: nlpi_ipopt.cpp:862
#define SCIP_Real
Definition: def.h:145
SCIP_NLPTERMSTAT lasttermstat
Definition: nlpi_ipopt.cpp:142
#define MIN(x, y)
Definition: memory.c:75
static SCIP_DECL_NLPISETMESSAGEHDLR(nlpiSetMessageHdlrIpopt)
SCIP_Real * lastsoldualcons
Definition: nlpi_ipopt.cpp:144
#define SCIP_INVALID
Definition: def.h:165
static SCIP_DECL_NLPISOLVE(nlpiSolveIpopt)
SCIP_RETCODE SCIPnlpiOracleSetInfinity(SCIP_NLPIORACLE *oracle, SCIP_Real infinity)
Definition: nlpioracle.c:1376
static SCIP_DECL_NLPIGETSTRINGPAR(nlpiGetStringParIpopt)
static SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetIpopt)
Definition: nlpi_ipopt.cpp:889
static SCIP_DECL_NLPISETREALPAR(nlpiSetRealParIpopt)
SCIP_RETCODE SCIPnlpiOracleEvalJacobian(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *convals, SCIP_Real *jacobi)
Definition: nlpioracle.c:2638
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:89
static const SCIP_Real convcheck_minred[convcheck_nchecks]
Definition: nlpi_ipopt.cpp:105
SCIP_Real * initguess
Definition: nlpi_ipopt.cpp:139
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:396
char ** SCIPnlpiOracleGetVarNames(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2230
static SCIP_DECL_NLPICHGEXPRTREE(nlpiChgExprtreeIpopt)
Definition: nlpi_ipopt.cpp:962
#define SCIP_ALLOC(x)
Definition: def.h:327
#define SCIPABORT()
Definition: def.h:288
static SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesIpopt)
Definition: nlpi_ipopt.cpp:837
static SCIP_RETCODE SCIPsolveLinearProb3(SCIP_Real *A, SCIP_Real *b, SCIP_Real *x, SCIP_Bool *success)
static SCIP_DECL_NLPIADDVARS(nlpiAddVarsIpopt)
Definition: nlpi_ipopt.cpp:690
SCIP_NLPIORACLE * oracle
Definition: nlpi_ipopt.cpp:130
#define SCIP_EXPRINTCAPABILITY_GRADIENT
int SCIPnlpiOracleGetMaxDegree(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2344
SCIP_RETCODE SCIPnlpiSetRealPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: nlpi.c:668
static const int convcheck_maxiter[convcheck_nchecks]
Definition: nlpi_ipopt.cpp:104