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