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-2015 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( !(*problem)->ipopt->Options()->ReadFromStream(*(*problem)->ipopt->Jnlst(), is) )
599  {
600  SCIPerrorMessage("Error when modifiying Ipopt options using options string\n%s\n", data->defoptions.c_str());
601  return SCIP_ERROR;
602  }
603  }
604 
605  /* apply user's given options file (this one is NLPI problem specific) */
606  if( (*problem)->ipopt->Initialize((*problem)->optfile) != Solve_Succeeded )
607  {
608  SCIPerrorMessage("Error during initialization of Ipopt using optionfile \"%s\"\n", (*problem)->optfile.c_str());
609  return SCIP_ERROR;
610  }
611 
612 
613  return SCIP_OKAY;
614 }
615 
616 /** free a problem instance
617  *
618  * input:
619  * - nlpi datastructure for solver interface
620  * - problem pointer where problem data is stored
621  */
622 static
623 SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemIpopt)
624 {
625  assert(nlpi != NULL);
626  assert(problem != NULL);
627  assert(*problem != NULL);
628 
629  if( (*problem)->oracle != NULL )
630  {
631  SCIP_CALL( SCIPnlpiOracleFree(&(*problem)->oracle) );
632  }
633 
634  BMSfreeMemoryArrayNull(&(*problem)->initguess);
635  BMSfreeMemoryArrayNull(&(*problem)->lastsolprimals);
636  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualcons);
637  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualvarlb);
638  BMSfreeMemoryArrayNull(&(*problem)->lastsoldualvarub);
639 
640  delete *problem;
641  *problem = NULL;
642 
643  return SCIP_OKAY;
644 }
645 
646 /** gets pointer to solver-internal problem instance to do dirty stuff
647  *
648  * input:
649  * - nlpi datastructure for solver interface
650  * - problem datastructure for problem instance
651  *
652  * return: void pointer to problem instance
653  */
654 SCIP_DECL_NLPIGETPROBLEMPOINTER(nlpiGetProblemPointerIpopt)
655 {
656  assert(nlpi != NULL);
657  assert(problem != NULL);
658 
659  return GetRawPtr(problem->nlp);
660 }
661 
662 /** add variables
663  *
664  * input:
665  * - nlpi datastructure for solver interface
666  * - problem datastructure for problem instance
667  * - nvars number of variables
668  * - lbs lower bounds of variables, can be NULL if -infinity
669  * - ubs upper bounds of variables, can be NULL if +infinity
670  * - varnames names of variables, can be NULL
671  */
672 static
673 SCIP_DECL_NLPIADDVARS(nlpiAddVarsIpopt)
674 {
675  assert(nlpi != NULL);
676  assert(problem != NULL);
677  assert(problem->oracle != NULL);
678 
679  SCIP_CALL( SCIPnlpiOracleAddVars(problem->oracle, nvars, lbs, ubs, varnames) );
680 
681  problem->firstrun = TRUE;
682  BMSfreeMemoryArrayNull(&problem->initguess);
683  invalidateSolution(problem);
684 
685  return SCIP_OKAY;
686 }
687 
688 /** add constraints
689  *
690  * quadratic coefficiens: row oriented matrix for each constraint
691  *
692  * input:
693  * - nlpi datastructure for solver interface
694  * - problem datastructure for problem instance
695  * - ncons number of added constraints
696  * - lhss left hand sides of constraints
697  * - rhss right hand sides of constraints
698  * - linoffsets start index of each constraints linear coefficients in lininds and linvals
699  * length: ncons + 1, linoffsets[ncons] gives length of lininds and linvals
700  * may be NULL in case of no linear part
701  * - lininds variable indices
702  * may be NULL in case of no linear part
703  * - linvals coefficient values
704  * may be NULL in case of no linear part
705  * - nquadelems number of quadratic elements for each constraint
706  * may be NULL in case of no quadratic part
707  * - quadelems quadratic elements for each constraint
708  * may be NULL in case of no quadratic part
709  * - exprvaridxs indices of variables in expression tree, maps variable indices in expression tree to indices in nlp
710  * entry of array may be NULL in case of no expression tree
711  * may be NULL in case of no expression tree in any constraint
712  * - exprtrees expression tree for nonquadratic part of constraints
713  * entry of array may be NULL in case of no nonquadratic part
714  * may be NULL in case of no nonquadratic part in any constraint
715  * - names of constraints, may be NULL or entries may be NULL
716  */
717 static
718 SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsIpopt)
719 {
720  assert(nlpi != NULL);
721  assert(problem != NULL);
722  assert(problem->oracle != NULL);
723 
724  SCIP_CALL( SCIPnlpiOracleAddConstraints(problem->oracle,
725  ncons, lhss, rhss,
726  nlininds, lininds, linvals,
727  nquadelems, quadelems,
728  exprvaridxs, exprtrees, names) );
729 
730  problem->firstrun = TRUE;
731  invalidateSolution(problem);
732 
733  return SCIP_OKAY;
734 }
735 
736 /** sets or overwrites objective, a minimization problem is expected
737  *
738  * May change sparsity pattern.
739  *
740  * input:
741  * - nlpi datastructure for solver interface
742  * - problem datastructure for problem instance
743  * - nlins number of linear variables
744  * - lininds variable indices
745  * may be NULL in case of no linear part
746  * - linvals coefficient values
747  * may be NULL in case of no linear part
748  * - nquadelems number of elements in matrix of quadratic part
749  * - quadelems elements of quadratic part
750  * may be NULL in case of no quadratic part
751  * - exprvaridxs indices of variables in expression tree, maps variable indices in expression tree to indices in nlp
752  * may be NULL in case of no expression tree
753  * - exprtree expression tree for nonquadratic part of objective function
754  * may be NULL in case of no nonquadratic part
755  * - constant objective value offset
756  */
757 static
758 SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveIpopt)
759 {
760  assert(nlpi != NULL);
761  assert(problem != NULL);
762  assert(problem->oracle != NULL);
763 
764  SCIP_CALL( SCIPnlpiOracleSetObjective(problem->oracle,
765  constant, nlins, lininds, linvals,
766  nquadelems, quadelems,
767  exprvaridxs, exprtree) );
768 
769  problem->firstrun = TRUE;
770  invalidateSolution(problem);
771 
772  return SCIP_OKAY;
773 }
774 
775 /** change variable bounds
776  *
777  * input:
778  * - nlpi datastructure for solver interface
779  * - problem datastructure for problem instance
780  * - nvars number of variables to change bounds
781  * - indices indices of variables to change bounds
782  * - lbs new lower bounds
783  * - ubs new upper bounds
784  */
785 static
786 SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsIpopt)
787 {
788  assert(nlpi != NULL);
789  assert(problem != NULL);
790  assert(problem->oracle != NULL);
791 
792  SCIP_CALL( SCIPnlpiOracleChgVarBounds(problem->oracle, nvars, indices, lbs, ubs) );
793 
794  invalidateSolution(problem);
795 
796  return SCIP_OKAY;
797 }
798 
799 /** change constraint bounds
800  *
801  * input:
802  * - nlpi datastructure for solver interface
803  * - problem datastructure for problem instance
804  * - nconss number of constraints to change sides
805  * - indices indices of constraints to change sides
806  * - lhss new left hand sides
807  * - rhss new right hand sides
808  */
809 static
810 SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesIpopt)
811 {
812  assert(nlpi != NULL);
813  assert(problem != NULL);
814  assert(problem->oracle != NULL);
815 
816  SCIP_CALL( SCIPnlpiOracleChgConsSides(problem->oracle, nconss, indices, lhss, rhss) );
817 
818  invalidateSolution(problem);
819 
820  return SCIP_OKAY;
821 }
822 
823 /** delete a set of variables
824  *
825  * input:
826  * - nlpi datastructure for solver interface
827  * - problem datastructure for problem instance
828  * - nlpi datastructure for solver interface
829  * - dstats deletion status of vars; 1 if var should be deleted, 0 if not
830  *
831  * output:
832  * - dstats new position of var, -1 if var was deleted
833  */
834 static
835 SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetIpopt)
836 {
837  assert(nlpi != NULL);
838  assert(problem != NULL);
839  assert(problem->oracle != NULL);
840 
841  SCIP_CALL( SCIPnlpiOracleDelVarSet(problem->oracle, dstats) );
842 
843  problem->firstrun = TRUE;
844  BMSfreeMemoryArrayNull(&problem->initguess); // @TODO keep initguess for remaining variables
845 
846  invalidateSolution(problem);
847 
848  return SCIP_OKAY;
849 }
850 
851 /** delete a set of constraints
852  *
853  * input:
854  * - nlpi datastructure for solver interface
855  * - problem datastructure for problem instance
856  * - dstats deletion status of rows; 1 if row should be deleted, 0 if not
857  *
858  * output:
859  * - dstats new position of row, -1 if row was deleted
860  */
861 static
862 SCIP_DECL_NLPIDELCONSSET(nlpiDelConstraintSetIpopt)
863 {
864  assert(nlpi != NULL);
865  assert(problem != NULL);
866  assert(problem->oracle != NULL);
867 
868  SCIP_CALL( SCIPnlpiOracleDelConsSet(problem->oracle, dstats) );
869 
870  problem->firstrun = TRUE;
871 
872  invalidateSolution(problem);
873 
874  return SCIP_OKAY;
875 }
876 
877 /** change one linear coefficient in a constraint or objective
878  *
879  * input:
880  * - nlpi datastructure for solver interface
881  * - problem datastructure for problem instance
882  * - idx index of constraint or -1 for objective
883  * - nvals number of values in linear constraint
884  * - varidxs indices of variable
885  * - vals new values for coefficient
886  *
887  * return: Error if coefficient did not exist before
888  */
889 static
890 SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsIpopt)
891 {
892  assert(nlpi != NULL);
893  assert(problem != NULL);
894  assert(problem->oracle != NULL);
895 
896  SCIP_CALL( SCIPnlpiOracleChgLinearCoefs(problem->oracle, idx, nvals, varidxs, vals) );
897  invalidateSolution(problem);
898 
899  return SCIP_OKAY;
900 }
901 
902 /** change one coefficient in the quadratic part of a constraint or objective
903  *
904  * input:
905  * - nlpi datastructure for solver interface
906  * - problem datastructure for problem instance
907  * - idx index of constraint or -1 for objective
908  * - nquadelems number of entries in quadratic matrix to change
909  * - quadelems new elements in quadratic matrix (replacing already existing ones or adding new ones)
910  *
911  * return: Error if coefficient did not exist before
912  */
913 static
914 SCIP_DECL_NLPICHGQUADCOEFS(nlpiChgQuadraticCoefsIpopt)
915 {
916  assert(nlpi != NULL);
917  assert(problem != NULL);
918  assert(problem->oracle != NULL);
919 
920  SCIP_CALL( SCIPnlpiOracleChgQuadCoefs(problem->oracle, idx, nquadelems, quadelems) );
921  invalidateSolution(problem);
922 
923  return SCIP_OKAY;
924 }
925 
926 /** replaces the expression tree of a constraint or objective
927  *
928  * input:
929  * - nlpi datastructure for solver interface
930  * - problem datastructure for problem instance
931  * - idxcons index of constraint or -1 for objective
932  * - exprtree new expression tree for constraint or objective, or NULL to only remove previous tree
933  */
934 static
935 SCIP_DECL_NLPICHGEXPRTREE(nlpiChgExprtreeIpopt)
936 {
937  assert(nlpi != NULL);
938  assert(problem != NULL);
939  assert(problem->oracle != NULL);
940 
941  SCIP_CALL( SCIPnlpiOracleChgExprtree(problem->oracle, idxcons, exprvaridxs, exprtree) );
942  invalidateSolution(problem);
943 
944  return SCIP_OKAY;
945 }
946 
947 /** change the value of one parameter in the nonlinear part
948  *
949  * input:
950  * - nlpi datastructure for solver interface
951  * - problem datastructure for problem instance
952  * - idxcons index of constraint or -1 for objective
953  * - idxparam index of parameter
954  * - value new value for nonlinear parameter
955  *
956  * return: Error if parameter does not exist
957  */
958 static
959 SCIP_DECL_NLPICHGNONLINCOEF(nlpiChgNonlinCoefIpopt)
960 {
961  assert(nlpi != NULL);
962  assert(problem != NULL);
963  assert(problem->oracle != NULL);
964 
965  SCIP_CALL( SCIPnlpiOracleChgExprParam(problem->oracle, idxcons, idxparam, value) );
966  invalidateSolution(problem);
967 
968  return SCIP_OKAY;
969 }
970 
971 /** change the constant offset in the objective
972  *
973  * input:
974  * - nlpi datastructure for solver interface
975  * - problem datastructure for problem instance
976  * - objconstant new value for objective constant
977  */
978 static
979 SCIP_DECL_NLPICHGOBJCONSTANT( nlpiChgObjConstantIpopt )
980 {
981  assert(nlpi != NULL);
982  assert(problem != NULL);
983  assert(problem->oracle != NULL);
984 
985  SCIP_CALL( SCIPnlpiOracleChgObjConstant(problem->oracle, objconstant) );
986 
987  return SCIP_OKAY;
988 }
989 
990 /** sets initial guess for primal variables
991  *
992  * input:
993  * - nlpi datastructure for solver interface
994  * - problem datastructure for problem instance
995  * - primalvalues initial primal values for variables, or NULL to clear previous values
996  * - consdualvalues initial dual values for constraints, or NULL to clear previous values
997  * - varlbdualvalues initial dual values for variable lower bounds, or NULL to clear previous values
998  * - varubdualvalues initial dual values for variable upper bounds, or NULL to clear previous values
999  */
1000 static
1001 SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessIpopt)
1002 {
1003  assert(nlpi != NULL);
1004  assert(problem != NULL);
1005  assert(problem->oracle != NULL);
1006 
1007  if( primalvalues != NULL )
1008  {
1009  if( !problem->initguess )
1010  {
1011  if( BMSduplicateMemoryArray(&problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle)) == NULL )
1012  return SCIP_NOMEMORY;
1013  }
1014  else
1015  {
1016  BMScopyMemoryArray(problem->initguess, primalvalues, SCIPnlpiOracleGetNVars(problem->oracle));
1017  }
1018  }
1019  else
1020  {
1021  BMSfreeMemoryArrayNull(&problem->initguess);
1022  }
1023 
1024  return SCIP_OKAY;
1025 }
1026 
1027 /** tries to solve NLP
1028  *
1029  * input:
1030  * - nlpi datastructure for solver interface
1031  * - problem datastructure for problem instance
1032  */
1033 static
1034 SCIP_DECL_NLPISOLVE(nlpiSolveIpopt)
1035 {
1036  ApplicationReturnStatus status;
1037 
1038  assert(nlpi != NULL);
1039  assert(problem != NULL);
1040  assert(problem->oracle != NULL);
1041 
1042  assert(IsValid(problem->ipopt));
1043  assert(IsValid(problem->nlp));
1044 
1045  problem->nlp->setNLPIPROBLEM(problem);
1046 
1047  problem->lastniter = -1;
1048  problem->lasttime = -1.0;
1049  problem->lastsolinfeas = SCIP_INVALID;
1050 
1051  try
1052  {
1053  SmartPtr<SolveStatistics> stats;
1054 
1055  if( problem->firstrun )
1056  {
1058 
1059  cap = SCIPexprintGetCapability() & SCIPnlpiOracleGetEvalCapability(problem->oracle);
1060 
1061  /* 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,
1062  * change NLP parameters or give an error
1063  */
1065  && SCIPnlpiOracleGetMaxDegree(problem->oracle) > 2 )
1066  {
1067  /* @todo could enable Jacobian approximation in Ipopt */
1070  {
1071  SCIPerrorMessage("Do not have expression interpreter that can compute function values and gradients. Cannot solve NLP with Ipopt.\n");
1072  problem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
1073  problem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
1074  return SCIP_OKAY;
1075  }
1076 
1077  /* enable Hessian approximation if we are nonquadratic and the expression interpreter or user expression do not support Hessians */
1078  if( !(cap & SCIP_EXPRINTCAPABILITY_HESSIAN) )
1079  {
1080  problem->ipopt->Options()->SetStringValue("hessian_approximation", "limited-memory");
1081  problem->nlp->approxhessian = true;
1082  }
1083  else
1084  problem->nlp->approxhessian = false;
1085  }
1086 
1087  status = problem->ipopt->OptimizeTNLP(GetRawPtr(problem->nlp));
1088  }
1089  else
1090  {
1091  /* ReOptimizeNLP with Ipopt <= 3.10.3 could return a solution not within bounds if all variables are fixed (see Ipopt ticket #179) */
1092 #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)
1093  status = problem->ipopt->ReOptimizeTNLP(GetRawPtr(problem->nlp));
1094 #else
1095  status = problem->ipopt->OptimizeTNLP(GetRawPtr(problem->nlp));
1096 #endif
1097  }
1098 
1099  // catch the very bad status codes
1100  switch( status ) {
1101  case Invalid_Problem_Definition:
1102  case Invalid_Option:
1103  case Unrecoverable_Exception:
1104  case NonIpopt_Exception_Thrown:
1105  case Internal_Error:
1106  SCIPerrorMessage("Ipopt returned with application return status %d\n", status);
1107  return SCIP_ERROR;
1108  case Insufficient_Memory:
1109  SCIPerrorMessage("Ipopt returned with status \"Insufficient Memory\"\n");
1110  return SCIP_NOMEMORY;
1111  case Invalid_Number_Detected:
1112  SCIPdebugMessage("Ipopt failed because of an invalid number in function or derivative value\n");
1113  invalidateSolution(problem);
1114  problem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
1115  problem->lasttermstat = SCIP_NLPTERMSTAT_EVALERR;
1116  default: ;
1117  }
1118 
1119  stats = problem->ipopt->Statistics();
1120  if( IsValid(stats) )
1121  {
1122  problem->lastniter = stats->IterationCount();
1123  problem->lasttime = stats->TotalCPUTime();
1124  }
1125  }
1126  catch( IpoptException except )
1127  {
1128  SCIPerrorMessage("Ipopt returned with exception: %s\n", except.Message().c_str());
1129  return SCIP_ERROR;
1130  }
1131 
1132  problem->firstrun = FALSE;
1133 
1134  return SCIP_OKAY;
1135 }
1136 
1137 /** gives solution status
1138  *
1139  * input:
1140  * - nlpi datastructure for solver interface
1141  * - problem datastructure for problem instance
1142  *
1143  * return: Solution Status
1144  */
1145 static
1146 SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatIpopt)
1147 {
1148  assert(nlpi != NULL);
1149  assert(problem != NULL);
1150 
1151  return problem->lastsolstat;
1152 }
1153 
1154 /** gives termination reason
1155  *
1156  * input:
1157  * - nlpi datastructure for solver interface
1158  * - problem datastructure for problem instance
1159  *
1160  * return: Termination Status
1161  */
1162 static
1163 SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatIpopt)
1164 {
1165  assert(nlpi != NULL);
1166  assert(problem != NULL);
1167 
1168  return problem->lasttermstat;
1169 }
1170 
1171 /** gives primal and dual solution values
1172  *
1173  * input:
1174  * - nlpi datastructure for solver interface
1175  * - problem datastructure for problem instance
1176  * - primalvalues buffer to store pointer to array to primal values, or NULL if not needed
1177  * - consdualvalues buffer to store pointer to array to dual values of constraints, or NULL if not needed
1178  * - varlbdualvalues buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed
1179  * - varubdualvalues buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed
1180  */
1181 static
1182 SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionIpopt)
1183 {
1184  assert(nlpi != NULL);
1185  assert(problem != NULL);
1186 
1187  if( primalvalues != NULL )
1188  *primalvalues = problem->lastsolprimals;
1189 
1190  if( consdualvalues != NULL )
1191  *consdualvalues = problem->lastsoldualcons;
1192 
1193  if( varlbdualvalues != NULL )
1194  *varlbdualvalues = problem->lastsoldualvarlb;
1195 
1196  if( varubdualvalues != NULL )
1197  *varubdualvalues = problem->lastsoldualvarub;
1198 
1199  return SCIP_OKAY;
1200 }
1201 
1202 /** gives solve statistics
1203  *
1204  * input:
1205  * - nlpi datastructure for solver interface
1206  * - problem datastructure for problem instance
1207  * - statistics pointer to store statistics
1208  *
1209  * output:
1210  * - statistics solve statistics
1211  */
1212 static
1213 SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsIpopt)
1214 {
1215  assert(nlpi != NULL);
1216  assert(problem != NULL);
1217 
1218  SCIPnlpStatisticsSetNIterations(statistics, problem->lastniter);
1219  SCIPnlpStatisticsSetTotalTime (statistics, problem->lasttime);
1220 
1221  return SCIP_OKAY;
1222 }
1223 
1224 /** gives required size of a buffer to store a warmstart object
1225  *
1226  * input:
1227  * - nlpi datastructure for solver interface
1228  * - problem datastructure for problem instance
1229  * - size pointer to store required size for warmstart buffer
1230  *
1231  * output:
1232  * - size required size for warmstart buffer
1233  */
1234 static
1235 SCIP_DECL_NLPIGETWARMSTARTSIZE(nlpiGetWarmstartSizeIpopt)
1236 {
1237  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1238  return SCIP_ERROR;
1239 }
1240 
1241 /** stores warmstart information in buffer
1242  *
1243  * Required size of buffer should have been obtained by SCIPnlpiGetWarmstartSize before.
1244  *
1245  * input:
1246  * - nlpi datastructure for solver interface
1247  * - problem datastructure for problem instance
1248  * - buffer memory to store warmstart information
1249  *
1250  * output:
1251  * - buffer warmstart information in solver specific data structure
1252  */
1253 static
1254 SCIP_DECL_NLPIGETWARMSTARTMEMO(nlpiGetWarmstartMemoIpopt)
1255 {
1256  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1257  return SCIP_ERROR;
1258 }
1259 
1260 /** sets warmstart information in solver
1261  *
1262  * Write warmstart to buffer.
1263  *
1264  * input:
1265  * - nlpi datastructure for solver interface
1266  * - problem datastructure for problem instance
1267  * - buffer warmstart information
1268  */
1269 static
1270 SCIP_DECL_NLPISETWARMSTARTMEMO(nlpiSetWarmstartMemoIpopt)
1271 {
1272  SCIPerrorMessage("method of Ipopt nonlinear solver is not implemented\n");
1273  SCIPABORT();
1274  return SCIP_OKAY;
1275 }
1276 
1277 /** gets integer parameter of NLP
1278  *
1279  * input:
1280  * - nlpi datastructure for solver interface
1281  * - problem datastructure for problem instance
1282  * - type parameter number
1283  * - ival pointer to store the parameter value
1284  *
1285  * output:
1286  * - ival parameter value
1287  */
1288 static
1289 SCIP_DECL_NLPIGETINTPAR(nlpiGetIntParIpopt)
1290 {
1291  assert(nlpi != NULL);
1292  assert(ival != NULL);
1293  assert(problem != NULL);
1294  assert(IsValid(problem->ipopt));
1295 
1296  //@TODO try-catch block for Ipopt exceptions
1297  switch( type )
1298  {
1300  {
1301  *ival = 1;
1302  break;
1303  }
1304 
1305  case SCIP_NLPPAR_VERBLEVEL:
1306  {
1307  int printlevel;
1308  problem->ipopt->Options()->GetIntegerValue("print_level", printlevel, "");
1309  if( printlevel <= J_STRONGWARNING )
1310  *ival = 0;
1311  else if( printlevel >= J_DETAILED )
1312  *ival = printlevel - J_ITERSUMMARY + 1;
1313  else /* J_SUMMARY or J_WARNING or J_ITERSUMMARY */
1314  *ival = 1;
1315  break;
1316  }
1317 
1318  case SCIP_NLPPAR_FEASTOL:
1319  {
1320  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1321  return SCIP_PARAMETERWRONGTYPE;
1322  }
1323 
1324  case SCIP_NLPPAR_RELOBJTOL:
1325  {
1326  SCIPerrorMessage("relative objective tolerance parameter is of type real.\n");
1327  return SCIP_PARAMETERWRONGTYPE;
1328  }
1329 
1330  case SCIP_NLPPAR_LOBJLIM:
1331  {
1332  SCIPerrorMessage("objective limit parameter is of type real.\n");
1333  return SCIP_PARAMETERWRONGTYPE;
1334  }
1335 
1336  case SCIP_NLPPAR_INFINITY:
1337  {
1338  SCIPerrorMessage("infinity parameter is of type real.\n");
1339  return SCIP_PARAMETERWRONGTYPE;
1340  }
1341 
1342  case SCIP_NLPPAR_ITLIM:
1343  {
1344  problem->ipopt->Options()->GetIntegerValue("max_iter", *ival, "");
1345  break;
1346  }
1347 
1348  case SCIP_NLPPAR_TILIM:
1349  {
1350  SCIPerrorMessage("time limit parameter is of type real.\n");
1351  return SCIP_PARAMETERWRONGTYPE;
1352  }
1353 
1354  case SCIP_NLPPAR_OPTFILE:
1355  {
1356  SCIPerrorMessage("optfile parameter is of type string.\n");
1357  return SCIP_PARAMETERWRONGTYPE;
1358  }
1359 
1360  case SCIP_NLPPAR_FASTFAIL:
1361  {
1362  *ival = problem->fastfail ? 1 : 0;
1363  break;
1364  }
1365 
1366  default:
1367  {
1368  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1369  return SCIP_PARAMETERUNKNOWN;
1370  }
1371  }
1372 
1373  return SCIP_OKAY;
1374 }
1375 
1376 /** sets integer parameter of NLP
1377  *
1378  * input:
1379  * - nlpi datastructure for solver interface
1380  * - problem datastructure for problem instance
1381  * - type parameter number
1382  * - ival parameter value
1383  */
1384 static
1385 SCIP_DECL_NLPISETINTPAR(nlpiSetIntParIpopt)
1386 {
1387  assert(nlpi != NULL);
1388  assert(problem != NULL);
1389  assert(IsValid(problem->ipopt));
1390 
1391  switch( type )
1392  {
1394  {
1395  if( ival == 0 || ival == 1 )
1396  {
1397  SCIP_NLPIDATA* data;
1398 
1399  data = SCIPnlpiGetData(nlpi);
1400  assert(data != NULL);
1401 
1402  SCIPmessagePrintWarning(data->messagehdlr, "from scratch parameter not supported by Ipopt interface yet. Ignored.\n");
1403  }
1404  else
1405  {
1406  SCIPerrorMessage("Value %d for parameter from scratch out of range {0, 1}\n", ival);
1407  return SCIP_PARAMETERWRONGVAL;
1408  }
1409  break;
1410  }
1411 
1412  case SCIP_NLPPAR_VERBLEVEL:
1413  {
1414  switch( ival )
1415  {
1416  case 0:
1417  problem->ipopt->Options()->SetIntegerValue("print_level", J_STRONGWARNING);
1418  break;
1419  case 1:
1420  problem->ipopt->Options()->SetIntegerValue("print_level", J_ITERSUMMARY);
1421  break;
1422  case 2:
1423  problem->ipopt->Options()->SetIntegerValue("print_level", J_DETAILED);
1424  break;
1425  default:
1426  if( ival > 2 )
1427  {
1428  problem->ipopt->Options()->SetIntegerValue("print_level", MIN(J_ITERSUMMARY + (ival-1), J_ALL));
1429  break;
1430  }
1431  else
1432  {
1433  SCIPerrorMessage("Value %d for parameter from verbosity level out of range {0, 1, 2}\n", ival);
1434  return SCIP_PARAMETERWRONGVAL;
1435  }
1436  }
1437  break;
1438  }
1439 
1440  case SCIP_NLPPAR_FEASTOL:
1441  {
1442  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1443  return SCIP_PARAMETERWRONGTYPE;
1444  }
1445 
1446  case SCIP_NLPPAR_RELOBJTOL:
1447  {
1448  SCIPerrorMessage("relative objective tolerance parameter is of type real.\n");
1449  return SCIP_PARAMETERWRONGTYPE;
1450  }
1451 
1452  case SCIP_NLPPAR_LOBJLIM:
1453  {
1454  SCIPerrorMessage("objective limit parameter is of type real.\n");
1455  return SCIP_PARAMETERWRONGTYPE;
1456  }
1457 
1458  case SCIP_NLPPAR_INFINITY:
1459  {
1460  SCIPerrorMessage("infinity parameter is of type real.\n");
1461  return SCIP_PARAMETERWRONGTYPE;
1462  }
1463 
1464  case SCIP_NLPPAR_ITLIM:
1465  {
1466  if( ival >= 0 )
1467  {
1468  problem->ipopt->Options()->SetIntegerValue("max_iter", ival);
1469  }
1470  else
1471  {
1472  SCIPerrorMessage("Value %d for parameter iteration limit is negative\n", ival);
1473  return SCIP_PARAMETERWRONGVAL;
1474  }
1475  break;
1476  }
1477 
1478  case SCIP_NLPPAR_TILIM:
1479  {
1480  SCIPerrorMessage("time limit parameter is of type real.\n");
1481  return SCIP_PARAMETERWRONGTYPE;
1482  }
1483 
1484  case SCIP_NLPPAR_OPTFILE:
1485  {
1486  SCIPerrorMessage("optfile parameter is of type string.\n");
1487  return SCIP_PARAMETERWRONGTYPE;
1488  }
1489 
1490  case SCIP_NLPPAR_FASTFAIL:
1491  {
1492  if( ival == 0 || ival == 1 )
1493  {
1494  problem->fastfail = (bool)ival;
1495  problem->storeintermediate = (bool)ival;
1496  }
1497  else
1498  {
1499  SCIPerrorMessage("Value %d for parameter fastfail out of range {0, 1}\n", ival);
1500  return SCIP_PARAMETERWRONGVAL;
1501  }
1502  break;
1503  }
1504 
1505  default:
1506  {
1507  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1508  return SCIP_PARAMETERUNKNOWN;
1509  }
1510  }
1511 
1512  return SCIP_OKAY;
1513 }
1514 
1515 /** gets floating point parameter of NLP
1516  *
1517  * input:
1518  * - nlpi datastructure for solver interface
1519  * - problem datastructure for problem instance, can be NULL only if type == SCIP_NLPPAR_INFINITY
1520  * - type parameter number
1521  * - dval pointer to store the parameter value
1522  *
1523  * output:
1524  * - dval parameter value
1525  */
1526 static
1527 SCIP_DECL_NLPIGETREALPAR(nlpiGetRealParIpopt)
1528 {
1529  assert(nlpi != NULL);
1530  assert(dval != NULL);
1531  assert(type == SCIP_NLPPAR_INFINITY || problem != NULL);
1532  assert(type == SCIP_NLPPAR_INFINITY || IsValid(problem->ipopt));
1533 
1534  switch( type )
1535  {
1537  {
1538  SCIPerrorMessage("from scratch parameter is of type int.\n");
1539  return SCIP_PARAMETERWRONGTYPE;
1540  }
1541 
1542  case SCIP_NLPPAR_VERBLEVEL:
1543  {
1544  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1545  return SCIP_PARAMETERWRONGTYPE;
1546  }
1547 
1548  case SCIP_NLPPAR_FEASTOL:
1549  {
1550  problem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", *dval, "");
1551  break;
1552  }
1553 
1554  case SCIP_NLPPAR_RELOBJTOL:
1555  {
1556  problem->ipopt->Options()->GetNumericValue("dual_inf_tol", *dval, "");
1557  break;
1558  }
1559 
1560  case SCIP_NLPPAR_LOBJLIM:
1561  {
1562  *dval = -SCIPnlpiOracleGetInfinity(problem->oracle);
1563  break;
1564  }
1565 
1566  case SCIP_NLPPAR_INFINITY:
1567  {
1568  if( problem )
1569  {
1570  *dval = SCIPnlpiOracleGetInfinity(problem->oracle);
1571  }
1572  else
1573  {
1574  SCIP_NLPIDATA* data = SCIPnlpiGetData(nlpi);
1575  assert(data != NULL);
1576  *dval = data->infinity;
1577  }
1578  break;
1579  }
1580 
1581  case SCIP_NLPPAR_ITLIM:
1582  {
1583  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1584  return SCIP_PARAMETERWRONGTYPE;
1585  }
1586 
1587  case SCIP_NLPPAR_TILIM:
1588  {
1589  problem->ipopt->Options()->GetNumericValue("max_cpu_time", *dval, "");
1590  break;
1591  }
1592 
1593  case SCIP_NLPPAR_OPTFILE:
1594  {
1595  SCIPerrorMessage("option file parameter is of type string.\n");
1596  return SCIP_PARAMETERWRONGTYPE;
1597  }
1598 
1599  case SCIP_NLPPAR_FASTFAIL:
1600  {
1601  SCIPerrorMessage("fastfail parameter is of type int.\n");
1602  return SCIP_PARAMETERWRONGTYPE;
1603  }
1604 
1605  default:
1606  {
1607  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1608  return SCIP_PARAMETERUNKNOWN;
1609  }
1610  }
1611 
1612  return SCIP_OKAY;
1613 }
1614 
1615 /** sets floating point parameter of NLP
1616  *
1617  * input:
1618  * - nlpi datastructure for solver interface
1619  * - problem datastructure for problem instance, can be NULL only if type == SCIP_NLPPAR_INFINITY
1620  * - type parameter number
1621  * - dval parameter value
1622  */
1623 static
1624 SCIP_DECL_NLPISETREALPAR(nlpiSetRealParIpopt)
1625 {
1626  assert(nlpi != NULL);
1627  assert(type == SCIP_NLPPAR_INFINITY || problem != NULL);
1628  assert(type == SCIP_NLPPAR_INFINITY || IsValid(problem->ipopt));
1629 
1630  switch( type )
1631  {
1633  {
1634  SCIPerrorMessage("from scratch parameter is of type int.\n");
1635  return SCIP_PARAMETERWRONGTYPE;
1636  }
1637 
1638  case SCIP_NLPPAR_VERBLEVEL:
1639  {
1640  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1641  return SCIP_PARAMETERWRONGTYPE;
1642  }
1643 
1644  case SCIP_NLPPAR_FEASTOL:
1645  {
1646  if( dval >= 0 )
1647  {
1648  setFeastol(problem, dval);
1649  }
1650  else
1651  {
1652  SCIPerrorMessage("Value %g for parameter feasibility tolerance is negative\n", dval);
1653  return SCIP_PARAMETERWRONGVAL;
1654  }
1655  break;
1656  }
1657 
1658  case SCIP_NLPPAR_RELOBJTOL:
1659  {
1660  if( dval >= 0 )
1661  {
1662  problem->ipopt->Options()->SetNumericValue("dual_inf_tol", dval);
1663  }
1664  else
1665  {
1666  SCIPerrorMessage("Value %g for parameter relative objective tolerance is negative\n", dval);
1667  return SCIP_PARAMETERWRONGVAL;
1668  }
1669  break;
1670  }
1671 
1672  case SCIP_NLPPAR_LOBJLIM:
1673  {
1674  SCIP_NLPIDATA* data;
1675 
1676  data = SCIPnlpiGetData(nlpi);
1677  assert(data != NULL);
1678 
1679  SCIPmessagePrintWarning(data->messagehdlr, "Parameter lower objective limit not supported by Ipopt interface yet. Ignored.\n");
1680  break;
1681  }
1682 
1683  case SCIP_NLPPAR_INFINITY:
1684  {
1685  if( dval < 0.0 )
1686  return SCIP_PARAMETERWRONGVAL;
1687  if( problem )
1688  {
1689  problem->ipopt->Options()->SetNumericValue("diverging_iterates_tol", dval);
1690  problem->ipopt->Options()->SetNumericValue("nlp_lower_bound_inf", -dval);
1691  problem->ipopt->Options()->SetNumericValue("nlp_upper_bound_inf", dval);
1692  SCIPnlpiOracleSetInfinity(problem->oracle, dval);
1693  }
1694  else
1695  {
1696  SCIP_NLPIDATA* data = SCIPnlpiGetData(nlpi);
1697  assert(data != NULL);
1698  data->infinity = dval;
1699  }
1700  break;
1701  }
1702 
1703  case SCIP_NLPPAR_ITLIM:
1704  {
1705  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1706  return SCIP_PARAMETERWRONGTYPE;
1707  }
1708 
1709  case SCIP_NLPPAR_TILIM:
1710  {
1711  if( dval >= 0 )
1712  {
1713  problem->ipopt->Options()->SetNumericValue("max_cpu_time", dval);
1714  }
1715  else
1716  {
1717  SCIPerrorMessage("Value %g for parameter time limit is negative\n", dval);
1718  return SCIP_PARAMETERWRONGVAL;
1719  }
1720  break;
1721  }
1722 
1723  case SCIP_NLPPAR_OPTFILE:
1724  {
1725  SCIPerrorMessage("option file parameter is of type string.\n");
1726  return SCIP_PARAMETERWRONGTYPE;
1727  }
1728 
1729  case SCIP_NLPPAR_FASTFAIL:
1730  {
1731  SCIPerrorMessage("fastfail parameter is of type int.\n");
1732  return SCIP_PARAMETERWRONGTYPE;
1733  }
1734 
1735  default:
1736  {
1737  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1738  return SCIP_PARAMETERUNKNOWN;
1739  }
1740  }
1741 
1742  return SCIP_OKAY;
1743 }
1744 
1745 /** gets string parameter of NLP
1746  *
1747  * input:
1748  * - nlpi NLP interface structure
1749  * - problem datastructure for problem instance
1750  * - type parameter number
1751  * - sval pointer to store the string value, the user must not modify the string
1752  *
1753  * output:
1754  * - sval parameter value
1755  */
1756 static
1757 SCIP_DECL_NLPIGETSTRINGPAR( nlpiGetStringParIpopt )
1758 {
1759  assert(nlpi != NULL);
1760  assert(problem != NULL);
1761 
1762  switch( type )
1763  {
1765  {
1766  SCIPerrorMessage("from scratch parameter is of type int.\n");
1767  return SCIP_PARAMETERWRONGTYPE;
1768  }
1769 
1770  case SCIP_NLPPAR_VERBLEVEL:
1771  {
1772  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1773  return SCIP_PARAMETERWRONGTYPE;
1774  }
1775 
1776  case SCIP_NLPPAR_FEASTOL:
1777  {
1778  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1779  return SCIP_PARAMETERWRONGTYPE;
1780  }
1781 
1782  case SCIP_NLPPAR_RELOBJTOL:
1783  {
1784  SCIPerrorMessage("objective tolerance parameter is of type real.\n");
1785  return SCIP_PARAMETERWRONGTYPE;
1786  }
1787 
1788  case SCIP_NLPPAR_LOBJLIM:
1789  {
1790  SCIPerrorMessage("objective limit parameter is of type real.\n");
1791  return SCIP_PARAMETERWRONGTYPE;
1792  }
1793 
1794  case SCIP_NLPPAR_INFINITY:
1795  {
1796  SCIPerrorMessage("infinity parameter is of type real.\n");
1797  return SCIP_PARAMETERWRONGTYPE;
1798  }
1799 
1800  case SCIP_NLPPAR_ITLIM:
1801  {
1802  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1803  return SCIP_PARAMETERWRONGTYPE;
1804  }
1805 
1806  case SCIP_NLPPAR_TILIM:
1807  {
1808  SCIPerrorMessage("time limit parameter is of type real.\n");
1809  return SCIP_PARAMETERWRONGTYPE;
1810  }
1811 
1812  case SCIP_NLPPAR_OPTFILE:
1813  {
1814  if( !problem->optfile.empty() )
1815  *sval = problem->optfile.c_str();
1816  else
1817  *sval = NULL;
1818  return SCIP_OKAY;
1819  }
1820 
1821  case SCIP_NLPPAR_FASTFAIL:
1822  {
1823  SCIPerrorMessage("fastfail parameter is of type int.\n");
1824  return SCIP_PARAMETERWRONGTYPE;
1825  }
1826 
1827  default:
1828  {
1829  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1830  return SCIP_PARAMETERUNKNOWN;
1831  }
1832  }
1833 
1834  return SCIP_OKAY;
1835 }
1836 
1837 /** sets string parameter of NLP
1838  *
1839  * input:
1840  * - nlpi NLP interface structure
1841  * - problem datastructure for problem instance
1842  * - type parameter number
1843  * - sval parameter value
1844  */
1845 static
1846 SCIP_DECL_NLPISETSTRINGPAR( nlpiSetStringParIpopt )
1847 {
1848  assert(nlpi != NULL);
1849  assert(problem != NULL);
1850 
1851  switch( type )
1852  {
1854  {
1855  SCIPerrorMessage("from scratch parameter is of type int.\n");
1856  return SCIP_PARAMETERWRONGTYPE;
1857  }
1858 
1859  case SCIP_NLPPAR_VERBLEVEL:
1860  {
1861  SCIPerrorMessage("verbosity level parameter is of type int.\n");
1862  return SCIP_PARAMETERWRONGTYPE;
1863  }
1864 
1865  case SCIP_NLPPAR_FEASTOL:
1866  {
1867  SCIPerrorMessage("feasibility tolerance parameter is of type real.\n");
1868  return SCIP_PARAMETERWRONGTYPE;
1869  }
1870 
1871  case SCIP_NLPPAR_RELOBJTOL:
1872  {
1873  SCIPerrorMessage("objective tolerance parameter is of type real.\n");
1874  return SCIP_PARAMETERWRONGTYPE;
1875  }
1876 
1877  case SCIP_NLPPAR_LOBJLIM:
1878  {
1879  SCIPerrorMessage("objective limit parameter is of type real.\n");
1880  return SCIP_PARAMETERWRONGTYPE;
1881  }
1882 
1883  case SCIP_NLPPAR_INFINITY:
1884  {
1885  SCIPerrorMessage("infinity parameter is of type real.\n");
1886  return SCIP_PARAMETERWRONGTYPE;
1887  }
1888 
1889  case SCIP_NLPPAR_ITLIM:
1890  {
1891  SCIPerrorMessage("iteration limit parameter is of type int.\n");
1892  return SCIP_PARAMETERWRONGTYPE;
1893  }
1894 
1895  case SCIP_NLPPAR_TILIM:
1896  {
1897  SCIPerrorMessage("time limit parameter is of type real.\n");
1898  return SCIP_PARAMETERWRONGTYPE;
1899  }
1900 
1901  case SCIP_NLPPAR_OPTFILE:
1902  {
1903  if( sval != NULL )
1904  problem->optfile = sval;
1905  else
1906  problem->optfile.clear();
1907 
1908  if( problem->ipopt->Initialize(problem->optfile) != Solve_Succeeded )
1909  {
1910  SCIPerrorMessage("Error initializing Ipopt using optionfile \"%s\"\n", problem->optfile.c_str());
1911  return SCIP_ERROR;
1912  }
1913  problem->ipopt->Options()->GetBoolValue("store_intermediate", problem->storeintermediate, "");
1914  problem->firstrun = TRUE;
1915 
1916  return SCIP_OKAY;
1917  }
1918 
1919  case SCIP_NLPPAR_FASTFAIL:
1920  {
1921  SCIPerrorMessage("fastfail parameter is of type int.\n");
1922  return SCIP_PARAMETERWRONGTYPE;
1923  }
1924 
1925  default:
1926  {
1927  SCIPerrorMessage("Parameter %d not known to Ipopt interface.\n", type);
1928  return SCIP_PARAMETERUNKNOWN;
1929  }
1930  }
1931 
1932  return SCIP_OKAY;
1933 }
1934 
1935 /** sets message handler for message output
1936  *
1937  * input:
1938  * - nlpi NLP interface structure
1939  * - messagehdlr SCIP message handler, or NULL to suppress all output
1940  */
1941 static
1942 SCIP_DECL_NLPISETMESSAGEHDLR( nlpiSetMessageHdlrIpopt )
1943 {
1944  SCIP_NLPIDATA* nlpidata;
1945 
1946  assert(nlpi != NULL);
1947 
1948  nlpidata = SCIPnlpiGetData(nlpi);
1949  assert(nlpidata != NULL);
1950 
1951  nlpidata->messagehdlr = messagehdlr;
1952 
1953  return SCIP_OKAY; /*lint !e527*/
1954 } /*lint !e715*/
1955 
1956 /** create solver interface for Ipopt solver */
1958  BMS_BLKMEM* blkmem, /**< block memory data structure */
1959  SCIP_NLPI** nlpi /**< pointer to buffer for nlpi address */
1960  )
1961 {
1962  SCIP_NLPIDATA* nlpidata;
1963 
1964  assert(blkmem != NULL);
1965  assert(nlpi != NULL);
1966 
1967  SCIP_ALLOC( nlpidata = new SCIP_NLPIDATA(blkmem) );
1968 
1969  SCIP_CALL( SCIPnlpiCreate(nlpi,
1971  nlpiCopyIpopt, nlpiFreeIpopt, nlpiGetSolverPointerIpopt,
1972  nlpiCreateProblemIpopt, nlpiFreeProblemIpopt, nlpiGetProblemPointerIpopt,
1973  nlpiAddVarsIpopt, nlpiAddConstraintsIpopt, nlpiSetObjectiveIpopt,
1974  nlpiChgVarBoundsIpopt, nlpiChgConsSidesIpopt, nlpiDelVarSetIpopt, nlpiDelConstraintSetIpopt,
1975  nlpiChgLinearCoefsIpopt, nlpiChgQuadraticCoefsIpopt, nlpiChgExprtreeIpopt, nlpiChgNonlinCoefIpopt,
1976  nlpiChgObjConstantIpopt, nlpiSetInitialGuessIpopt, nlpiSolveIpopt, nlpiGetSolstatIpopt, nlpiGetTermstatIpopt,
1977  nlpiGetSolutionIpopt, nlpiGetStatisticsIpopt,
1978  nlpiGetWarmstartSizeIpopt, nlpiGetWarmstartMemoIpopt, nlpiSetWarmstartMemoIpopt,
1979  nlpiGetIntParIpopt, nlpiSetIntParIpopt, nlpiGetRealParIpopt, nlpiSetRealParIpopt,
1980  nlpiGetStringParIpopt, nlpiSetStringParIpopt, nlpiSetMessageHdlrIpopt,
1981  nlpidata) );
1982 
1983  return SCIP_OKAY;
1984 }
1985 
1986 /** gets string that identifies Ipopt (version number) */
1987 const char* SCIPgetSolverNameIpopt(void)
1988 {
1989  return "Ipopt " IPOPT_VERSION;
1990 }
1991 
1992 /** gets string that describes Ipopt (version number) */
1993 const char* SCIPgetSolverDescIpopt(void)
1994 {
1995  return "Interior Point Optimizer developed by A. Waechter et.al. (www.coin-or.org/Ipopt)";
1996 }
1997 
1998 /** returns whether Ipopt is available, i.e., whether it has been linked in */
2000 {
2001  return TRUE;
2002 }
2003 
2004 /** gives a pointer to the IpoptApplication object stored in Ipopt-NLPI's NLPI problem data structure */
2006  SCIP_NLPIPROBLEM* nlpiproblem /**< NLP problem of Ipopt-NLPI */
2007  )
2008 {
2009  assert(nlpiproblem != NULL);
2010 
2011  return (void*)GetRawPtr(nlpiproblem->ipopt);
2012 }
2013 
2014 /** gives a pointer to the NLPIORACLE object stored in Ipopt-NLPI's NLPI problem data structure */
2016  SCIP_NLPIPROBLEM* nlpiproblem /**< NLP problem of Ipopt-NLPI */
2017  )
2018 {
2019  assert(nlpiproblem != NULL);
2020 
2021  return nlpiproblem->oracle;
2022 }
2023 
2024 /** sets modified default settings that are used when setting up an Ipopt problem
2025  *
2026  * Do not forget to add a newline after the last option in optionsstring.
2027  */
2029  SCIP_NLPI* nlpi, /**< Ipopt NLP interface */
2030  const char* optionsstring /**< string with options as in Ipopt options file */
2031  )
2032 {
2033  SCIP_NLPIDATA* data;
2034 
2035  assert(nlpi != NULL);
2036 
2037  data = SCIPnlpiGetData(nlpi);
2038  assert(data != NULL);
2039 
2040  data->defoptions = optionsstring;
2041 }
2042 
2043 /** Method to return some info about the nlp */
2044 bool ScipNLP::get_nlp_info(
2045  Index& n, /**< place to store number of variables */
2046  Index& m, /**< place to store number of constraints */
2047  Index& nnz_jac_g, /**< place to store number of nonzeros in jacobian */
2048  Index& nnz_h_lag, /**< place to store number of nonzeros in hessian */
2049  IndexStyleEnum& index_style /**< place to store used index style (0-based or 1-based) */
2050  )
2051 {
2052  const int* offset;
2053  SCIP_RETCODE retcode;
2054 
2055  assert(nlpiproblem != NULL);
2056  assert(nlpiproblem->oracle != NULL);
2057 
2058  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2059  m = SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle);
2060 
2061  retcode = SCIPnlpiOracleGetJacobianSparsity(nlpiproblem->oracle, &offset, NULL);
2062  if( retcode != SCIP_OKAY )
2063  return false;
2064  assert(offset != NULL);
2065  nnz_jac_g = offset[m];
2066 
2067  if( !approxhessian )
2068  {
2069  retcode = SCIPnlpiOracleGetHessianLagSparsity(nlpiproblem->oracle, &offset, NULL);
2070  if( retcode != SCIP_OKAY )
2071  return false;
2072  assert(offset != NULL);
2073  nnz_h_lag = offset[n];
2074  }
2075  else
2076  {
2077  nnz_h_lag = 0;
2078  }
2079 
2080  index_style = TNLP::C_STYLE;
2081 
2082  return true;
2083 }
2084 
2085 /** Method to return the bounds for my problem */
2086 bool ScipNLP::get_bounds_info(
2087  Index n, /**< number of variables */
2088  Number* x_l, /**< buffer to store lower bounds on variables */
2089  Number* x_u, /**< buffer to store upper bounds on variables */
2090  Index m, /**< number of constraints */
2091  Number* g_l, /**< buffer to store lower bounds on constraints */
2092  Number* g_u /**< buffer to store lower bounds on constraints */
2093  )
2094 {
2095  assert(nlpiproblem != NULL);
2096  assert(nlpiproblem->oracle != NULL);
2097 
2098  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2099  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2100 
2101  assert(SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle) != NULL);
2102  assert(SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle) != NULL);
2103 
2104  BMScopyMemoryArray(x_l, SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle), n);
2105  BMScopyMemoryArray(x_u, SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle), n);
2106 #ifndef NDEBUG
2107  for( int i = 0; i < n; ++i )
2108  assert(x_l[i] <= x_u[i]);
2109 #endif
2110 
2111  for( int i = 0; i < m; ++i )
2112  {
2113  g_l[i] = SCIPnlpiOracleGetConstraintLhs(nlpiproblem->oracle, i);
2114  g_u[i] = SCIPnlpiOracleGetConstraintRhs(nlpiproblem->oracle, i);
2115  assert(g_l[i] <= g_u[i]);
2116  }
2117 
2118  return true;
2119 }
2120 
2121 /** Method to return the starting point for the algorithm */
2122 bool ScipNLP::get_starting_point(
2123  Index n, /**< number of variables */
2124  bool init_x, /**< whether initial values for primal values are requested */
2125  Number* x, /**< buffer to store initial primal values */
2126  bool init_z, /**< whether initial values for dual values of variable bounds are requested */
2127  Number* z_L, /**< buffer to store dual values for variable lower bounds */
2128  Number* z_U, /**< buffer to store dual values for variable upper bounds */
2129  Index m, /**< number of constraints */
2130  bool init_lambda, /**< whether initial values for dual values of constraints are required */
2131  Number* lambda /**< buffer to store dual values of constraints */
2132  )
2133 {
2134  assert(nlpiproblem != NULL);
2135  assert(nlpiproblem->oracle != NULL);
2136 
2137  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2138  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2139 
2140  if( init_x )
2141  {
2142  if( nlpiproblem->initguess )
2143  {
2144  BMScopyMemoryArray(x, nlpiproblem->initguess, n);
2145  }
2146  else
2147  {
2148  SCIP_Real lb, ub;
2149  unsigned int perturbseed;
2150 
2151  SCIPdebugMessage("Ipopt started without intial primal values; make up starting guess by projecting 0 onto variable bounds\n");
2152 
2153  perturbseed = 1;
2154  for( int i = 0; i < n; ++i )
2155  {
2156  lb = SCIPnlpiOracleGetVarLbs(nlpiproblem->oracle)[i];
2157  ub = SCIPnlpiOracleGetVarUbs(nlpiproblem->oracle)[i];
2158  if( lb > 0.0 )
2159  x[i] = SCIPgetRandomReal(lb, lb + MAXPERTURB*MIN(1.0, ub-lb), &perturbseed);
2160  else if( ub < 0.0 )
2161  x[i] = SCIPgetRandomReal(ub - MAXPERTURB*MIN(1.0, ub-lb), ub, &perturbseed);
2162  else
2163  x[i] = SCIPgetRandomReal(MAX(lb, -MAXPERTURB*MIN(1.0, ub-lb)), MIN(ub, MAXPERTURB*MIN(1.0, ub-lb)), &perturbseed);
2164  }
2165  }
2166  }
2167  if( init_z || init_lambda )
2168  return false;
2169 
2170  return true;
2171 }
2172 
2173 /** Method to return the variables linearity. */
2174 bool ScipNLP::get_variables_linearity(
2175  Index n, /**< number of variables */
2176  LinearityType* var_types /**< buffer to store linearity types of variables */
2177  )
2178 {
2179  assert(nlpiproblem != NULL);
2180  assert(nlpiproblem->oracle != NULL);
2181 
2182  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2183 
2184  for( int i = 0; i < n; ++i )
2185  var_types[i] = (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) <= 1 ? LINEAR : NON_LINEAR);
2186 
2187  return true;
2188 }
2189 
2190 /** Method to return the constraint linearity. */
2191 bool ScipNLP::get_constraints_linearity(
2192  Index m, /**< number of constraints */
2193  LinearityType* const_types /**< buffer to store linearity types of constraints */
2194  )
2195 {
2196  int i;
2197 
2198  assert(nlpiproblem != NULL);
2199  assert(nlpiproblem->oracle != NULL);
2200 
2201  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2202 
2203  for( i = 0; i < m; ++i )
2204  const_types[i] = (SCIPnlpiOracleGetConstraintDegree(nlpiproblem->oracle, i) <= 1 ? LINEAR : NON_LINEAR);
2205 
2206  return true;
2207 }
2208 
2209 /** Method to return the number of nonlinear variables. */
2210 Index ScipNLP::get_number_of_nonlinear_variables()
2211 {
2212  int count;
2213  int n;
2214 
2215  assert(nlpiproblem != NULL);
2216  assert(nlpiproblem->oracle != NULL);
2217 
2218  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2219 
2220  count = 0;
2221  for( int i = 0; i < n; ++i )
2222  if (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) > 1)
2223  ++count;
2224 
2225  return count;
2226 }
2227 
2228 /** Method to return the indices of the nonlinear variables */
2229 bool ScipNLP::get_list_of_nonlinear_variables(
2230  Index num_nonlin_vars, /**< number of nonlinear variables */
2231  Index* pos_nonlin_vars /**< array to fill with indices of nonlinear variables */
2232  )
2233 {
2234  int count;
2235  int n;
2236 
2237  assert(nlpiproblem != NULL);
2238  assert(nlpiproblem->oracle != NULL);
2239 
2240  n = SCIPnlpiOracleGetNVars(nlpiproblem->oracle);
2241 
2242  count = 0;
2243  for( int i = 0; i < n; ++i )
2244  if (SCIPnlpiOracleGetVarDegree(nlpiproblem->oracle, i) > 1)
2245  {
2246  assert(count < num_nonlin_vars);
2247  pos_nonlin_vars[count++] = i;
2248  }
2249 
2250  assert(count == num_nonlin_vars);
2251 
2252  return true;
2253 }
2254 
2255 /** Method to return metadata about variables and constraints */
2256 bool ScipNLP::get_var_con_metadata(
2257  Index n, /**< number of variables */
2258  StringMetaDataMapType& var_string_md, /**< variable meta data of string type */
2259  IntegerMetaDataMapType& var_integer_md,/**< variable meta data of integer type */
2260  NumericMetaDataMapType& var_numeric_md,/**< variable meta data of numeric type */
2261  Index m, /**< number of constraints */
2262  StringMetaDataMapType& con_string_md, /**< constraint meta data of string type */
2263  IntegerMetaDataMapType& con_integer_md,/**< constraint meta data of integer type */
2264  NumericMetaDataMapType& con_numeric_md /**< constraint meta data of numeric type */
2265  )
2266 {
2267  assert(nlpiproblem != NULL);
2268  assert(nlpiproblem->oracle != NULL);
2269  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2270  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2271 
2272  char** varnames = SCIPnlpiOracleGetVarNames(nlpiproblem->oracle);
2273  if( varnames != NULL )
2274  {
2275  std::vector<std::string>& varnamesvec(var_string_md["idx_names"]);
2276  varnamesvec.reserve(n);
2277  for( int i = 0; i < n; ++i )
2278  {
2279  if( varnames[i] != NULL )
2280  {
2281  varnamesvec.push_back(varnames[i]);
2282  }
2283  else
2284  {
2285  char buffer[20];
2286  sprintf(buffer, "nlpivar%8d", i);
2287  varnamesvec.push_back(buffer);
2288  }
2289  }
2290  }
2291 
2292  std::vector<std::string>& consnamesvec(con_string_md["idx_names"]);
2293  consnamesvec.reserve(m);
2294  for( int i = 0; i < m; ++i )
2295  {
2296  if( SCIPnlpiOracleGetConstraintName(nlpiproblem->oracle, i) != NULL )
2297  {
2298  consnamesvec.push_back(SCIPnlpiOracleGetConstraintName(nlpiproblem->oracle, i));
2299  }
2300  else
2301  {
2302  char buffer[20];
2303  sprintf(buffer, "nlpicons%8d", i);
2304  consnamesvec.push_back(buffer);
2305  }
2306  }
2307 
2308  return true;
2309 }
2310 
2311 /** Method to return the objective value */
2312 bool ScipNLP::eval_f(
2313  Index n, /**< number of variables */
2314  const Number* x, /**< point to evaluate */
2315  bool new_x, /**< whether some function evaluation method has been called for this point before */
2316  Number& obj_value /**< place to store objective function value */
2317  )
2318 {
2319  assert(nlpiproblem != NULL);
2320  assert(nlpiproblem->oracle != NULL);
2321 
2322  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2323 
2324  return SCIPnlpiOracleEvalObjectiveValue(nlpiproblem->oracle, x, &obj_value) == SCIP_OKAY;
2325 }
2326 
2327 /** Method to return the gradient of the objective */
2328 bool ScipNLP::eval_grad_f(
2329  Index n, /**< number of variables */
2330  const Number* x, /**< point to evaluate */
2331  bool new_x, /**< whether some function evaluation method has been called for this point before */
2332  Number* grad_f /**< buffer to store objective gradient */
2333  )
2334 {
2335  SCIP_Real dummy;
2336 
2337  assert(nlpiproblem != NULL);
2338  assert(nlpiproblem->oracle != NULL);
2339 
2340  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2341 
2342  return SCIPnlpiOracleEvalObjectiveGradient(nlpiproblem->oracle, x, TRUE, &dummy, grad_f) == SCIP_OKAY;
2343 }
2344 
2345 /** Method to return the constraint residuals */
2346 bool ScipNLP::eval_g(
2347  Index n, /**< number of variables */
2348  const Number* x, /**< point to evaluate */
2349  bool new_x, /**< whether some function evaluation method has been called for this point before */
2350  Index m, /**< number of constraints */
2351  Number* g /**< buffer to store constraint function values */
2352  )
2353 {
2354  assert(nlpiproblem != NULL);
2355  assert(nlpiproblem->oracle != NULL);
2356 
2357  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2358 
2359  return SCIPnlpiOracleEvalConstraintValues(nlpiproblem->oracle, x, g) == SCIP_OKAY;
2360 }
2361 
2362 /** Method to return:
2363  * 1) The structure of the jacobian (if "values" is NULL)
2364  * 2) The values of the jacobian (if "values" is not NULL)
2365  */
2366 bool ScipNLP::eval_jac_g(
2367  Index n, /**< number of variables */
2368  const Number* x, /**< point to evaluate */
2369  bool new_x, /**< whether some function evaluation method has been called for this point before */
2370  Index m, /**< number of constraints */
2371  Index nele_jac, /**< number of nonzero entries in jacobian */
2372  Index* iRow, /**< buffer to store row indices of nonzero jacobian entries, or NULL if values are requested */
2373  Index* jCol, /**< buffer to store column indices of nonzero jacobian entries, or NULL if values are requested */
2374  Number* values /**< buffer to store values of nonzero jacobian entries, or NULL if structure is requested */
2375  )
2376 {
2377  assert(nlpiproblem != NULL);
2378  assert(nlpiproblem->oracle != NULL);
2379 
2380  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2381  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2382 
2383  if( values == NULL )
2384  { /* Ipopt wants to know sparsity structure */
2385  const int* jacoffset;
2386  const int* jaccol;
2387  int j;
2388  int i;
2389 
2390  assert(iRow != NULL);
2391  assert(jCol != NULL);
2392 
2393  if( SCIPnlpiOracleGetJacobianSparsity(nlpiproblem->oracle, &jacoffset, &jaccol) != SCIP_OKAY )
2394  return false;
2395 
2396  assert(jacoffset[0] == 0);
2397  assert(jacoffset[m] == nele_jac);
2398  j = jacoffset[0];
2399  for( i = 0; i < m; ++i )
2400  for( ; j < jacoffset[i+1]; ++j )
2401  iRow[j] = i;
2402 
2403  BMScopyMemoryArray(jCol, jaccol, nele_jac);
2404  }
2405  else
2406  {
2407  if( SCIPnlpiOracleEvalJacobian(nlpiproblem->oracle, x, TRUE, NULL, values) != SCIP_OKAY )
2408  return false;
2409  }
2410 
2411  return true;
2412 }
2413 
2414 /** Method to return:
2415  * 1) The structure of the hessian of the lagrangian (if "values" is NULL)
2416  * 2) The values of the hessian of the lagrangian (if "values" is not NULL)
2417  */
2418 bool ScipNLP::eval_h(
2419  Index n, /**< number of variables */
2420  const Number* x, /**< point to evaluate */
2421  bool new_x, /**< whether some function evaluation method has been called for this point before */
2422  Number obj_factor, /**< weight for objective function */
2423  Index m, /**< number of constraints */
2424  const Number* lambda, /**< weights for constraint functions */
2425  bool new_lambda, /**< whether the hessian has been evaluated for these values of lambda before */
2426  Index nele_hess, /**< number of nonzero entries in hessian */
2427  Index* iRow, /**< buffer to store row indices of nonzero hessian entries, or NULL if values are requested */
2428  Index* jCol, /**< buffer to store column indices of nonzero hessian entries, or NULL if values are requested */
2429  Number* values /**< buffer to store values of nonzero hessian entries, or NULL if structure is requested */
2430  )
2431 {
2432  assert(nlpiproblem != NULL);
2433  assert(nlpiproblem->oracle != NULL);
2434 
2435  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2436  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2437 
2438  if( values == NULL )
2439  { /* Ipopt wants to know sparsity structure */
2440  const int* heslagoffset;
2441  const int* heslagcol;
2442  int j;
2443  int i;
2444 
2445  assert(iRow != NULL);
2446  assert(jCol != NULL);
2447 
2448  if( SCIPnlpiOracleGetHessianLagSparsity(nlpiproblem->oracle, &heslagoffset, &heslagcol) != SCIP_OKAY )
2449  return false;
2450 
2451  assert(heslagoffset[0] == 0);
2452  assert(heslagoffset[n] == nele_hess);
2453  j = heslagoffset[0];
2454  for( i = 0; i < n; ++i )
2455  for( ; j < heslagoffset[i+1]; ++j )
2456  iRow[j] = i;
2457 
2458  BMScopyMemoryArray(jCol, heslagcol, nele_hess);
2459  }
2460  else
2461  {
2462  if( SCIPnlpiOracleEvalHessianLag(nlpiproblem->oracle, x, TRUE, obj_factor, lambda, values) != SCIP_OKAY )
2463  return false;
2464  }
2465 
2466  return true;
2467 }
2468 
2469 /** Method called by the solver at each iteration.
2470  *
2471  * Checks whether Ctrl-C was hit.
2472  */
2473 bool ScipNLP::intermediate_callback(
2474  AlgorithmMode mode, /**< current mode of algorithm */
2475  Index iter, /**< current iteration number */
2476  Number obj_value, /**< current objective value */
2477  Number inf_pr, /**< current primal infeasibility */
2478  Number inf_du, /**< current dual infeasibility */
2479  Number mu, /**< current barrier parameter */
2480  Number d_norm, /**< current gradient norm */
2481  Number regularization_size,/**< current size of regularization */
2482  Number alpha_du, /**< current dual alpha */
2483  Number alpha_pr, /**< current primal alpha */
2484  Index ls_trials, /**< current number of linesearch trials */
2485  const IpoptData* ip_data, /**< pointer to Ipopt Data */
2486  IpoptCalculatedQuantities* ip_cq /**< pointer to current calculated quantities */
2487  )
2488 {
2489  if( nlpiproblem->storeintermediate && mode == RegularMode && inf_pr < nlpiproblem->lastsolinfeas )
2490  {
2491  Ipopt::TNLPAdapter* tnlp_adapter;
2492 
2493  tnlp_adapter = NULL;
2494  if( ip_cq != NULL )
2495  {
2496  Ipopt::OrigIpoptNLP* orignlp;
2497 
2498  orignlp = dynamic_cast<OrigIpoptNLP*>(GetRawPtr(ip_cq->GetIpoptNLP()));
2499  if( orignlp != NULL )
2500  tnlp_adapter = dynamic_cast<TNLPAdapter*>(GetRawPtr(orignlp->nlp()));
2501  }
2502 
2503  if( tnlp_adapter != NULL && ip_data != NULL && IsValid(ip_data->curr()) )
2504  {
2505  SCIPdebugMessage("update lastsol: inf_pr old = %g -> new = %g\n", nlpiproblem->lastsolinfeas, inf_pr);
2506 
2507  if( nlpiproblem->lastsolprimals == NULL )
2508  {
2509  assert(nlpiproblem->lastsoldualcons == NULL);
2510  assert(nlpiproblem->lastsoldualvarlb == NULL);
2511  assert(nlpiproblem->lastsoldualvarub == NULL);
2512  if( BMSallocMemoryArray(&nlpiproblem->lastsolprimals, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL ||
2513  BMSallocMemoryArray(&nlpiproblem->lastsoldualcons, SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle)) == NULL ||
2514  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarlb, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL ||
2515  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarub, SCIPnlpiOracleGetNVars(nlpiproblem->oracle)) == NULL )
2516  {
2517  SCIPerrorMessage("out-of-memory in ScipNLP::intermediate_callback()\n");
2518  return TRUE;
2519  }
2520  }
2521 
2522  assert(IsValid(ip_data->curr()->x()));
2523  tnlp_adapter->ResortX(*ip_data->curr()->x(), nlpiproblem->lastsolprimals);
2524  nlpiproblem->lastsolinfeas = inf_pr;
2525 
2526  assert(IsValid(ip_data->curr()->y_c()));
2527  assert(IsValid(ip_data->curr()->y_d()));
2528  tnlp_adapter->ResortG(*ip_data->curr()->y_c(), *ip_data->curr()->y_d(), nlpiproblem->lastsoldualcons);
2529 
2530  // need to clear arrays first because ResortBnds only sets values for non-fixed variables
2531  BMSclearMemoryArray(nlpiproblem->lastsoldualvarlb, SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2532  BMSclearMemoryArray(nlpiproblem->lastsoldualvarub, SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2533  assert(IsValid(ip_data->curr()->z_L()));
2534  assert(IsValid(ip_data->curr()->z_U()));
2535  tnlp_adapter->ResortBnds(*ip_data->curr()->z_L(), nlpiproblem->lastsoldualvarlb, *ip_data->curr()->z_U(), nlpiproblem->lastsoldualvarub);
2536 
2537  }
2538  }
2539 
2540  /* do convergence test if fastfail is enabled */
2541  if( nlpiproblem->fastfail )
2542  {
2543  int i;
2544 
2545  if( iter == 0 )
2546  {
2547  conv_lastrestoiter = -1;
2548  }
2549  else if( mode == RestorationPhaseMode )
2550  {
2551  conv_lastrestoiter = iter;
2552  }
2553  else if( conv_lastrestoiter == iter-1 )
2554  {
2555  /* just switched back from restoration mode, reset dual reduction targets */
2556  for( i = 0; i < convcheck_nchecks; ++i )
2557  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2558  }
2559 
2560  if( iter == convcheck_startiter )
2561  {
2562  /* define initial targets and iteration limits */
2563  for( i = 0; i < convcheck_nchecks; ++i )
2564  {
2565  conv_prtarget[i] = convcheck_minred[i] * inf_pr;
2566  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2567  conv_iterlim[i] = iter + convcheck_maxiter[i];
2568  }
2569  }
2570  else if( iter > convcheck_startiter )
2571  {
2572  /* check if we should stop */
2573  for( i = 0; i < convcheck_nchecks; ++i )
2574  {
2575  if( inf_pr <= conv_prtarget[i] )
2576  {
2577  /* sufficient reduction w.r.t. primal infeasibility target
2578  * reset target w.r.t. current infeasibilities
2579  */
2580  conv_prtarget[i] = convcheck_minred[i] * inf_pr;
2581  conv_dutarget[i] = convcheck_minred[i] * inf_du;
2582  conv_iterlim[i] = iter + convcheck_maxiter[i];
2583  }
2584  else if( iter >= conv_iterlim[i] )
2585  {
2586  /* we hit a limit, should we really stop? */
2587  SCIPdebugMessage("convcheck %d: inf_pr = %e > target %e; inf_du = %e target %e: ",
2588  i, inf_pr, conv_prtarget[i], inf_du, conv_dutarget[i]);
2589  if( mode == RegularMode && iter <= conv_lastrestoiter + convcheck_startiter )
2590  {
2591  /* if we returned from feasibility restoration recently, we allow some more iterations,
2592  * because Ipopt may go for optimality for some iterations, at the costs of infeasibility
2593  */
2594  SCIPdebugPrintf("continue, because restoration phase only %d iters ago\n", iter - conv_lastrestoiter);
2595  }
2596  else if( mode == RegularMode && inf_du <= conv_dutarget[i] && iter < conv_iterlim[i] + convcheck_maxiter[i] )
2597  {
2598  /* if dual reduction is sufficient, we allow for twice the number of iterations to reach primal infeas reduction */
2599  SCIPdebugPrintf("continue, because dual infeas. red. sufficient and only %d iters above limit\n", iter - conv_iterlim[i]);
2600  }
2601  else
2602  {
2603  SCIPdebugPrintf("abort\n");
2604  return false;
2605  }
2606  }
2607  }
2608  }
2609  }
2610 
2611  return (SCIPinterrupted() == FALSE);
2612 }
2613 
2614 /** This method is called when the algorithm is complete so the TNLP can store/write the solution. */
2615 void ScipNLP::finalize_solution(
2616  SolverReturn status, /**< solve and solution status */
2617  Index n, /**< number of variables */
2618  const Number* x, /**< primal solution values */
2619  const Number* z_L, /**< dual values of variable lower bounds */
2620  const Number* z_U, /**< dual values of variable upper bounds */
2621  Index m, /**< number of constraints */
2622  const Number* g, /**< values of constraints */
2623  const Number* lambda, /**< dual values of constraints */
2624  Number obj_value, /**< objective function value */
2625  const IpoptData* data, /**< pointer to Ipopt Data */
2626  IpoptCalculatedQuantities* cq /**< pointer to calculated quantities */
2627  )
2628 {
2629  assert(nlpiproblem != NULL);
2630  assert(nlpiproblem->oracle != NULL);
2631 
2632  assert(n == SCIPnlpiOracleGetNVars(nlpiproblem->oracle));
2633  assert(m == SCIPnlpiOracleGetNConstraints(nlpiproblem->oracle));
2634 
2635  bool check_feasibility = false; // whether we should check x for feasibility, if not NULL
2636  switch( status )
2637  {
2638  case SUCCESS:
2639  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCOPT;
2640  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2641  assert(x != NULL);
2642  break;
2643 
2644  case STOP_AT_ACCEPTABLE_POINT:
2645  /* if stop at acceptable point, then dual infeasibility can be arbitrary large, so claim only feasibility */
2646  case FEASIBLE_POINT_FOUND:
2647  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2648  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2649  assert(x != NULL);
2650  break;
2651 
2652  case MAXITER_EXCEEDED:
2653  check_feasibility = true;
2654  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2655  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_ITLIM;
2656  break;
2657 
2658  case CPUTIME_EXCEEDED:
2659  check_feasibility = true;
2660  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2661  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_TILIM;
2662  break;
2663 
2664  case STOP_AT_TINY_STEP:
2665  case RESTORATION_FAILURE:
2666  case ERROR_IN_STEP_COMPUTATION:
2667  check_feasibility = true;
2668  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2669  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_NUMERR;
2670  break;
2671 
2672  case LOCAL_INFEASIBILITY:
2673  /* still check feasibility, since we let Ipopt solve with higher tolerance than actually required */
2674  check_feasibility = true;
2675  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2676  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2677  break;
2678 
2679  case DIVERGING_ITERATES:
2680  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNBOUNDED;
2681  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_UOBJLIM;
2682  break;
2683 
2684  case INVALID_NUMBER_DETECTED:
2685  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2686  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_EVALERR;
2687  break;
2688 
2689  case USER_REQUESTED_STOP:
2690  check_feasibility = true;
2691  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2692  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OKAY;
2693  break;
2694 
2695  case TOO_FEW_DEGREES_OF_FREEDOM:
2696  case INTERNAL_ERROR:
2697  case INVALID_OPTION:
2698  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2699  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
2700  break;
2701 
2702  case OUT_OF_MEMORY:
2703  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2704  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_MEMERR;
2705  break;
2706 
2707  default:
2708  SCIPerrorMessage("Ipopt returned with unknown solution status %d\n", status);
2709  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2710  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_OTHER;
2711  break;
2712  }
2713 
2714  /* 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 */
2715  if( (x == NULL || nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE || nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_UNKNOWN) && nlpiproblem->lastsolinfeas != SCIP_INVALID )
2716  {
2717  /* if infeasibility of lastsol is not invalid, then lastsol values should exist */
2718  assert(nlpiproblem->lastsolprimals != NULL);
2719  assert(nlpiproblem->lastsoldualcons != NULL);
2720  assert(nlpiproblem->lastsoldualvarlb != NULL);
2721  assert(nlpiproblem->lastsoldualvarub != NULL);
2722 
2723  /* check if lastsol is feasible */
2724  Number constrvioltol;
2725  nlpiproblem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", constrvioltol, "");
2726  if( nlpiproblem->lastsolinfeas <= constrvioltol )
2727  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2728  else
2729  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2730 
2731  SCIPdebugMessage("drop Ipopt's final point and report intermediate locally %sfeasible solution with infeas %g instead (acceptable: %g)\n",
2732  nlpiproblem->lastsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE ? "in" : "", nlpiproblem->lastsolinfeas, constrvioltol);
2733  }
2734  else
2735  {
2736  assert(x != NULL);
2737  assert(lambda != NULL);
2738  assert(z_L != NULL);
2739  assert(z_U != NULL);
2740 
2741  if( nlpiproblem->lastsolprimals == NULL )
2742  {
2743  assert(nlpiproblem->lastsoldualcons == NULL);
2744  assert(nlpiproblem->lastsoldualvarlb == NULL);
2745  assert(nlpiproblem->lastsoldualvarub == NULL);
2746  BMSallocMemoryArray(&nlpiproblem->lastsolprimals, n);
2747  BMSallocMemoryArray(&nlpiproblem->lastsoldualcons, m);
2748  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarlb, n);
2749  BMSallocMemoryArray(&nlpiproblem->lastsoldualvarub, n);
2750 
2751  if( nlpiproblem->lastsolprimals == NULL || nlpiproblem->lastsoldualcons == NULL ||
2752  nlpiproblem->lastsoldualvarlb == NULL || nlpiproblem->lastsoldualvarub == NULL )
2753  {
2754  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2755  nlpiproblem->lasttermstat = SCIP_NLPTERMSTAT_MEMERR;
2756  return;
2757  }
2758  }
2759 
2760  BMScopyMemoryArray(nlpiproblem->lastsolprimals, x, n);
2761  BMScopyMemoryArray(nlpiproblem->lastsoldualcons, lambda, m);
2762  BMScopyMemoryArray(nlpiproblem->lastsoldualvarlb, z_L, n);
2763  BMScopyMemoryArray(nlpiproblem->lastsoldualvarub, z_U, n);
2764 
2765  if( check_feasibility && cq != NULL )
2766  {
2767  Number constrviol;
2768  Number constrvioltol;
2769 
2770  constrviol = cq->curr_constraint_violation();
2771 
2772  nlpiproblem->ipopt->Options()->GetNumericValue("acceptable_constr_viol_tol", constrvioltol, "");
2773  if( constrviol <= constrvioltol )
2774  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_FEASIBLE;
2775  else
2776  nlpiproblem->lastsolstat = SCIP_NLPSOLSTAT_LOCINFEASIBLE;
2777  }
2778  }
2779 }
2780 
2781 /* Ipopt >= 3.10 do not reveal defines like F77_FUNC.
2782  * However, they install IpLapack.hpp, so Ipopt's Lapack interface is available.
2783  * Thus, we use IpLapack if F77_FUNC is not defined and access Lapack's Dsyev directly if F77_FUNC is defined.
2784  */
2785 #ifndef F77_FUNC
2786 
2787 #include "IpLapack.hpp"
2788 
2789 /** Calls Lapacks Dsyev routine to compute eigenvalues and eigenvectors of a dense matrix.
2790  *
2791  * It's here, because we use Ipopt's interface to Lapack.
2792  */
2794  SCIP_Bool computeeigenvectors,/**< should also eigenvectors should be computed ? */
2795  int N, /**< dimension */
2796  SCIP_Real* a, /**< matrix data on input (size N*N); eigenvectors on output if computeeigenvectors == TRUE */
2797  SCIP_Real* w /**< buffer to store eigenvalues (size N) */
2798  )
2799 {
2800  int info;
2801 
2802  IpLapackDsyev(computeeigenvectors, N, a, N, w, info);
2803 
2804  if( info != 0 )
2805  {
2806  SCIPerrorMessage("There was an error when calling DSYEV. INFO = %d\n", info);
2807  return SCIP_ERROR;
2808  }
2809 
2810  return SCIP_OKAY;
2811 }
2812 
2813 /** solves a linear problem of the form Ax = b
2814  *
2815  * Calls Lapacks IpLapackDgetrf routine to calculate a LU factorization and uses this factorization to solve
2816  * the linear problem Ax = b.
2817  * It's here, because Ipopt is linked against Lapack.
2818  */
2820  int N, /**< dimension */
2821  SCIP_Real** A, /**< matrix data on input (size N*N) */
2822  SCIP_Real* b, /**< right hand side vector (size N) */
2823  SCIP_Real* x, /**< buffer to store solution (size N) */
2824  SCIP_Bool* success /**< pointer to store if the solving routine was successful */
2825  )
2826 {
2827  SCIP_Real* tmp_A;
2828  SCIP_Real* tmp_b;
2829  int* tmp_pivot;
2830  int info;
2831  int i;
2832 
2833  assert(N > 0);
2834  assert(A != NULL);
2835  assert(b != NULL);
2836  assert(x != NULL);
2837  assert(success != NULL);
2838 
2839  SCIP_ALLOC( BMSallocMemoryArray(&tmp_A, N*N) );
2840  SCIP_ALLOC( BMSallocMemoryArray(&tmp_b, N) );
2841  SCIP_ALLOC( BMSallocMemoryArray(&tmp_pivot, N) );
2842 
2843  /* copy values from A into the tmp_A array */
2844  for( i = 0; i < N; ++i)
2845  {
2846  int j;
2847  for( j = 0; j < N; ++j )
2848  tmp_A[N*i+j] = A[j][i]; /* note that we have to fill tmp_A column wise */
2849 
2850  tmp_b[i] = b[i];
2851  }
2852 
2853  /* compute the LU factorization */
2854  IpLapackDgetrf(N, tmp_A, tmp_pivot, N, info);
2855 
2856  if( info != 0 )
2857  {
2858  BMSfreeMemoryArray(&tmp_pivot);
2859  BMSfreeMemoryArray(&tmp_b);
2860  BMSfreeMemoryArray(&tmp_A);
2861 
2862  SCIPerrorMessage("There was an error when calling Dgetrf. INFO = %d\n", info);
2863  *success = FALSE;
2864 
2865  return SCIP_OKAY;
2866  }
2867 
2868  /* solve linear problem */
2869  IpLapackDgetrs(N, 1, tmp_A, N, tmp_pivot, tmp_b, N);
2870 
2871  /* copy the solution */
2872  for( i = 0; i < N; ++i )
2873  x[i] = tmp_b[i];
2874 
2875  BMSfreeMemoryArray(&tmp_pivot);
2876  BMSfreeMemoryArray(&tmp_b);
2877  BMSfreeMemoryArray(&tmp_A);
2878 
2879  *success = TRUE;
2880 
2881  return SCIP_OKAY;
2882 }
2883 
2884 #else
2885 
2886 extern "C" {
2887  /** LAPACK Fortran subroutine DSYEV */
2888  void F77_FUNC(dsyev,DSYEV)(
2889  char* jobz, /**< 'N' to compute eigenvalues only, 'V' to compute eigenvalues and eigenvectors */
2890  char* uplo, /**< 'U' if upper triangle of A is stored, 'L' if lower triangle of A is stored */
2891  int* n, /**< dimension */
2892  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 */
2893  int* ldA, /**< leading dimension, probably equal to n */
2894  double* W, /**< buffer for the eigenvalues in ascending order */
2895  double* WORK, /**< workspace array */
2896  int* LWORK, /**< length of WORK; if LWORK = -1, then the optimal workspace size is calculated and returned in WORK(1) */
2897  int* info /**< == 0: successful exit; < 0: illegal argument at given position; > 0: failed to converge */
2898  );
2899 }
2900 
2901 /** Calls Lapacks Dsyev routine to compute eigenvalues and eigenvectors of a dense matrix.
2902  *
2903  * It's here, because Ipopt is linked against Lapack.
2904  */
2906  SCIP_Bool computeeigenvectors,/**< should also eigenvectors should be computed ? */
2907  int N, /**< dimension */
2908  SCIP_Real* a, /**< matrix data on input (size N*N); eigenvectors on output if computeeigenvectors == TRUE */
2909  SCIP_Real* w /**< buffer to store eigenvalues (size N) */
2910  )
2911 {
2912  int INFO;
2913  char JOBZ = computeeigenvectors ? 'V' : 'N';
2914  char UPLO = 'L';
2915  int LDA = N;
2916  double* WORK = NULL;
2917  int LWORK;
2918  double WORK_PROBE;
2919  int i;
2920 
2921  /* First we find out how large LWORK should be */
2922  LWORK = -1;
2923  F77_FUNC(dsyev,DSYEV)(&JOBZ, &UPLO, &N, a, &LDA, w, &WORK_PROBE, &LWORK, &INFO);
2924  if( INFO != 0 )
2925  {
2926  SCIPerrorMessage("There was an error when calling DSYEV. INFO = %d\n", INFO);
2927  return SCIP_ERROR;
2928  }
2929 
2930  LWORK = (int) WORK_PROBE;
2931  assert(LWORK > 0);
2932 
2933  SCIP_ALLOC( BMSallocMemoryArray(&WORK, LWORK) );
2934 
2935  for( i = 0; i < LWORK; ++i )
2936  WORK[i] = i;
2937 
2938  F77_FUNC(dsyev,DSYEV)(&JOBZ, &UPLO, &N, a, &LDA, w, WORK, &LWORK, &INFO);
2939 
2940  BMSfreeMemoryArray(&WORK);
2941 
2942  if( INFO != 0 )
2943  {
2944  SCIPerrorMessage("There was an error when calling DSYEV. INFO = %d\n", INFO);
2945  return SCIP_ERROR;
2946  }
2947 
2948  return SCIP_OKAY;
2949 }
2950 
2951 #endif
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
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:103
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:623
#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:831
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
#define FALSE
Definition: def.h:53
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:52
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
static SCIP_DECL_NLPIGETINTPAR(nlpiGetIntParIpopt)
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:78
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)
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:758
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:654
int SCIPnlpiOracleGetConstraintDegree(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2312
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:102
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:979
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:914
static SCIP_DECL_NLPICHGNONLINCOEF(nlpiChgNonlinCoefIpopt)
Definition: nlpi_ipopt.cpp:959
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)
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_Real * lastsolprimals
Definition: nlpi_ipopt.cpp:140
#define SCIP_DEFAULT_FEASTOL
Definition: def.h:132
static SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsIpopt)
Definition: nlpi_ipopt.cpp:786
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
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:50
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:890
static const int convcheck_startiter
Definition: nlpi_ipopt.cpp:100
static SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatIpopt)
SCIP_NLPIDATA * SCIPnlpiGetData(SCIP_NLPI *nlpi)
Definition: nlpi.c:731
#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:718
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:7714
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:129
#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:835
#define SCIP_Real
Definition: def.h:124
SCIP_NLPTERMSTAT lasttermstat
Definition: nlpi_ipopt.cpp:139
#define MIN(x, y)
Definition: memory.c:63
static SCIP_DECL_NLPISETMESSAGEHDLR(nlpiSetMessageHdlrIpopt)
SCIP_Real * lastsoldualcons
Definition: nlpi_ipopt.cpp:141
#define SCIP_INVALID
Definition: def.h:144
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:862
static SCIP_DECL_NLPISETREALPAR(nlpiSetRealParIpopt)
SCIP_RETCODE SCIPnlpiOracleEvalJacobian(SCIP_NLPIORACLE *oracle, const SCIP_Real *x, SCIP_Bool isnewx, SCIP_Real *convals, SCIP_Real *jacobi)
Definition: nlpioracle.c:2638
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
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:841
char ** SCIPnlpiOracleGetVarNames(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2230
static SCIP_DECL_NLPICHGEXPRTREE(nlpiChgExprtreeIpopt)
Definition: nlpi_ipopt.cpp:935
#define SCIP_ALLOC(x)
Definition: def.h:274
#define SCIPABORT()
Definition: def.h:235
static SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesIpopt)
Definition: nlpi_ipopt.cpp:810
static SCIP_DECL_NLPIADDVARS(nlpiAddVarsIpopt)
Definition: nlpi_ipopt.cpp:673
SCIP_RETCODE LapackDsyev(SCIP_Bool computeeigenvectors, int N, SCIP_Real *a, SCIP_Real *w)
SCIP_NLPIORACLE * oracle
Definition: nlpi_ipopt.cpp:127
SCIP_RETCODE SCIPsolveLinearProb(int N, SCIP_Real **A, SCIP_Real *b, SCIP_Real *x, SCIP_Bool *success)
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