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