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
(16) Event overrun-local: |
Overrunning array "nlpi->ntermstat" of 10 4-byte elements at element index 15 (byte offset 63) using index "(*nlpi->nlpigettermstat)(set->scip, nlpi, problem)" (which evaluates to 15). |
580 ++nlpi->ntermstat[nlpi->nlpigettermstat(set->scip, nlpi, problem)];
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