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