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