1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file    nlpi_all.c
26   	 * @ingroup DEFPLUGINS_NLPI
27   	 * @brief   NLP interface that uses all available NLP interfaces
28   	 * @author  Benjamin Mueller
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include "scip/nlpi_all.h"
34   	#include "scip/scip_mem.h"
35   	#include "scip/scip_numerics.h"
36   	#include "scip/scip_nlpi.h"
37   	
38   	#include <string.h>
39   	
40   	#define NLPI_NAME              "all"                       /**< short concise name of solver */
41   	#define NLPI_DESC              "NLP interface that uses all available NLP interfaces" /**< description of solver */
42   	#define NLPI_PRIORITY          -3000                       /**< priority of NLP solver */
43   	
44   	/*
45   	 * Data structures
46   	 */
47   	
48   	struct SCIP_NlpiData
49   	{
50   	   SCIP_NLPI**           nlpis;              /**< array containing all nlpis */
51   	   int                   nnlpis;             /**< total number of nlpis */
52   	};
53   	
54   	struct SCIP_NlpiProblem
55   	{
56   	   SCIP_NLPIPROBLEM**    nlpiproblems;       /**< array containing all nlpi problems */
57   	   int                   nnlpiproblems;      /**< total number of nlpi problems */
58   	   int                   bestidx;            /**< index of NLP solver with the best solution */
59   	};
60   	
61   	#ifdef SCIP_STATISTIC
62   	static int _nnlps = 0;                       /**< number of NLPs that have been solved */
63   	#endif
64   	
65   	/*
66   	 * Local methods
67   	 */
68   	
69   	/*
70   	 * Callback methods of NLP solver interface
71   	 */
72   	
73   	/** copy method of NLP interface (called when SCIP copies plugins) */
74   	static
75   	SCIP_DECL_NLPICOPY(nlpiCopyAll)
76   	{
77   	   /* include NLPI */
78   	   SCIP_CALL( SCIPincludeNlpSolverAll(scip) );
79   	
80   	   return SCIP_OKAY;  /*lint !e527*/
81   	}  /*lint !e715*/
82   	
83   	/** destructor of NLP interface to free nlpi data */
84   	static
85   	SCIP_DECL_NLPIFREE(nlpiFreeAll)
86   	{
87   	   assert(nlpi != NULL);
88   	   assert(nlpidata != NULL);
89   	   assert(*nlpidata != NULL);
90   	
91   	   SCIPfreeBlockMemoryArrayNull(scip, &(*nlpidata)->nlpis, (*nlpidata)->nnlpis);
92   	   SCIPfreeBlockMemory(scip, nlpidata);
93   	   assert(*nlpidata == NULL);
94   	
95   	   return SCIP_OKAY;  /*lint !e527*/
96   	}  /*lint !e715*/
97   	
98   	/** creates a problem instance */
99   	static
100  	SCIP_DECL_NLPICREATEPROBLEM(nlpiCreateProblemAll)
101  	{
102  	   SCIP_NLPIDATA* data;
103  	   int i;
104  	
105  	   assert(nlpi    != NULL);
106  	   assert(problem != NULL);
107  	
108  	   data = SCIPnlpiGetData(nlpi);
109  	   assert(data != NULL);
110  	
111  	   SCIP_CALL( SCIPallocClearBlockMemory(scip, problem) );
112  	
113  	   /* initialize problem */
114  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*problem)->nlpiproblems, data->nnlpis) );
115  	   (*problem)->nnlpiproblems = data->nnlpis;
116  	
117  	   for( i = 0; i < data->nnlpis; ++i )
118  	   {
119  	      assert(data->nlpis[i] != NULL);
120  	      SCIP_CALL( SCIPcreateNlpiProblem(scip, data->nlpis[i], &((*problem)->nlpiproblems[i]), name) );
121  	   }
122  	
123  	   return SCIP_OKAY;
124  	}  /*lint !e715*/
125  	
126  	/** free a problem instance */
127  	static
128  	SCIP_DECL_NLPIFREEPROBLEM(nlpiFreeProblemAll)
129  	{
130  	   SCIP_NLPIDATA* data;
131  	   int i;
132  	
133  	   assert(nlpi     != NULL);
134  	   assert(problem  != NULL);
135  	   assert(*problem != NULL);
136  	
137  	   data = SCIPnlpiGetData(nlpi);
138  	   assert(data != NULL);
139  	
140  	   for( i = 0; i < data->nnlpis; ++i )
141  	   {
142  	      assert(data->nlpis[i] != NULL);
143  	      SCIP_CALL( SCIPfreeNlpiProblem(scip, data->nlpis[i], &(*problem)->nlpiproblems[i]) );
144  	   }
145  	
146  	   SCIPfreeBlockMemoryArrayNull(scip, &(*problem)->nlpiproblems, data->nnlpis);
147  	   SCIPfreeBlockMemory(scip, problem);
148  	
149  	   return SCIP_OKAY;
150  	}  /*lint !e715*/
151  	
152  	/** add variables */
153  	static
154  	SCIP_DECL_NLPIADDVARS(nlpiAddVarsAll)
155  	{
156  	   SCIP_NLPIDATA* nlpidata;
157  	   int i;
158  	
159  	   nlpidata = SCIPnlpiGetData(nlpi);
160  	   assert(nlpidata != NULL);
161  	
162  	   for( i = 0; i < nlpidata->nnlpis; ++i )
163  	   {
164  	      assert(nlpidata->nlpis[i] != NULL);
165  	      assert(problem->nlpiproblems[i] != NULL);
166  	
167  	      SCIP_CALL( SCIPaddNlpiVars(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], nvars, lbs, ubs, varnames) );
168  	   }
169  	
170  	   return SCIP_OKAY;
171  	}  /*lint !e715*/
172  	
173  	
174  	/** add constraints */
175  	static
176  	SCIP_DECL_NLPIADDCONSTRAINTS(nlpiAddConstraintsAll)
177  	{
178  	   SCIP_NLPIDATA* nlpidata;
179  	   int i;
180  	
181  	   nlpidata = SCIPnlpiGetData(nlpi);
182  	   assert(nlpidata != NULL);
183  	
184  	   for( i = 0; i < nlpidata->nnlpis; ++i )
185  	   {
186  	      assert(nlpidata->nlpis[i] != NULL);
187  	      assert(problem->nlpiproblems[i] != NULL);
188  	
189  	      SCIP_CALL( SCIPaddNlpiConstraints(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], nconss, lhss, rhss,
190  	         nlininds, lininds, linvals, exprs, names) );
191  	   }
192  	
193  	   return SCIP_OKAY;
194  	}  /*lint !e715*/
195  	
196  	/** sets or overwrites objective, a minimization problem is expected */
197  	static
198  	SCIP_DECL_NLPISETOBJECTIVE(nlpiSetObjectiveAll)
199  	{
200  	   SCIP_NLPIDATA* nlpidata;
201  	   int i;
202  	
203  	   nlpidata = SCIPnlpiGetData(nlpi);
204  	   assert(nlpidata != NULL);
205  	
206  	   for( i = 0; i < nlpidata->nnlpis; ++i )
207  	   {
208  	      assert(nlpidata->nlpis[i] != NULL);
209  	      assert(problem->nlpiproblems[i] != NULL);
210  	
211  	      SCIP_CALL( SCIPsetNlpiObjective(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], nlins, lininds, linvals, expr, constant) );
212  	   }
213  	
214  	   return SCIP_OKAY;
215  	}  /*lint !e715*/
216  	
217  	/** change variable bounds */
218  	static
219  	SCIP_DECL_NLPICHGVARBOUNDS(nlpiChgVarBoundsAll)
220  	{
221  	   SCIP_NLPIDATA* nlpidata;
222  	   int i;
223  	
224  	   nlpidata = SCIPnlpiGetData(nlpi);
225  	   assert(nlpidata != NULL);
226  	
227  	   for( i = 0; i < nlpidata->nnlpis; ++i )
228  	   {
229  	      assert(nlpidata->nlpis[i] != NULL);
230  	      assert(problem->nlpiproblems[i] != NULL);
231  	
232  	      SCIP_CALL( SCIPchgNlpiVarBounds(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], nvars, indices, lbs, ubs) );
233  	   }
234  	
235  	   return SCIP_OKAY;
236  	}  /*lint !e715*/
237  	
238  	/** change constraint bounds */
239  	static
240  	SCIP_DECL_NLPICHGCONSSIDES(nlpiChgConsSidesAll)
241  	{
242  	   SCIP_NLPIDATA* nlpidata;
243  	   int i;
244  	
245  	   nlpidata = SCIPnlpiGetData(nlpi);
246  	   assert(nlpidata != NULL);
247  	
248  	   for( i = 0; i < nlpidata->nnlpis; ++i )
249  	   {
250  	      assert(nlpidata->nlpis[i] != NULL);
251  	      assert(problem->nlpiproblems[i] != NULL);
252  	
253  	      SCIP_CALL( SCIPchgNlpiConsSides(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], nconss, indices, lhss, rhss) );
254  	   }
255  	
256  	   return SCIP_OKAY;
257  	}  /*lint !e715*/
258  	
259  	/** delete a set of variables */
260  	static
261  	SCIP_DECL_NLPIDELVARSET(nlpiDelVarSetAll)
262  	{
263  	   SCIP_NLPIDATA* nlpidata;
264  	   int* tmpdstats;
265  	   int i;
266  	
267  	   nlpidata = SCIPnlpiGetData(nlpi);
268  	   assert(nlpidata != NULL);
269  	
270  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &tmpdstats, dstatssize) );
271  	
272  	   for( i = 0; i < nlpidata->nnlpis; ++i )
273  	   {
274  	      assert(nlpidata->nlpis[i] != NULL);
275  	      assert(problem->nlpiproblems[i] != NULL);
276  	
277  	      if( i < nlpidata->nnlpis -1 )
278  	      {
279  	         /* restore dstats entries */
280  	         BMScopyMemoryArray(tmpdstats, dstats, dstatssize);
281  	
282  	         SCIP_CALL( SCIPdelNlpiVarSet(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], tmpdstats, dstatssize) );
283  	      }
284  	      else
285  	      {
286  	         /* NOTE this works only when all dstats array are the same after calling the nlpidelvarset callback
287  	          * As long as all solvers use the SCIP NLPI oracle to store the NLP problem data, this is the case.
288  	          * @TODO Assert that the returned dstats are all the same?
289  	          */
290  	         SCIP_CALL( SCIPdelNlpiVarSet(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], dstats, dstatssize) );
291  	      }
292  	   }
293  	
294  	   SCIPfreeBlockMemoryArray(scip, &tmpdstats, dstatssize);
295  	
296  	   return SCIP_OKAY;
297  	}  /*lint !e715*/
298  	
299  	/** delete a set of constraints */
300  	static
301  	SCIP_DECL_NLPIDELCONSSET( nlpiDelConstraintSetAll )
302  	{
303  	   SCIP_NLPIDATA* nlpidata;
304  	   int* tmpdstats;
305  	   int i;
306  	
307  	   nlpidata = SCIPnlpiGetData(nlpi);
308  	   assert(nlpidata != NULL);
309  	
310  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &tmpdstats, dstatssize) );
311  	
312  	   for( i = 0; i < nlpidata->nnlpis; ++i )
313  	   {
314  	      assert(nlpidata->nlpis[i] != NULL);
315  	      assert(problem->nlpiproblems[i] != NULL);
316  	
317  	      if( i < nlpidata->nnlpis - 1 )
318  	      {
319  	         /* restore dstats entries */
320  	         BMScopyMemoryArray(tmpdstats, dstats, dstatssize);
321  	
322  	         SCIP_CALL( SCIPdelNlpiConsSet(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], tmpdstats, dstatssize) );
323  	      }
324  	      else
325  	      {
326  	         /* NOTE this works only when all dstats array are the same after calling the nlpidelconsset callback
327  	          * As long as all solvers use the SCIP NLPI oracle to store the NLP problem data, this is the case.
328  	          * @TODO Assert that the returned dstats are all the same?
329  	          */
330  	         SCIP_CALL( SCIPdelNlpiConsSet(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], dstats, dstatssize) );
331  	      }
332  	   }
333  	
334  	   SCIPfreeBlockMemoryArray(scip, &tmpdstats, dstatssize);
335  	
336  	   return SCIP_OKAY;
337  	}  /*lint !e715*/
338  	
339  	/** changes (or adds) linear coefficients in a constraint or objective */
340  	static
341  	SCIP_DECL_NLPICHGLINEARCOEFS(nlpiChgLinearCoefsAll)
342  	{
343  	   SCIP_NLPIDATA* nlpidata;
344  	   int i;
345  	
346  	   nlpidata = SCIPnlpiGetData(nlpi);
347  	   assert(nlpidata != NULL);
348  	
349  	   for( i = 0; i < nlpidata->nnlpis; ++i )
350  	   {
351  	      assert(nlpidata->nlpis[i] != NULL);
352  	      assert(problem->nlpiproblems[i] != NULL);
353  	
354  	      SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], idx, nvals, varidxs, vals) );
355  	   }
356  	
357  	   return SCIP_OKAY;
358  	}  /*lint !e715*/
359  	
360  	/** replaces the expression of a constraint or objective */
361  	static
362  	SCIP_DECL_NLPICHGEXPR(nlpiChgExprAll)
363  	{
364  	   SCIP_NLPIDATA* nlpidata;
365  	   int i;
366  	
367  	   nlpidata = SCIPnlpiGetData(nlpi);
368  	   assert(nlpidata != NULL);
369  	
370  	   for( i = 0; i < nlpidata->nnlpis; ++i )
371  	   {
372  	      assert(nlpidata->nlpis[i] != NULL);
373  	      assert(problem->nlpiproblems[i] != NULL);
374  	
375  	      SCIP_CALL( SCIPchgNlpiExpr(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], idxcons, expr) );
376  	   }
377  	
378  	   return SCIP_OKAY;
379  	}  /*lint !e715*/
380  	
381  	/** change the constant offset in the objective */
382  	static
383  	SCIP_DECL_NLPICHGOBJCONSTANT(nlpiChgObjConstantAll)
384  	{
385  	   SCIP_NLPIDATA* nlpidata;
386  	   int i;
387  	
388  	   nlpidata = SCIPnlpiGetData(nlpi);
389  	   assert(nlpidata != NULL);
390  	
391  	   for( i = 0; i < nlpidata->nnlpis; ++i )
392  	   {
393  	      assert(nlpidata->nlpis[i] != NULL);
394  	      assert(problem->nlpiproblems[i] != NULL);
395  	
396  	      SCIP_CALL( SCIPchgNlpiObjConstant(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], objconstant) );
397  	   }
398  	
399  	   return SCIP_OKAY;
400  	}  /*lint !e715*/
401  	
402  	/** sets initial guess for primal variables */
403  	static
404  	SCIP_DECL_NLPISETINITIALGUESS(nlpiSetInitialGuessAll)
405  	{
406  	   SCIP_NLPIDATA* nlpidata;
407  	   int i;
408  	
409  	   nlpidata = SCIPnlpiGetData(nlpi);
410  	   assert(nlpidata != NULL);
411  	
412  	   for( i = 0; i < nlpidata->nnlpis; ++i )
413  	   {
414  	      assert(nlpidata->nlpis[i] != NULL);
415  	      assert(problem->nlpiproblems[i] != NULL);
416  	
417  	      SCIP_CALL( SCIPsetNlpiInitialGuess(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], primalvalues, consdualvalues,
418  	            varlbdualvalues, varubdualvalues) );
419  	   }
420  	
421  	   return SCIP_OKAY;
422  	}  /*lint !e715*/
423  	
424  	/** tries to solve NLP */
425  	static
426  	SCIP_DECL_NLPISOLVE(nlpiSolveAll)
427  	{
428  	   SCIP_NLPIDATA* nlpidata;
429  	   SCIP_NLPTERMSTAT besttermstat;
430  	   SCIP_NLPSOLSTAT bestsolstat;
431  	   SCIP_Real bestsolval;
432  	   int i;
433  	
434  	   nlpidata = SCIPnlpiGetData(nlpi);
435  	   assert(nlpidata != NULL);
436  	
437  	   /* use first solver per default */
438  	   problem->bestidx = 0;
439  	
440  	   /* initialize best solution values */
441  	   besttermstat = SCIP_NLPTERMSTAT_OTHER;
442  	   bestsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
443  	   bestsolval = SCIPinfinity(scip);
444  	
445  	   for( i = 0; i < nlpidata->nnlpis; ++i )
446  	   {
447  	      SCIP_NLPTERMSTAT termstat;
448  	      SCIP_NLPSOLSTAT solstat;
449  	      SCIP_Real solval;
450  	      SCIP_Bool update;
451  	
452  	      assert(nlpidata->nlpis[i] != NULL);
453  	      assert(problem->nlpiproblems[i] != NULL);
454  	
455  	      /* solve NLP */
456  	      SCIP_CALL( SCIPsolveNlpiParam(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], param) );
457  	
458  	      termstat = SCIPgetNlpiTermstat(scip, nlpidata->nlpis[i], problem->nlpiproblems[i]);
459  	      solstat = SCIPgetNlpiSolstat(scip, nlpidata->nlpis[i], problem->nlpiproblems[i]);
460  	      solval = SCIPinfinity(scip);
461  	      update = FALSE;
462  	
463  	      /* collect solution value */
464  	      if( solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
465  	      {
466  	         SCIP_CALL( SCIPgetNlpiSolution(scip, nlpidata->nlpis[i], problem->nlpiproblems[i],
467  	               NULL, NULL, NULL, NULL, &solval) );
468  	         assert(!SCIPisInfinity(scip, solval));
469  	      }
470  	
471  	      /* better termination status -> update best solver */
472  	      if( termstat < besttermstat )
473  	         update = TRUE;
474  	
475  	      /* no feasible solutions have been found so far -> update best solver */
476  	      else if( bestsolstat >= SCIP_NLPSOLSTAT_LOCINFEASIBLE && solstat <= SCIP_NLPSOLSTAT_LOCINFEASIBLE )
477  	         update = TRUE;
478  	
479  	      /* use solver with the better solution value */
480  	      else if( solval < bestsolval )
481  	         update = TRUE;
482  	
483  	      /* update best solver */
484  	      if( update )
485  	      {
486  	         besttermstat = termstat;
487  	         bestsolstat = solstat;
488  	         bestsolval = solval;
489  	         problem->bestidx = i;
490  	      }
491  	
492  	#ifdef SCIP_STATISTIC
493  	      {
494  	         SCIP_NLPSTATISTICS stats;
495  	
496  	         SCIP_CALL( SCIPgetNlpiStatistics(scip, nlpidata->nlpis[i], problem->nlpiproblems[i], &stats) );
497  	
498  	         SCIPstatisticMessage("%d solver %s termstat %d solstat %d solval %e iters %d time %g\n",
499  	            _nnlps, SCIPnlpiGetName(nlpidata->nlpis[i]), termstat, solstat, solval,
500  	            stats.niterations, stats.totaltime);
501  	      }
502  	#endif
503  	
504  	      /* don't try more NLP solvers if allowed time is exceeded or SCIP is asked to interrupt */
505  	      if( termstat == SCIP_NLPTERMSTAT_TIMELIMIT || termstat == SCIP_NLPTERMSTAT_INTERRUPT )
506  	         break;
507  	   }
508  	
509  	#ifdef SCIP_STATISTIC
510  	   ++_nnlps;
511  	#endif
512  	
513  	   return SCIP_OKAY;
514  	}  /*lint !e715*/
515  	
516  	/** gives solution status */
517  	static
518  	SCIP_DECL_NLPIGETSOLSTAT(nlpiGetSolstatAll)
519  	{
520  	   SCIP_NLPIDATA* nlpidata;
521  	
522  	   nlpidata = SCIPnlpiGetData(nlpi);
523  	   assert(nlpidata != NULL);
524  	   assert(nlpidata->nlpis != NULL);
525  	   assert(nlpidata->nlpis[problem->bestidx] != NULL);
526  	   assert(problem->nlpiproblems != NULL);
527  	   assert(problem->nlpiproblems[problem->bestidx] != NULL);
528  	
529  	   /* return the solution status of the first nlpi */
530  	   return SCIPgetNlpiSolstat(scip, nlpidata->nlpis[problem->bestidx], problem->nlpiproblems[problem->bestidx]);
531  	}
532  	
533  	/** gives termination reason */
534  	static
535  	SCIP_DECL_NLPIGETTERMSTAT(nlpiGetTermstatAll)
536  	{
537  	   SCIP_NLPIDATA* nlpidata;
538  	
539  	   nlpidata = SCIPnlpiGetData(nlpi);
540  	   assert(nlpidata != NULL);
541  	   assert(nlpidata->nlpis != NULL);
542  	   assert(nlpidata->nlpis[problem->bestidx] != NULL);
543  	   assert(problem->nlpiproblems != NULL);
544  	   assert(problem->nlpiproblems[problem->bestidx] != NULL);
545  	
546  	   /* return the solution status of the first nlpi */
547  	   return SCIPgetNlpiTermstat(scip, nlpidata->nlpis[problem->bestidx], problem->nlpiproblems[problem->bestidx]);
548  	}
549  	
550  	/** gives primal and dual solution values */
551  	static
552  	SCIP_DECL_NLPIGETSOLUTION(nlpiGetSolutionAll)
553  	{
554  	   SCIP_NLPIDATA* nlpidata;
555  	
556  	   nlpidata = SCIPnlpiGetData(nlpi);
557  	   assert(nlpidata != NULL);
558  	   assert(nlpidata->nlpis != NULL);
559  	   assert(nlpidata->nlpis[problem->bestidx] != NULL);
560  	   assert(problem->nlpiproblems != NULL);
561  	   assert(problem->nlpiproblems[problem->bestidx] != NULL);
562  	
563  	   /* return the solution status of the first nlpi */
564  	   SCIP_CALL( SCIPgetNlpiSolution(scip, nlpidata->nlpis[problem->bestidx], problem->nlpiproblems[problem->bestidx],
565  	         primalvalues, consdualvalues, varlbdualvalues, varubdualvalues, objval) );
566  	
567  	   return SCIP_OKAY;
568  	}
569  	
570  	/** gives solve statistics */
571  	static
572  	SCIP_DECL_NLPIGETSTATISTICS(nlpiGetStatisticsAll)
573  	{
574  	   SCIP_NLPIDATA* nlpidata;
575  	
576  	   nlpidata = SCIPnlpiGetData(nlpi);
577  	   assert(nlpidata != NULL);
578  	   assert(nlpidata->nlpis != NULL);
579  	   assert(nlpidata->nlpis[problem->bestidx] != NULL);
580  	   assert(problem->nlpiproblems != NULL);
581  	   assert(problem->nlpiproblems[problem->bestidx] != NULL);
582  	
583  	   /* collect statistics of the first solver */
584  	   SCIP_CALL( SCIPgetNlpiStatistics(scip, nlpidata->nlpis[problem->bestidx], problem->nlpiproblems[problem->bestidx],
585  	         statistics) );
586  	
587  	   return SCIP_OKAY;
588  	}  /*lint !e715*/
589  	
590  	/*
591  	 * NLP solver interface specific interface methods
592  	 */
593  	
594  	/** create solver interface for the solver "All" and includes it into SCIP, if at least 2 NLPIs have already been included
595  	 *
596  	 * This method should be called after all other NLP solver interfaces have been included.
597  	 */
598  	SCIP_RETCODE SCIPincludeNlpSolverAll(
599  	   SCIP*                 scip                /**< SCIP data structure */
600  	   )
601  	{
602  	   SCIP_NLPIDATA* nlpidata;
603  	   int i;
604  	
605  	   assert(scip != NULL);
606  	
607  	   /* the number of NLPIs so far must be >= 2 */
608  	   if( SCIPgetNNlpis(scip) < 2 )
609  	      return SCIP_OKAY;
610  	
611  	   /* create all solver interface data */
612  	   SCIP_CALL( SCIPallocClearBlockMemory(scip, &nlpidata) );
613  	
614  	   nlpidata->nnlpis = SCIPgetNNlpis(scip);
615  	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &nlpidata->nlpis, nlpidata->nnlpis) );
616  	
617  	   /* copy nlpi pointers TODO should not need that */
618  	   for( i = 0; i < nlpidata->nnlpis; ++i )
619  	      nlpidata->nlpis[i] = SCIPgetNlpis(scip)[i];
620  	
621  	   /* create solver interface */
622  	   SCIP_CALL( SCIPincludeNlpi(scip,
623  	         NLPI_NAME, NLPI_DESC, NLPI_PRIORITY,
624  	         nlpiCopyAll, nlpiFreeAll, NULL,
625  	         nlpiCreateProblemAll, nlpiFreeProblemAll, NULL,
626  	         nlpiAddVarsAll, nlpiAddConstraintsAll, nlpiSetObjectiveAll,
627  	         nlpiChgVarBoundsAll, nlpiChgConsSidesAll, nlpiDelVarSetAll, nlpiDelConstraintSetAll,
628  	         nlpiChgLinearCoefsAll, nlpiChgExprAll,
629  	         nlpiChgObjConstantAll, nlpiSetInitialGuessAll, nlpiSolveAll, nlpiGetSolstatAll, nlpiGetTermstatAll,
630  	         nlpiGetSolutionAll, nlpiGetStatisticsAll,
631  	         nlpidata) );
632  	
633  	   return SCIP_OKAY;
634  	}
635