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