1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   nlpi.c
17   	 * @ingroup OTHER_CFILES
18   	 * @brief  methods for handling NLP solver interface
19   	 * @author Stefan Vigerske
20   	 * @author Thorsten Gellermann
21   	 */
22   	
23   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24   	
25   	#include <stdio.h>
26   	#include <assert.h>
27   	#include <string.h>
28   	
29   	#include "scip/nlpi.h"
30   	#include "scip/pub_message.h"
31   	#include "scip/pub_nlpi.h"
32   	#include "scip/clock.h"
33   	#include "scip/struct_nlpi.h"
34   	#include "scip/struct_set.h"
35   	#include "scip/struct_stat.h"
36   	
37   	/** compares two NLPIs w.r.t. their priority */
38   	SCIP_DECL_SORTPTRCOMP(SCIPnlpiComp)
39   	{  /*lint --e{715}*/
40   	   return ((SCIP_NLPI*)elem2)->priority - ((SCIP_NLPI*)elem1)->priority;
41   	}
42   	
43   	/** creates an NLP solver interface */
44   	SCIP_RETCODE SCIPnlpiCreate(
45   	   SCIP_NLPI**                     nlpi,                        /**< pointer to NLP interface data structure */
46   	   const char*                     name,                        /**< name of NLP interface */
47   	   const char*                     description,                 /**< description of NLP interface */
48   	   int                             priority,                    /**< priority of NLP interface */
49   	   SCIP_DECL_NLPICOPY              ((*nlpicopy)),               /**< copying of NLPI, can be NULL */
50   	   SCIP_DECL_NLPIFREE              ((*nlpifree)),               /**< free NLPI user data */
51   	   SCIP_DECL_NLPIGETSOLVERPOINTER  ((*nlpigetsolverpointer)),   /**< get solver pointer, can be NULL */
52   	   SCIP_DECL_NLPICREATEPROBLEM     ((*nlpicreateproblem)),      /**< create a new problem instance */
53   	   SCIP_DECL_NLPIFREEPROBLEM       ((*nlpifreeproblem)),        /**< free a problem instance */
54   	   SCIP_DECL_NLPIGETPROBLEMPOINTER ((*nlpigetproblempointer)),  /**< get problem pointer, can be NULL */
55   	   SCIP_DECL_NLPIADDVARS           ((*nlpiaddvars)),            /**< add variables */
56   	   SCIP_DECL_NLPIADDCONSTRAINTS    ((*nlpiaddconstraints)),     /**< add constraints */
57   	   SCIP_DECL_NLPISETOBJECTIVE      ((*nlpisetobjective)),       /**< set objective */
58   	   SCIP_DECL_NLPICHGVARBOUNDS      ((*nlpichgvarbounds)),       /**< change variable bounds */
59   	   SCIP_DECL_NLPICHGCONSSIDES      ((*nlpichgconssides)),       /**< change constraint sides */
60   	   SCIP_DECL_NLPIDELVARSET         ((*nlpidelvarset)),          /**< delete a set of constraints */
61   	   SCIP_DECL_NLPIDELCONSSET        ((*nlpidelconsset)),         /**< delete a set of constraints */
62   	   SCIP_DECL_NLPICHGLINEARCOEFS    ((*nlpichglinearcoefs)),     /**< change coefficients in linear part of a constraint or objective */
63   	   SCIP_DECL_NLPICHGEXPR           ((*nlpichgexpr)),            /**< change nonlinear expression a constraint or objective */
64   	   SCIP_DECL_NLPICHGOBJCONSTANT    ((*nlpichgobjconstant)),     /**< change the constant offset in the objective */
65   	   SCIP_DECL_NLPISETINITIALGUESS   ((*nlpisetinitialguess)),    /**< set initial guess, can be NULL */
66   	   SCIP_DECL_NLPISOLVE             ((*nlpisolve)),              /**< solve NLP */
67   	   SCIP_DECL_NLPIGETSOLSTAT        ((*nlpigetsolstat)),         /**< get solution status */
68   	   SCIP_DECL_NLPIGETTERMSTAT       ((*nlpigettermstat)),        /**< get termination status */
69   	   SCIP_DECL_NLPIGETSOLUTION       ((*nlpigetsolution)),        /**< get solution */
70   	   SCIP_DECL_NLPIGETSTATISTICS     ((*nlpigetstatistics)),      /**< get solve statistics */
71   	   SCIP_NLPIDATA*                  nlpidata                     /**< NLP interface local data */
72   	   )
73   	{  /*lint --e{715}*/
74   	   assert(nlpi != NULL);
75   	
76   	   assert(name != NULL);
77   	   assert(description != NULL);
78   	   assert(nlpifree != NULL);
79   	   assert(nlpicreateproblem != NULL);
80   	   assert(nlpifreeproblem != NULL);
81   	   assert(nlpiaddvars != NULL);
82   	   assert(nlpiaddconstraints != NULL);
83   	   assert(nlpisetobjective != NULL);
84   	   assert(nlpichgvarbounds != NULL);
85   	   assert(nlpichgconssides != NULL);
86   	   assert(nlpidelconsset != NULL);
87   	   assert(nlpichglinearcoefs != NULL);
88   	   assert(nlpichgobjconstant != NULL);
89   	   assert(nlpisolve != NULL);
90   	   assert(nlpigetsolstat != NULL);
91   	   assert(nlpigettermstat != NULL);
92   	   assert(nlpigetsolution != NULL);
93   	   assert(nlpigetstatistics != NULL);
94   	
95   	   SCIP_ALLOC( BMSallocClearMemory(nlpi) );
96   	
97   	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*nlpi)->name, name, strlen(name)+1) );
98   	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*nlpi)->description, description, strlen(description)+1) );
99   	   (*nlpi)->priority = priority;
100  	   (*nlpi)->nlpicopy = nlpicopy;
101  	   (*nlpi)->nlpifree = nlpifree;
102  	   (*nlpi)->nlpigetsolverpointer = nlpigetsolverpointer;
103  	   (*nlpi)->nlpicreateproblem = nlpicreateproblem;
104  	   (*nlpi)->nlpifreeproblem = nlpifreeproblem;
105  	   (*nlpi)->nlpigetproblempointer = nlpigetproblempointer;
106  	   (*nlpi)->nlpiaddvars = nlpiaddvars;
107  	   (*nlpi)->nlpiaddconstraints = nlpiaddconstraints;
108  	   (*nlpi)->nlpisetobjective = nlpisetobjective;
109  	   (*nlpi)->nlpichgvarbounds = nlpichgvarbounds;
110  	   (*nlpi)->nlpichgconssides = nlpichgconssides;
111  	   (*nlpi)->nlpidelvarset = nlpidelvarset;
112  	   (*nlpi)->nlpidelconsset = nlpidelconsset;
113  	   (*nlpi)->nlpichglinearcoefs = nlpichglinearcoefs;
114  	   (*nlpi)->nlpichgobjconstant = nlpichgobjconstant;
115  	   (*nlpi)->nlpisetinitialguess = nlpisetinitialguess;
116  	   (*nlpi)->nlpisolve = nlpisolve;
117  	   (*nlpi)->nlpigetsolstat = nlpigetsolstat;
118  	   (*nlpi)->nlpigettermstat = nlpigettermstat;
119  	   (*nlpi)->nlpigetsolution = nlpigetsolution;
120  	   (*nlpi)->nlpigetstatistics = nlpigetstatistics;
121  	   (*nlpi)->nlpidata = nlpidata;
122  	
123  	   SCIP_CALL( SCIPclockCreate(&(*nlpi)->problemtime, SCIP_CLOCKTYPE_DEFAULT) );
124  	
125  	   return SCIP_OKAY;
126  	}
127  	
128  	/** sets NLP solver priority */
129  	void SCIPnlpiSetPriority(
130  	   SCIP_NLPI*            nlpi,               /**< NLP interface structure */
131  	   int                   priority            /**< new priority of NLPI */
132  	   )
133  	{
134  	   assert(nlpi != NULL);
135  	
136  	   nlpi->priority = priority;
137  	}
138  	
139  	/** copies an NLPI and includes it into another SCIP instance */
140  	SCIP_RETCODE SCIPnlpiCopyInclude(
141  	   SCIP_NLPI*            sourcenlpi,         /**< the NLP interface to copy */
142  	   SCIP_SET*             targetset           /**< global SCIP settings where to include copy */
143  	   )
144  	{
145  	   assert(sourcenlpi != NULL);
146  	   assert(targetset != NULL);
147  	
148  	   if( sourcenlpi->nlpicopy != NULL )
149  	   {
150  	      SCIP_CALL( sourcenlpi->nlpicopy(targetset->scip, sourcenlpi) );
151  	   }
152  	
153  	   return SCIP_OKAY;
154  	}
155  	
156  	/** frees NLPI */
157  	SCIP_RETCODE SCIPnlpiFree(
158  	   SCIP_NLPI**           nlpi,               /**< pointer to NLPI data structure */
159  	   SCIP_SET*             set                 /**< global SCIP settings */
160  	   )
161  	{
162  	   assert(nlpi  != NULL);
163  	   assert(*nlpi != NULL);
164  	   assert(set   != NULL);
165  	
166  	   if( (*nlpi)->nlpifree != NULL )
167  	   {
168  	      SCIP_CALL( (*nlpi)->nlpifree(set->scip, *nlpi, &(*nlpi)->nlpidata) );
169  	      assert((*nlpi)->nlpidata == NULL);
170  	   }
171  	   BMSfreeMemoryArray(&(*nlpi)->name);
172  	   BMSfreeMemoryArray(&(*nlpi)->description);
173  	
174  	   SCIPclockFree(&(*nlpi)->problemtime);
175  	
176  	   BMSfreeMemory(nlpi);
177  	
178  	   assert(*nlpi == NULL);
179  	
180  	   return SCIP_OKAY;
181  	}
182  	
183  	/** initializes NLPI */
184  	void SCIPnlpiInit(
185  	   SCIP_NLPI*            nlpi                /**< solver interface */
186  	   )
187  	{
188  	   assert(nlpi != NULL);
189  	
190  	   nlpi->nproblems = 0;
191  	   nlpi->nsolves = 0;
192  	   SCIPclockReset(nlpi->problemtime);
193  	   nlpi->solvetime = 0.0;
194  	   nlpi->evaltime = 0.0;
195  	   nlpi->niter = 0L;
196  	   BMSclearMemoryArray(nlpi->ntermstat, (int)SCIP_NLPTERMSTAT_OTHER+1);
197  	   BMSclearMemoryArray(nlpi->nsolstat, (int)SCIP_NLPSOLSTAT_UNKNOWN+1);
198  	}
199  	
200  	/** gets pointer for NLP solver */
201  	void* SCIPnlpiGetSolverPointer(
202  	   SCIP_SET*             set,                /**< global SCIP settings */
203  	   SCIP_NLPI*            nlpi,               /**< solver interface */
204  	   SCIP_NLPIPROBLEM*     problem             /**< problem instance, or NULL */
205  	   )
206  	{
207  	   assert(set != NULL);
208  	   assert(nlpi != NULL);
209  	
210  	   if( nlpi->nlpigetsolverpointer != NULL )
211  	      return nlpi->nlpigetsolverpointer(set->scip, nlpi, problem);
212  	   else
213  	      return NULL;
214  	}
215  	
216  	/** creates a problem instance */
217  	SCIP_RETCODE SCIPnlpiCreateProblem(
218  	   SCIP_SET*             set,                /**< global SCIP settings */
219  	   SCIP_NLPI*            nlpi,               /**< solver interface */
220  	   SCIP_NLPIPROBLEM**    problem,            /**< problem pointer to store the problem data */
221  	   const char*           name                /**< name of problem, can be NULL */
222  	   )
223  	{
224  	   assert(set != NULL);
225  	   assert(nlpi != NULL);
226  	   assert(nlpi->nlpicreateproblem != NULL);
227  	   assert(problem != NULL);
228  	
229  	   SCIPclockStart(nlpi->problemtime, set);
230  	   SCIP_CALL( nlpi->nlpicreateproblem(set->scip, nlpi, problem, name) );
231  	   SCIPclockStop(nlpi->problemtime, set);
232  	
233  	   ++nlpi->nproblems;
234  	
235  	   return SCIP_OKAY;
236  	}
237  	
238  	/** frees a problem instance */
239  	SCIP_RETCODE SCIPnlpiFreeProblem(
240  	   SCIP_SET*             set,                /**< global SCIP settings */
241  	   SCIP_NLPI*            nlpi,               /**< solver interface */
242  	   SCIP_NLPIPROBLEM**    problem             /**< pointer where problem instance is stored */
243  	   )
244  	{
245  	   assert(set != NULL);
246  	   assert(nlpi != NULL);
247  	   assert(nlpi->nlpifreeproblem != NULL);
248  	   assert(problem != NULL);
249  	
250  	   SCIPclockStart(nlpi->problemtime, set);
251  	   SCIP_CALL( nlpi->nlpifreeproblem(set->scip, nlpi, problem) );
252  	   SCIPclockStop(nlpi->problemtime, set);
253  	
254  	   return SCIP_OKAY;
255  	}
256  	
257  	/** gets pointer to solver-internal problem instance */
258  	void* SCIPnlpiGetProblemPointer(
259  	   SCIP_SET*             set,                /**< global SCIP settings */
260  	   SCIP_NLPI*            nlpi,               /**< solver interface */
261  	   SCIP_NLPIPROBLEM*     problem             /**< problem instance */
262  	   )
263  	{
264  	   assert(set != NULL);
265  	   assert(nlpi != NULL);
266  	   assert(problem != NULL);
267  	
268  	   if( nlpi->nlpigetproblempointer != NULL )
269  	      return nlpi->nlpigetproblempointer(set->scip, nlpi, problem);
270  	   else
271  	      return NULL;
272  	}
273  	
274  	/** add variables to nlpi */
275  	SCIP_RETCODE SCIPnlpiAddVars(
276  	   SCIP_SET*             set,                /**< global SCIP settings */
277  	   SCIP_NLPI*            nlpi,               /**< solver interface */
278  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
279  	   int                   nvars,              /**< number of variables */
280  	   const SCIP_Real*      lbs,                /**< lower bounds of variables, can be NULL if -infinity */
281  	   const SCIP_Real*      ubs,                /**< upper bounds of variables, can be NULL if +infinity */
282  	   const char**          varnames            /**< names of variables, can be NULL */
283  	   )
284  	{
285  	   assert(set != NULL);
286  	   assert(nlpi != NULL);
287  	   assert(nlpi->nlpiaddvars != NULL);
288  	   assert(problem != NULL);
289  	
290  	   SCIPclockStart(nlpi->problemtime, set);
291  	   SCIP_CALL( nlpi->nlpiaddvars(set->scip, nlpi, problem, nvars, lbs, ubs, varnames) );
292  	   SCIPclockStop(nlpi->problemtime, set);
293  	
294  	   return SCIP_OKAY;
295  	}
296  	
297  	/** add constraints to nlpi */
298  	SCIP_RETCODE SCIPnlpiAddConstraints(
299  	   SCIP_SET*             set,                /**< global SCIP settings */
300  	   SCIP_NLPI*            nlpi,               /**< solver interface */
301  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
302  	   int                   nconss,             /**< number of constraints */
303  	   const SCIP_Real*      lhss,               /**< left hand sides of constraints, can be NULL if -infinity */
304  	   const SCIP_Real*      rhss,               /**< right hand sides of constraints, can be NULL if +infinity */
305  	   const int*            nlininds,           /**< number of linear coefficients for each constraint, may be NULL in case of no linear part */
306  	   int* const*           lininds,            /**< indices of variables for linear coefficients for each constraint, may be NULL in case of no linear part */
307  	   SCIP_Real* const*     linvals,            /**< values of linear coefficient for each constraint, may be NULL in case of no linear part */
308  	   SCIP_EXPR**           exprs,              /**< expressions for nonlinear part of constraints, entry of array may be NULL in case of no nonlinear part, may be NULL in case of no nonlinear part in any constraint */
309  	   const char**          names               /**< names of constraints, may be NULL or entries may be NULL */
310  	   )
311  	{
312  	   assert(set != NULL);
313  	   assert(nlpi != NULL);
314  	   assert(nlpi->nlpiaddconstraints != NULL);
315  	   assert(problem != NULL);
316  	
317  	   SCIPclockStart(nlpi->problemtime, set);
318  	   SCIP_CALL( nlpi->nlpiaddconstraints(set->scip, nlpi, problem, nconss, lhss, rhss, nlininds, lininds, linvals, exprs, names) );
319  	   SCIPclockStop(nlpi->problemtime, set);
320  	
321  	   return SCIP_OKAY;
322  	}
323  	
324  	/** sets or overwrites objective, a minimization problem is expected */
325  	SCIP_RETCODE SCIPnlpiSetObjective(
326  	   SCIP_SET*             set,                /**< global SCIP settings */
327  	   SCIP_NLPI*            nlpi,               /**< solver interface */
328  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
329  	   int                   nlins,              /**< number of linear variables */
330  	   const int*            lininds,            /**< variable indices, may be NULL in case of no linear part */
331  	   const SCIP_Real*      linvals,            /**< coefficient values, may be NULL in case of no linear part */
332  	   SCIP_EXPR*            expr,               /**< expression for nonlinear part of objective function, may be NULL in case of no nonlinear part */
333  	   const SCIP_Real       constant            /**< objective value offset */
334  	   )
335  	{
336  	   assert(set != NULL);
337  	   assert(nlpi != NULL);
338  	   assert(nlpi->nlpisetobjective != NULL);
339  	   assert(problem != NULL);
340  	
341  	   SCIPclockStart(nlpi->problemtime, set);
342  	   SCIP_CALL( nlpi->nlpisetobjective(set->scip, nlpi, problem, nlins, lininds, linvals, expr, constant) );
343  	   SCIPclockStop(nlpi->problemtime, set);
344  	
345  	   return SCIP_OKAY;
346  	}
347  	
348  	/** change variable bounds */
349  	SCIP_RETCODE SCIPnlpiChgVarBounds(
350  	   SCIP_SET*             set,                /**< global SCIP settings */
351  	   SCIP_NLPI*            nlpi,               /**< solver interface */
352  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
353  	   const int             nvars,              /**< number of variables to change bounds */
354  	   const int*            indices,            /**< indices of variables to change bounds */
355  	   const SCIP_Real*      lbs,                /**< new lower bounds */
356  	   const SCIP_Real*      ubs                 /**< new upper bounds */
357  	   )
358  	{
359  	   assert(set != NULL);
360  	   assert(nlpi != NULL);
361  	   assert(nlpi->nlpichgvarbounds != NULL);
362  	   assert(problem != NULL);
363  	
364  	   SCIPclockStart(nlpi->problemtime, set);
365  	   SCIP_CALL( nlpi->nlpichgvarbounds(set->scip, nlpi, problem, nvars, indices, lbs, ubs) );
366  	   SCIPclockStop(nlpi->problemtime, set);
367  	
368  	   return SCIP_OKAY;
369  	}
370  	
371  	/** change constraint sides */
372  	SCIP_RETCODE SCIPnlpiChgConsSides(
373  	   SCIP_SET*             set,                /**< global SCIP settings */
374  	   SCIP_NLPI*            nlpi,               /**< solver interface */
375  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
376  	   int                   nconss,             /**< number of constraints to change sides */
377  	   const int*            indices,            /**< indices of constraints to change sides */
378  	   const SCIP_Real*      lhss,               /**< new left hand sides */
379  	   const SCIP_Real*      rhss                /**< new right hand sides */
380  	   )
381  	{
382  	   assert(set != NULL);
383  	   assert(nlpi != NULL);
384  	   assert(nlpi->nlpichgconssides != NULL);
385  	   assert(problem != NULL);
386  	
387  	   SCIPclockStart(nlpi->problemtime, set);
388  	   SCIP_CALL( nlpi->nlpichgconssides(set->scip, nlpi, problem, nconss, indices, lhss, rhss) );
389  	   SCIPclockStop(nlpi->problemtime, set);
390  	
391  	   return SCIP_OKAY;
392  	}
393  	
394  	/** delete a set of variables */
395  	SCIP_RETCODE SCIPnlpiDelVarSet(
396  	   SCIP_SET*             set,                /**< global SCIP settings */
397  	   SCIP_NLPI*            nlpi,               /**< solver interface */
398  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
399  	   int*                  dstats,             /**< deletion status of vars; 1 if var should be deleted, 0 if not */
400  	   int                   dstatssize          /**< size of the dstats array */
401  	   )
402  	{
403  	   assert(set != NULL);
404  	   assert(nlpi != NULL);
405  	   assert(nlpi->nlpidelvarset != NULL);
406  	   assert(problem != NULL);
407  	
408  	   SCIPclockStart(nlpi->problemtime, set);
409  	   SCIP_CALL( nlpi->nlpidelvarset(set->scip, nlpi, problem, dstats, dstatssize) );
410  	   SCIPclockStop(nlpi->problemtime, set);
411  	
412  	   return SCIP_OKAY;
413  	}
414  	
415  	/** delete a set of constraints */
416  	SCIP_RETCODE SCIPnlpiDelConsSet(
417  	   SCIP_SET*             set,                /**< global SCIP settings */
418  	   SCIP_NLPI*            nlpi,               /**< solver interface */
419  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
420  	   int*                  dstats,             /**< deletion status of constraints; 1 if constraint should be deleted, 0 if not */
421  	   int                   dstatssize          /**< size of the dstats array */
422  	   )
423  	{
424  	   assert(set != NULL);
425  	   assert(nlpi != NULL);
426  	   assert(nlpi->nlpidelconsset != NULL);
427  	   assert(problem != NULL);
428  	
429  	   SCIPclockStart(nlpi->problemtime, set);
430  	   SCIP_CALL( nlpi->nlpidelconsset(set->scip, nlpi, problem, dstats, dstatssize) );
431  	   SCIPclockStop(nlpi->problemtime, set);
432  	
433  	   return SCIP_OKAY;
434  	}
435  	
436  	/** changes or adds linear coefficients in a constraint or objective */
437  	SCIP_RETCODE SCIPnlpiChgLinearCoefs(
438  	   SCIP_SET*             set,                /**< global SCIP settings */
439  	   SCIP_NLPI*            nlpi,               /**< solver interface */
440  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
441  	   int                   idx,                /**< index of constraint or -1 for objective */
442  	   int                   nvals,              /**< number of values in linear constraint to change */
443  	   const int*            varidxs,            /**< indices of variables which coefficient to change */
444  	   const SCIP_Real*      vals                /**< new values for coefficients */
445  	   )
446  	{
447  	   assert(set != NULL);
448  	   assert(nlpi != NULL);
449  	   assert(nlpi->nlpichglinearcoefs != NULL);
450  	   assert(problem != NULL);
451  	
452  	   SCIPclockStart(nlpi->problemtime, set);
453  	   SCIP_CALL( nlpi->nlpichglinearcoefs(set->scip, nlpi, problem, idx, nvals, varidxs, vals) );
454  	   SCIPclockStop(nlpi->problemtime, set);
455  	
456  	   return SCIP_OKAY;
457  	}
458  	
459  	/** change the expression in the nonlinear part */
460  	SCIP_RETCODE SCIPnlpiChgExpr(
461  	   SCIP_SET*             set,                /**< global SCIP settings */
462  	   SCIP_NLPI*            nlpi,               /**< solver interface */
463  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
464  	   int                   idxcons,            /**< index of constraint or -1 for objective */
465  	   SCIP_EXPR*            expr                /**< new expression for constraint or objective, or NULL to only remove previous tree */
466  	   )
467  	{
468  	   assert(set != NULL);
469  	   assert(nlpi != NULL);
470  	   assert(nlpi->nlpichgexpr != NULL);
471  	   assert(problem != NULL);
472  	
473  	   SCIPclockStart(nlpi->problemtime, set);
474  	   SCIP_CALL( nlpi->nlpichgexpr(set->scip, nlpi, problem, idxcons, expr) );
475  	   SCIPclockStop(nlpi->problemtime, set);
476  	
477  	   return SCIP_OKAY;
478  	}
479  	
480  	/** change the constant offset in the objective */
481  	SCIP_RETCODE SCIPnlpiChgObjConstant(
482  	   SCIP_SET*             set,                /**< global SCIP settings */
483  	   SCIP_NLPI*            nlpi,               /**< solver interface */
484  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
485  	   SCIP_Real             objconstant         /**< new value for objective constant */
486  	   )
487  	{
488  	   assert(set != NULL);
489  	   assert(nlpi != NULL);
490  	   assert(nlpi->nlpichgobjconstant != NULL);
491  	   assert(problem != NULL);
492  	
493  	   SCIPclockStart(nlpi->problemtime, set);
494  	   SCIP_CALL( nlpi->nlpichgobjconstant(set->scip, nlpi, problem, objconstant) );
495  	   SCIPclockStop(nlpi->problemtime, set);
496  	
497  	   return SCIP_OKAY;
498  	}
499  	
500  	/** sets initial guess for primal variables */
501  	SCIP_RETCODE SCIPnlpiSetInitialGuess(
502  	   SCIP_SET*             set,                /**< global SCIP settings */
503  	   SCIP_NLPI*            nlpi,               /**< solver interface */
504  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
505  	   SCIP_Real*            primalvalues,       /**< initial primal values for variables, or NULL to clear previous values */
506  	   SCIP_Real*            consdualvalues,     /**< initial dual values for constraints, or NULL to clear previous values */
507  	   SCIP_Real*            varlbdualvalues,    /**< initial dual values for variable lower bounds, or NULL to clear previous values */
508  	   SCIP_Real*            varubdualvalues     /**< initial dual values for variable upper bounds, or NULL to clear previous values */
509  	   )
510  	{
511  	   assert(set != NULL);
512  	   assert(nlpi != NULL);
513  	   assert(problem != NULL);
514  	
515  	   if( nlpi->nlpisetinitialguess != NULL )
516  	   {
517  	      SCIP_CALL( nlpi->nlpisetinitialguess(set->scip, nlpi, problem, primalvalues, consdualvalues, varlbdualvalues, varubdualvalues) );
518  	   }
519  	
520  	   return SCIP_OKAY;
521  	}
522  	
523  	/** tries to solve NLP */
524  	SCIP_RETCODE SCIPnlpiSolve(
525  	   SCIP_SET*             set,                /**< global SCIP settings */
526  	   SCIP_STAT*            stat,               /**< problem statistics */
527  	   SCIP_NLPI*            nlpi,               /**< solver interface */
528  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
529  	   SCIP_NLPPARAM*        param               /**< solve parameters */
530  	   )
531  	{
532  	   SCIP_NLPSTATISTICS stats;
533  	
534  	   assert(set != NULL);
535  	   assert(nlpi != NULL);
536  	   assert(nlpi->nlpisolve != NULL);
537  	   assert(problem != NULL);
538  	   assert(param != NULL);
539  	
540  	   /* check that parameter values are in accepted range (if type allows more than we would accept) */
(1) Event cond_false: Condition "param->iterlimit < 0", taking false branch.
541  	   if( param->iterlimit < 0 )
542  	   {
543  	      SCIPerrorMessage("Value %d for parameter iteration limit must be non-negative.\n", param->iterlimit);
544  	      return SCIP_PARAMETERWRONGVAL;
(2) Event if_end: End of if statement.
545  	   }
(3) Event cond_false: Condition "param->feastol < 0.", taking false branch.
546  	   if( param->feastol < 0.0 )
547  	   {
548  	      SCIPerrorMessage("Value %g for parameter feasibility tolerance cannot be negative\n", param->feastol);
549  	      return SCIP_PARAMETERWRONGVAL;
(4) Event if_end: End of if statement.
550  	   }
(5) Event cond_false: Condition "param->opttol < 0.", taking false branch.
551  	   if( param->opttol < 0.0 )
552  	   {
553  	      SCIPerrorMessage("Value %g for parameter optimality tolerance cannot be negative\n", param->opttol);
554  	      return SCIP_PARAMETERWRONGVAL;
(6) Event if_end: End of if statement.
555  	   }
(7) Event cond_false: Condition "param->solvertol < 0.", taking false branch.
556  	   if( param->solvertol < 0.0 )
557  	   {
558  	      SCIPerrorMessage("Value %g for parameter solver tolerance cannot be negative\n", param->solvertol);
559  	      return SCIP_PARAMETERWRONGVAL;
(8) Event if_end: End of if statement.
560  	   }
(9) Event cond_false: Condition "param->timelimit < 0.", taking false branch.
561  	   if( param->timelimit < 0.0 )
562  	   {
563  	      SCIPerrorMessage("Value %g for parameter time limit cannot be negative\n", param->timelimit);
564  	      return SCIP_PARAMETERWRONGVAL;
(10) Event if_end: End of if statement.
565  	   }
566  	
(11) Event cond_true: Condition "param->timelimit == (double)(double)1.79769e+308", taking true branch.
(12) Event cond_true: Condition "set->istimelimitfinite", taking true branch.
567  	   if( param->timelimit == SCIP_REAL_MAX && set->istimelimitfinite )  /*lint !e777*/
568  	   {
569  	      /* set timelimit to time remaining if limits/time has been set */
570  	      param->timelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
(13) Event cond_true: Condition "param->timelimit < 0.", taking true branch.
571  	      if( param->timelimit < 0.0 )
572  	         param->timelimit = 0.0;
573  	      /* still call NLP solver if no time left to ensure proper termination codes */
574  	   }
575  	
576  	   ++nlpi->nsolves;
577  	
(14) Event cond_false: Condition "(_restat_ = (*nlpi->nlpisolve)(set->scip, nlpi, problem, *param)) != SCIP_OKAY", taking false branch.
(15) Event if_end: End of if statement.
578  	   SCIP_CALL( nlpi->nlpisolve(set->scip, nlpi, problem, *param) );
579  	
580  	   ++nlpi->ntermstat[nlpi->nlpigettermstat(set->scip, nlpi, problem)];
(16) Event overrun-local: Overrunning array "nlpi->nsolstat" of 7 4-byte elements at element index 7 (byte offset 31) using index "(*nlpi->nlpigetsolstat)(set->scip, nlpi, problem)" (which evaluates to 7).
581  	   ++nlpi->nsolstat[nlpi->nlpigetsolstat(set->scip, nlpi, problem)];
582  	
583  	   SCIP_CALL( nlpi->nlpigetstatistics(set->scip, nlpi, problem, &stats) );
584  	   nlpi->solvetime += stats.totaltime;
585  	   nlpi->evaltime += stats.evaltime;
586  	   nlpi->niter += stats.niterations;
587  	
588  	   return SCIP_OKAY;
589  	}
590  	
591  	/** gives solution status */
592  	SCIP_NLPSOLSTAT SCIPnlpiGetSolstat(
593  	   SCIP_SET*             set,                /**< global SCIP settings */
594  	   SCIP_NLPI*            nlpi,               /**< solver interface */
595  	   SCIP_NLPIPROBLEM*     problem             /**< problem instance */
596  	   )
597  	{
598  	   assert(set != NULL);
599  	   assert(nlpi != NULL);
600  	   assert(nlpi->nlpigetsolstat != NULL);
601  	   assert(problem != NULL);
602  	
603  	   return nlpi->nlpigetsolstat(set->scip, nlpi, problem);
604  	}
605  	
606  	/** gives termination reason */
607  	SCIP_NLPTERMSTAT SCIPnlpiGetTermstat(
608  	   SCIP_SET*             set,                /**< global SCIP settings */
609  	   SCIP_NLPI*            nlpi,               /**< solver interface */
610  	   SCIP_NLPIPROBLEM*     problem             /**< problem instance */
611  	   )
612  	{
613  	   assert(set != NULL);
614  	   assert(nlpi != NULL);
615  	   assert(nlpi->nlpigettermstat != NULL);
616  	   assert(problem != NULL);
617  	
618  	   return nlpi->nlpigettermstat(set->scip, nlpi, problem);
619  	}
620  	
621  	/** gives primal and dual solution
622  	 * for a ranged constraint, the dual variable is positive if the right hand side is active and negative if the left hand side is active
623  	 */
624  	SCIP_RETCODE SCIPnlpiGetSolution(
625  	   SCIP_SET*             set,                /**< global SCIP settings */
626  	   SCIP_NLPI*            nlpi,               /**< solver interface */
627  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
628  	   SCIP_Real**           primalvalues,       /**< buffer to store pointer to array to primal values, or NULL if not needed */
629  	   SCIP_Real**           consdualvalues,     /**< buffer to store pointer to array to dual values of constraints, or NULL if not needed */
630  	   SCIP_Real**           varlbdualvalues,    /**< buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed */
631  	   SCIP_Real**           varubdualvalues,    /**< buffer to store pointer to array to dual values of variable lower bounds, or NULL if not needed */
632  	   SCIP_Real*            objval              /**< pointer to store the objective value, or NULL if not needed */
633  	   )
634  	{
635  	   assert(set != NULL);
636  	   assert(nlpi != NULL);
637  	   assert(nlpi->nlpigetsolution != NULL);
638  	   assert(problem != NULL);
639  	
640  	   SCIP_CALL( nlpi->nlpigetsolution(set->scip, nlpi, problem, primalvalues, consdualvalues, varlbdualvalues, varubdualvalues, objval) );
641  	
642  	   return SCIP_OKAY;
643  	}
644  	
645  	/** gives solve statistics */
646  	SCIP_RETCODE SCIPnlpiGetStatistics(
647  	   SCIP_SET*             set,                /**< global SCIP settings */
648  	   SCIP_NLPI*            nlpi,               /**< solver interface */
649  	   SCIP_NLPIPROBLEM*     problem,            /**< problem instance */
650  	   SCIP_NLPSTATISTICS*   statistics          /**< pointer to store statistics */
651  	   )
652  	{
653  	   assert(set != NULL);
654  	   assert(nlpi != NULL);
655  	   assert(nlpi->nlpigetstatistics != NULL);
656  	   assert(problem != NULL);
657  	
658  	   SCIP_CALL( nlpi->nlpigetstatistics(set->scip, nlpi, problem, statistics) );
659  	
660  	   return SCIP_OKAY;
661  	}
662  	
663  	/* from pub_nlpi.h */
664  	
665  	#ifdef NDEBUG
666  	/* Undo the defines from pub_nlpi.h, which exist if NDEBUG is defined. */
667  	#undef SCIPnlpiGetData
668  	#undef SCIPnlpiGetName
669  	#undef SCIPnlpiGetDesc
670  	#undef SCIPnlpiGetPriority
671  	#undef SCIPnlpiSetPriority
672  	#undef SCIPnlpiGetNProblems
673  	#undef SCIPnlpiGetProblemTime
674  	#undef SCIPnlpiGetNSolves
675  	#undef SCIPnlpiGetSolveTime
676  	#undef SCIPnlpiGetEvalTime
677  	#undef SCIPnlpiGetNIterations
678  	#undef SCIPnlpiGetNTermStat
679  	#undef SCIPnlpiGetNSolStat
680  	#endif
681  	
682  	/** gets data of an NLPI */
683  	SCIP_NLPIDATA* SCIPnlpiGetData(
684  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
685  	   )
686  	{
687  	   assert(nlpi != NULL);
688  	
689  	   return nlpi->nlpidata;
690  	}
691  	
692  	/** gets NLP solver name */
693  	const char* SCIPnlpiGetName(
694  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
695  	   )
696  	{
697  	   assert(nlpi != NULL);
698  	
699  	   return nlpi->name;
700  	}
701  	
702  	/** gets NLP solver description */
703  	const char* SCIPnlpiGetDesc(
704  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
705  	   )
706  	{
707  	   assert(nlpi != NULL);
708  	
709  	   return nlpi->description;
710  	}
711  	
712  	/** gets NLP solver priority */
713  	int SCIPnlpiGetPriority(
714  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
715  	   )
716  	{
717  	   assert(nlpi != NULL);
718  	
719  	   return nlpi->priority;
720  	}
721  	
722  	
723  	/**@name Statistics */
724  	/**@{ */
725  	
726  	/** gives number of problems created for NLP solver so far */
727  	int SCIPnlpiGetNProblems(
728  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
729  	   )
730  	{
731  	   assert(nlpi != NULL);
732  	   return nlpi->nproblems;
733  	}
734  	
735  	/** gives total time spend in problem creation/modification/freeing */
736  	SCIP_Real SCIPnlpiGetProblemTime(
737  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
738  	   )
739  	{
740  	   assert(nlpi != NULL);
741  	   return SCIPclockGetTime(nlpi->problemtime);
742  	}
743  	
744  	/** total number of NLP solves so far */
745  	int SCIPnlpiGetNSolves(
746  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
747  	   )
748  	{
749  	   assert(nlpi != NULL);
750  	   return nlpi->nsolves;
751  	}
752  	
753  	/** gives total time spend in NLP solves (as reported by solver) */
754  	SCIP_Real SCIPnlpiGetSolveTime(
755  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
756  	   )
757  	{
758  	   assert(nlpi != NULL);
759  	   return nlpi->solvetime;
760  	}
761  	
762  	/** gives total time spend in function evaluation during NLP solves
763  	 *
764  	 * If parameter `timing/nlpieval` is off (the default), depending on the NLP solver, this may just return 0.
765  	 */
766  	SCIP_Real SCIPnlpiGetEvalTime(
767  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
768  	   )
769  	{
770  	   assert(nlpi != NULL);
771  	   return nlpi->evaltime;
772  	}
773  	
774  	/** gives total number of iterations spend by NLP solver so far */
775  	SCIP_Longint SCIPnlpiGetNIterations(
776  	   SCIP_NLPI*            nlpi                /**< NLP interface structure */
777  	   )
778  	{
779  	   assert(nlpi != NULL);
780  	   return nlpi->niter;
781  	}
782  	
783  	/** gives number of times a solve ended with a specific termination status */
784  	int SCIPnlpiGetNTermStat(
785  	   SCIP_NLPI*            nlpi,               /**< NLP interface structure */
786  	   SCIP_NLPTERMSTAT      termstatus          /**< the termination status to query for */
787  	   )
788  	{
789  	   assert(nlpi != NULL);
790  	   return nlpi->ntermstat[termstatus];
791  	}
792  	
793  	/** gives number of times a solve ended with a specific solution status */
794  	int SCIPnlpiGetNSolStat(
795  	   SCIP_NLPI*            nlpi,               /**< NLP interface structure */
796  	   SCIP_NLPSOLSTAT       solstatus           /**< the solution status to query for */
797  	   )
798  	{
799  	   assert(nlpi != NULL);
800  	   return nlpi->nsolstat[solstatus];
801  	}
802  	
803  	/** adds statistics from one NLPI to another */
804  	void SCIPnlpiMergeStatistics(
805  	   SCIP_NLPI*            targetnlpi,         /**< NLP interface where to add statistics */
806  	   SCIP_NLPI*            sourcenlpi,         /**< NLP interface from which to add statistics */
807  	   SCIP_Bool             reset               /**< whether to reset statistics in sourcescip */
808  	   )
809  	{
810  	   int i;
811  	
812  	   assert(targetnlpi != NULL);
813  	   assert(sourcenlpi != NULL);
814  	
815  	   targetnlpi->nproblems += sourcenlpi->nproblems;
816  	   targetnlpi->nsolves += sourcenlpi->nsolves;
817  	   SCIPclockSetTime(targetnlpi->problemtime, SCIPclockGetTime(targetnlpi->problemtime) + SCIPclockGetTime(sourcenlpi->problemtime));
818  	   targetnlpi->solvetime += sourcenlpi->solvetime;
819  	   targetnlpi->evaltime += sourcenlpi->evaltime;
820  	   targetnlpi->niter += sourcenlpi->niter;
821  	
822  	   for( i = (int)SCIP_NLPTERMSTAT_OKAY; i <= (int)SCIP_NLPTERMSTAT_OTHER; ++i )
823  	      targetnlpi->ntermstat[i] += sourcenlpi->ntermstat[i];
824  	   for( i = (int)SCIP_NLPSOLSTAT_GLOBOPT; i <= (int)SCIP_NLPSOLSTAT_UNKNOWN; ++i )
825  	      targetnlpi->nsolstat[i] += sourcenlpi->nsolstat[i];
826  	
827  	   if( reset )
828  	   {
829  	      sourcenlpi->nproblems = 0;
830  	      sourcenlpi->nsolves = 0;
831  	      SCIPclockReset(sourcenlpi->problemtime);
832  	      sourcenlpi->solvetime = 0.0;
833  	      sourcenlpi->evaltime = 0.0;
834  	      sourcenlpi->niter = 0;
835  	
836  	      for( i = (int)SCIP_NLPTERMSTAT_OKAY; i <= (int)SCIP_NLPTERMSTAT_OTHER; ++i )
837  	         sourcenlpi->ntermstat[i] = 0;
838  	      for( i = (int)SCIP_NLPSOLSTAT_GLOBOPT; i <= (int)SCIP_NLPSOLSTAT_UNKNOWN; ++i )
839  	         sourcenlpi->nsolstat[i] = 0;
840  	   }
841  	}
842  	
843  	/**@} */ /* Statistics */
844