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