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