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 nlhdlr.c 26 * @ingroup OTHER_CFILES 27 * @brief functions for nonlinearity handlers of nonlinear constraint handler 28 * @author Ksenia Bestuzheva 29 * @author Benjamin Mueller 30 * @author Felipe Serrano 31 * @author Stefan Vigerske 32 */ 33 34 #include <assert.h> 35 36 #include "scip/pub_nlhdlr.h" 37 #include "scip/nlhdlr.h" 38 #include "scip/struct_nlhdlr.h" 39 #include "scip/scip_timing.h" 40 #include "scip/scip_mem.h" 41 #include "scip/scip_param.h" 42 #include "scip/scip_message.h" 43 #include "scip/pub_misc.h" 44 45 /**@addtogroup PublicNlhdlrInterfaceMethods 46 * @{ 47 */ 48 49 #ifdef NDEBUG 50 /* Undo the defines from pub_nlhdlr.h, which exist if NDEBUG is defined. */ 51 #undef SCIPnlhdlrSetCopyHdlr 52 #undef SCIPnlhdlrSetFreeHdlrData 53 #undef SCIPnlhdlrSetFreeExprData 54 #undef SCIPnlhdlrSetInitExit 55 #undef SCIPnlhdlrSetProp 56 #undef SCIPnlhdlrSetSepa 57 #undef SCIPnlhdlrSetSollinearize 58 #undef SCIPnlhdlrGetName 59 #undef SCIPnlhdlrGetDesc 60 #undef SCIPnlhdlrGetDetectPriority 61 #undef SCIPnlhdlrGetEnfoPriority 62 #undef SCIPnlhdlrIsEnabled 63 #undef SCIPnlhdlrGetData 64 #undef SCIPnlhdlrHasIntEval 65 #undef SCIPnlhdlrHasReverseProp 66 #undef SCIPnlhdlrHasInitSepa 67 #undef SCIPnlhdlrHasExitSepa 68 #undef SCIPnlhdlrHasEnfo 69 #undef SCIPnlhdlrHasEstimate 70 #undef SCIPnlhdlrHasSollinearize 71 #endif 72 73 /** sets the copy handler callback of a nonlinear handler */ 74 void SCIPnlhdlrSetCopyHdlr( 75 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 76 SCIP_DECL_NLHDLRCOPYHDLR((*copy)) /**< copy callback (can be NULL) */ 77 ) 78 { 79 assert(nlhdlr != NULL); 80 81 nlhdlr->copyhdlr = copy; 82 } 83 84 /** sets the nonlinear handler callback to free the nonlinear handler data */ 85 void SCIPnlhdlrSetFreeHdlrData( 86 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 87 SCIP_DECL_NLHDLRFREEHDLRDATA((*freehdlrdata)) /**< handler free callback (can be NULL) */ 88 ) 89 { 90 assert(nlhdlr != NULL); 91 92 nlhdlr->freehdlrdata = freehdlrdata; 93 } 94 95 /** sets the nonlinear handler callback to free expression specific data of nonlinear handler */ 96 void SCIPnlhdlrSetFreeExprData( 97 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 98 SCIP_DECL_NLHDLRFREEEXPRDATA((*freeexprdata)) /**< nonlinear handler expression data free callback 99 * (can be NULL if data does not need to be freed) */ 100 ) 101 { 102 assert(nlhdlr != NULL); 103 104 nlhdlr->freeexprdata = freeexprdata; 105 } 106 107 /** sets the initialization and deinitialization callback of a nonlinear handler */ 108 void SCIPnlhdlrSetInitExit( 109 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 110 SCIP_DECL_NLHDLRINIT((*init)), /**< initialization callback (can be NULL) */ 111 SCIP_DECL_NLHDLREXIT((*exit_)) /**< deinitialization callback (can be NULL) */ 112 ) 113 { 114 assert(nlhdlr != NULL); 115 116 nlhdlr->init = init; 117 nlhdlr->exit = exit_; 118 } 119 120 /** sets the propagation callbacks of a nonlinear handler */ 121 void SCIPnlhdlrSetProp( 122 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 123 SCIP_DECL_NLHDLRINTEVAL((*inteval)), /**< interval evaluation callback (can be NULL) */ 124 SCIP_DECL_NLHDLRREVERSEPROP((*reverseprop)) /**< reverse propagation callback (can be NULL) */ 125 ) 126 { 127 assert(nlhdlr != NULL); 128 129 nlhdlr->inteval = inteval; 130 nlhdlr->reverseprop = reverseprop; 131 } 132 133 /** sets the enforcement callbacks of a nonlinear handler */ 134 void SCIPnlhdlrSetSepa( 135 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 136 SCIP_DECL_NLHDLRINITSEPA((*initsepa)), /**< separation initialization callback (can be NULL) */ 137 SCIP_DECL_NLHDLRENFO((*enfo)), /**< enforcement callback (can be NULL if estimate is not NULL) */ 138 SCIP_DECL_NLHDLRESTIMATE((*estimate)), /**< estimation callback (can be NULL if sepa is not NULL) */ 139 SCIP_DECL_NLHDLREXITSEPA((*exitsepa)) /**< separation deinitialization callback (can be NULL) */ 140 ) 141 { 142 assert(nlhdlr != NULL); 143 assert(enfo != NULL || estimate != NULL); 144 145 nlhdlr->initsepa = initsepa; 146 nlhdlr->enfo = enfo; 147 nlhdlr->estimate = estimate; 148 nlhdlr->exitsepa = exitsepa; 149 } 150 151 /** sets the solution linearization callback of a nonlinear handler */ 152 void SCIPnlhdlrSetSollinearize( 153 SCIP_NLHDLR* nlhdlr, /**< nonlinear handler */ 154 SCIP_DECL_NLHDLRSOLLINEARIZE((*sollinearize)) /**< solution linearization callback */ 155 ) 156 { 157 assert(nlhdlr != NULL); 158 assert(sollinearize != NULL); 159 160 nlhdlr->sollinearize = sollinearize; 161 } 162 163 /** gives name of nonlinear handler */ 164 const char* SCIPnlhdlrGetName( 165 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 166 ) 167 { 168 assert(nlhdlr != NULL); 169 170 return nlhdlr->name; 171 } 172 173 /** gives description of nonlinear handler, can be NULL */ 174 const char* SCIPnlhdlrGetDesc( 175 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 176 ) 177 { 178 assert(nlhdlr != NULL); 179 180 return nlhdlr->desc; 181 } 182 183 /** gives detection priority of nonlinear handler */ 184 int SCIPnlhdlrGetDetectPriority( 185 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 186 ) 187 { 188 assert(nlhdlr != NULL); 189 190 return nlhdlr->detectpriority; 191 } 192 193 /** gives enforcement priority of nonlinear handler */ 194 int SCIPnlhdlrGetEnfoPriority( 195 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 196 ) 197 { 198 assert(nlhdlr != NULL); 199 200 return nlhdlr->enfopriority; 201 } 202 203 /** returns whether nonlinear handler is enabled */ 204 SCIP_Bool SCIPnlhdlrIsEnabled( 205 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 206 ) 207 { 208 assert(nlhdlr != NULL); 209 210 return nlhdlr->enabled; 211 } 212 213 /** gives handler data of nonlinear handler */ 214 SCIP_NLHDLRDATA* SCIPnlhdlrGetData( 215 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 216 ) 217 { 218 assert(nlhdlr != NULL); 219 220 return nlhdlr->data; 221 } 222 223 /** returns whether nonlinear handler implements the interval evaluation callback */ 224 SCIP_Bool SCIPnlhdlrHasIntEval( 225 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 226 ) 227 { 228 assert(nlhdlr != NULL); 229 230 return nlhdlr->inteval != NULL; 231 } 232 233 /** returns whether nonlinear handler implements the reverse propagation callback */ 234 SCIP_Bool SCIPnlhdlrHasReverseProp( 235 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 236 ) 237 { 238 assert(nlhdlr != NULL); 239 240 return nlhdlr->reverseprop != NULL; 241 } 242 243 /** returns whether nonlinear handler implements the separation initialization callback */ 244 SCIP_Bool SCIPnlhdlrHasInitSepa( 245 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 246 ) 247 { 248 assert(nlhdlr != NULL); 249 250 return nlhdlr->initsepa != NULL; 251 } 252 253 /** returns whether nonlinear handler implements the separation deinitialization callback */ 254 SCIP_Bool SCIPnlhdlrHasExitSepa( 255 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 256 ) 257 { 258 assert(nlhdlr != NULL); 259 260 return nlhdlr->exitsepa != NULL; 261 } 262 263 /** returns whether nonlinear handler implements the enforcement callback */ 264 SCIP_Bool SCIPnlhdlrHasEnfo( 265 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 266 ) 267 { 268 assert(nlhdlr != NULL); 269 270 return nlhdlr->enfo != NULL; 271 } 272 273 /** returns whether nonlinear handler implements the estimator callback */ 274 SCIP_Bool SCIPnlhdlrHasEstimate( 275 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 276 ) 277 { 278 assert(nlhdlr != NULL); 279 280 return nlhdlr->estimate != NULL; 281 } 282 283 /** returns whether nonlinear handler implements the solution linearization callback */ 284 SCIP_Bool SCIPnlhdlrHasSollinearize( 285 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 286 ) 287 { 288 assert(nlhdlr != NULL); 289 290 return nlhdlr->sollinearize != NULL; 291 } 292 293 /** compares two nonlinear handlers by detection priority 294 * 295 * if handlers have same detection priority, then compare by name 296 */ 297 SCIP_DECL_SORTPTRCOMP(SCIPnlhdlrComp) 298 { 299 SCIP_NLHDLR* h1; 300 SCIP_NLHDLR* h2; 301 302 assert(elem1 != NULL); 303 assert(elem2 != NULL); 304 305 h1 = (SCIP_NLHDLR*)elem1; 306 h2 = (SCIP_NLHDLR*)elem2; 307 308 if( h1->detectpriority != h2->detectpriority ) 309 return h1->detectpriority - h2->detectpriority; 310 311 return strcmp(h1->name, h2->name); 312 } 313 314 #ifdef SCIP_DISABLED_CODE 315 /** compares nonlinear handler by enforcement priority 316 * 317 * if handlers have same enforcement priority, then compare by detection priority, then by name 318 */ 319 SCIP_DECL_SORTPTRCOMP(SCIPnlhdlrCompEnfo) 320 { 321 SCIP_NLHDLR* h1; 322 SCIP_NLHDLR* h2; 323 324 assert(elem1 != NULL); 325 assert(elem2 != NULL); 326 327 h1 = (SCIP_NLHDLR*)elem1; 328 h2 = (SCIP_NLHDLR*)elem2; 329 330 if( h1->enfopriority != h2->enfopriority ) 331 return h1->enfopriority - h2->enfopriority; 332 333 if( h1->detectpriority != h2->detectpriority ) 334 return h1->detectpriority - h2->detectpriority; 335 336 return strcmp(h1->name, h2->name); 337 } 338 #endif 339 340 /** @} */ 341 342 /* nlhdlr private API functions from nlhdlr.h */ 343 344 #ifndef NDEBUG 345 #undef SCIPnlhdlrResetNDetectionslast 346 #undef SCIPnlhdlrIncrementNCutoffs 347 #undef SCIPnlhdlrIncrementNSeparated 348 #endif 349 350 /** creates a nonlinear handler */ 351 SCIP_RETCODE SCIPnlhdlrCreate( 352 SCIP* scip, /**< SCIP data structure */ 353 SCIP_NLHDLR** nlhdlr, /**< buffer to store pointer to created nonlinear handler */ 354 const char* name, /**< name of nonlinear handler (must not be NULL) */ 355 const char* desc, /**< description of nonlinear handler (can be NULL) */ 356 int detectpriority, /**< detection priority of nonlinear handler */ 357 int enfopriority, /**< enforcement priority of nonlinear handler */ 358 SCIP_DECL_NLHDLRDETECT((*detect)), /**< structure detection callback of nonlinear handler */ 359 SCIP_DECL_NLHDLREVALAUX((*evalaux)), /**< auxiliary evaluation callback of nonlinear handler */ 360 SCIP_NLHDLRDATA* nlhdlrdata /**< data of nonlinear handler (can be NULL) */ 361 ) 362 { 363 char paramname[SCIP_MAXSTRLEN]; 364 365 assert(scip != NULL); 366 assert(nlhdlr != NULL); 367 assert(name != NULL); 368 assert(detect != NULL); 369 assert(evalaux != NULL); 370 371 SCIP_CALL( SCIPallocClearBlockMemory(scip, nlhdlr) ); 372 373 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*nlhdlr)->name, name, strlen(name)+1) ); 374 if( desc != NULL ) 375 { 376 SCIP_CALL_FINALLY( SCIPduplicateMemoryArray(scip, &(*nlhdlr)->desc, desc, strlen(desc)+1), 377 SCIPfreeMemoryArray(scip, &(*nlhdlr)->name) ); 378 } 379 380 (*nlhdlr)->detectpriority = detectpriority; 381 (*nlhdlr)->enfopriority = enfopriority; 382 (*nlhdlr)->data = nlhdlrdata; 383 (*nlhdlr)->detect = detect; 384 (*nlhdlr)->evalaux = evalaux; 385 386 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->detecttime) ); 387 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->enfotime) ); 388 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->proptime) ); 389 SCIP_CALL( SCIPcreateClock(scip, &(*nlhdlr)->intevaltime) ); 390 391 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "nlhdlr/%s/enabled", name); 392 SCIP_CALL( SCIPaddBoolParam(scip, paramname, "should this nonlinear handler be used", 393 &(*nlhdlr)->enabled, FALSE, TRUE, NULL, NULL) ); 394 395 return SCIP_OKAY; 396 } 397 398 /** frees a nonlinear handler */ 399 SCIP_RETCODE SCIPnlhdlrFree( 400 SCIP* scip, /**< SCIP data structure */ 401 SCIP_NLHDLR** nlhdlr /**< pointer to nonlinear handler to be freed */ 402 ) 403 { 404 assert(nlhdlr != NULL); 405 assert(*nlhdlr != NULL); 406 407 if( (*nlhdlr)->freehdlrdata != NULL ) 408 { 409 SCIP_CALL( (*nlhdlr)->freehdlrdata(scip, *nlhdlr, &(*nlhdlr)->data) ); 410 } 411 412 /* free clocks */ 413 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->detecttime) ); 414 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->enfotime) ); 415 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->proptime) ); 416 SCIP_CALL( SCIPfreeClock(scip, &(*nlhdlr)->intevaltime) ); 417 418 SCIPfreeMemory(scip, &(*nlhdlr)->name); 419 SCIPfreeMemoryNull(scip, &(*nlhdlr)->desc); 420 421 SCIPfreeBlockMemory(scip, nlhdlr); 422 423 return SCIP_OKAY; 424 } 425 426 /** call the handler copy callback of a nonlinear handler */ 427 SCIP_DECL_NLHDLRCOPYHDLR(SCIPnlhdlrCopyhdlr) 428 { 429 /* TODO for now just don't copy disabled nlhdlr, a clean way would probably be to first copy and disable then */ 430 if( sourcenlhdlr->copyhdlr != NULL && sourcenlhdlr->enabled ) 431 { 432 SCIP_CALL( sourcenlhdlr->copyhdlr(targetscip, targetconshdlr, sourceconshdlr, sourcenlhdlr) ); 433 } 434 435 return SCIP_OKAY; 436 } 437 438 /** call the free expression specific data callback of a nonlinear handler */ 439 SCIP_DECL_NLHDLRFREEEXPRDATA(SCIPnlhdlrFreeexprdata) 440 { 441 assert(nlhdlr != NULL); 442 assert(nlhdlrexprdata != NULL); 443 assert(*nlhdlrexprdata != NULL); 444 445 if( nlhdlr->freeexprdata != NULL ) 446 { 447 SCIP_CALL( nlhdlr->freeexprdata(scip, nlhdlr, expr, nlhdlrexprdata) ); 448 assert(*nlhdlrexprdata == NULL); 449 } 450 451 return SCIP_OKAY; 452 } 453 454 /** call the initialization callback of a nonlinear handler */ 455 SCIP_DECL_NLHDLRINIT(SCIPnlhdlrInit) 456 { 457 assert(nlhdlr != NULL); 458 459 nlhdlr->nenfocalls = 0; 460 nlhdlr->nintevalcalls = 0; 461 nlhdlr->npropcalls = 0; 462 nlhdlr->nseparated = 0; 463 nlhdlr->ncutoffs = 0; 464 nlhdlr->ndomreds = 0; 465 nlhdlr->nbranchscores = 0; 466 nlhdlr->ndetections = 0; 467 nlhdlr->ndetectionslast = 0; 468 469 SCIP_CALL( SCIPresetClock(scip, nlhdlr->detecttime) ); 470 SCIP_CALL( SCIPresetClock(scip, nlhdlr->enfotime) ); 471 SCIP_CALL( SCIPresetClock(scip, nlhdlr->proptime) ); 472 SCIP_CALL( SCIPresetClock(scip, nlhdlr->intevaltime) ); 473 474 if( nlhdlr->init != NULL ) 475 { 476 SCIP_CALL( nlhdlr->init(scip, nlhdlr) ); 477 } 478 479 return SCIP_OKAY; 480 } 481 482 /** call the deinitialization callback of a nonlinear handler */ 483 SCIP_DECL_NLHDLREXIT(SCIPnlhdlrExit) 484 { 485 assert(nlhdlr != NULL); 486 487 if( nlhdlr->exit != NULL ) 488 { 489 SCIP_CALL( nlhdlr->exit(scip, nlhdlr) ); 490 } 491 492 return SCIP_OKAY; 493 } 494 495 /** call the detect callback of a nonlinear handler */ 496 SCIP_DECL_NLHDLRDETECT(SCIPnlhdlrDetect) 497 { 498 assert(scip != NULL); 499 assert(nlhdlr != NULL); 500 assert(nlhdlr->detect != NULL); 501 assert(nlhdlr->detecttime != NULL); 502 assert(participating != NULL); 503 504 SCIP_CALL( SCIPstartClock(scip, nlhdlr->detecttime) ); 505 SCIP_CALL( nlhdlr->detect(scip, conshdlr, nlhdlr, expr, cons, enforcing, participating, nlhdlrexprdata) ); 506 SCIP_CALL( SCIPstopClock(scip, nlhdlr->detecttime) ); 507 508 if( *participating != SCIP_NLHDLR_METHOD_NONE ) 509 { 510 ++nlhdlr->ndetections; 511 ++nlhdlr->ndetectionslast; 512 } 513 514 return SCIP_OKAY; 515 } 516 517 /** call the auxiliary evaluation callback of a nonlinear handler */ 518 SCIP_DECL_NLHDLREVALAUX(SCIPnlhdlrEvalaux) 519 { 520 assert(nlhdlr != NULL); 521 assert(nlhdlr->evalaux != NULL); 522 523 SCIP_CALL( nlhdlr->evalaux(scip, nlhdlr, expr, nlhdlrexprdata, auxvalue, sol) ); 524 525 return SCIP_OKAY; 526 } 527 528 /** call the interval evaluation callback of a nonlinear handler */ 529 SCIP_DECL_NLHDLRINTEVAL(SCIPnlhdlrInteval) 530 { 531 assert(scip != NULL); 532 assert(nlhdlr != NULL); 533 assert(nlhdlr->intevaltime != NULL); 534 535 if( nlhdlr->inteval != NULL ) 536 { 537 SCIP_CALL( SCIPstartClock(scip, nlhdlr->intevaltime) ); 538 SCIP_CALL( nlhdlr->inteval(scip, nlhdlr, expr, nlhdlrexprdata, interval, intevalvar, intevalvardata) ); 539 SCIP_CALL( SCIPstopClock(scip, nlhdlr->intevaltime) ); 540 541 ++nlhdlr->nintevalcalls; 542 } 543 544 return SCIP_OKAY; 545 } 546 547 /** call the reverse propagation callback of a nonlinear handler */ 548 SCIP_DECL_NLHDLRREVERSEPROP(SCIPnlhdlrReverseprop) 549 { 550 assert(scip != NULL); 551 assert(nlhdlr != NULL); 552 assert(nlhdlr->proptime != NULL); 553 assert(infeasible != NULL); 554 assert(nreductions != NULL); 555 556 if( nlhdlr->reverseprop == NULL ) 557 { 558 *infeasible = FALSE; 559 *nreductions = 0; 560 561 return SCIP_OKAY; 562 } 563 564 SCIP_CALL( SCIPstartClock(scip, nlhdlr->proptime) ); 565 SCIP_CALL( nlhdlr->reverseprop(scip, conshdlr, nlhdlr, expr, nlhdlrexprdata, bounds, infeasible, nreductions) ); 566 SCIP_CALL( SCIPstopClock(scip, nlhdlr->proptime) ); 567 568 /* update statistics */ 569 nlhdlr->ndomreds += *nreductions; 570 if( *infeasible ) 571 ++nlhdlr->ncutoffs; 572 ++nlhdlr->npropcalls; 573 574 return SCIP_OKAY; 575 } 576 577 /** call the separation initialization callback of a nonlinear handler */ 578 SCIP_DECL_NLHDLRINITSEPA(SCIPnlhdlrInitsepa) 579 { 580 assert(scip != NULL); 581 assert(nlhdlr != NULL); 582 assert(nlhdlr->enfotime != NULL); 583 assert(infeasible != NULL); 584 585 if( nlhdlr->initsepa == NULL ) 586 { 587 *infeasible = FALSE; 588 return SCIP_OKAY; 589 } 590 591 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) ); 592 SCIP_CALL( nlhdlr->initsepa(scip, conshdlr, cons, nlhdlr, expr, nlhdlrexprdata, overestimate, underestimate, infeasible) ); 593 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) ); 594 595 ++nlhdlr->nenfocalls; 596 if( *infeasible ) 597 ++nlhdlr->ncutoffs; 598 599 return SCIP_OKAY; 600 } 601 602 /** call the separation deinitialization callback of a nonlinear handler */ 603 SCIP_DECL_NLHDLREXITSEPA(SCIPnlhdlrExitsepa) 604 { 605 assert(scip != NULL); 606 assert(nlhdlr != NULL); 607 assert(nlhdlr->enfotime != NULL); 608 609 if( nlhdlr->exitsepa != NULL ) 610 { 611 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) ); 612 SCIP_CALL( nlhdlr->exitsepa(scip, nlhdlr, expr, nlhdlrexprdata) ); 613 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) ); 614 } 615 616 return SCIP_OKAY; 617 } 618 619 /** call the enforcement callback of a nonlinear handler */ 620 SCIP_DECL_NLHDLRENFO(SCIPnlhdlrEnfo) 621 { 622 assert(scip != NULL); 623 assert(nlhdlr != NULL); 624 assert(nlhdlr->enfotime != NULL); 625 assert(result != NULL); 626 627 if( nlhdlr->enfo == NULL ) 628 { 629 *result = SCIP_DIDNOTRUN; 630 return SCIP_OKAY; 631 } 632 633 #ifndef NDEBUG 634 /* check that auxvalue is correct by reevaluating */ 635 { 636 SCIP_Real auxvaluetest; 637 SCIP_CALL( SCIPnlhdlrEvalaux(scip, nlhdlr, expr, nlhdlrexprdata, &auxvaluetest, sol) ); 638 /* we should get EXACTLY the same value from calling evalaux with the same solution as before */ 639 assert(auxvalue == auxvaluetest); /*lint !e777*/ 640 } 641 #endif 642 643 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) ); 644 SCIP_CALL( nlhdlr->enfo(scip, conshdlr, cons, nlhdlr, expr, nlhdlrexprdata, sol, auxvalue, 645 overestimate, allowweakcuts, separated, addbranchscores, result) ); 646 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) ); 647 648 /* update statistics */ 649 ++nlhdlr->nenfocalls; 650 switch( *result ) 651 { 652 case SCIP_SEPARATED : 653 ++nlhdlr->nseparated; 654 break; 655 case SCIP_BRANCHED: 656 ++nlhdlr->nbranchscores; 657 break; 658 case SCIP_CUTOFF: 659 ++nlhdlr->ncutoffs; 660 break; 661 case SCIP_REDUCEDDOM: 662 ++nlhdlr->ndomreds; 663 break; 664 default: ; 665 } /*lint !e788*/ 666 667 return SCIP_OKAY; 668 } 669 670 /** call the estimator callback of a nonlinear handler */ 671 SCIP_DECL_NLHDLRESTIMATE(SCIPnlhdlrEstimate) 672 { 673 assert(scip != NULL); 674 assert(nlhdlr != NULL); 675 assert(nlhdlr->enfotime != NULL); 676 assert(success != NULL); 677 assert(addedbranchscores != NULL); 678 679 if( nlhdlr->estimate == NULL ) 680 { 681 *success = FALSE; 682 *addedbranchscores = FALSE; 683 return SCIP_OKAY; 684 } 685 686 #ifndef NDEBUG 687 /* check that auxvalue is correct by reevaluating */ 688 { 689 SCIP_Real auxvaluetest; 690 SCIP_CALL( SCIPnlhdlrEvalaux(scip, nlhdlr, expr, nlhdlrexprdata, &auxvaluetest, sol) ); 691 /* we should get EXACTLY the same value from calling evalaux with the same solution as before */ 692 assert(auxvalue == auxvaluetest); /*lint !e777*/ 693 } 694 #endif 695 696 SCIP_CALL( SCIPstartClock(scip, nlhdlr->enfotime) ); 697 SCIP_CALL( nlhdlr->estimate(scip, conshdlr, nlhdlr, expr, nlhdlrexprdata, sol, auxvalue, overestimate, targetvalue, addbranchscores, rowpreps, success, addedbranchscores) ); 698 SCIP_CALL( SCIPstopClock(scip, nlhdlr->enfotime) ); 699 700 /* update statistics */ 701 ++nlhdlr->nenfocalls; 702 703 return SCIP_OKAY; 704 } 705 706 /** call the solution notification callback of a nonlinear handler */ 707 SCIP_DECL_NLHDLRSOLLINEARIZE(SCIPnlhdlrSollinearize) 708 { 709 assert(scip != NULL); 710 assert(nlhdlr != NULL); 711 712 if( nlhdlr->sollinearize == NULL ) 713 return SCIP_OKAY; 714 715 SCIP_CALL( nlhdlr->sollinearize(scip, conshdlr, cons, nlhdlr, expr, nlhdlrexprdata, sol, solisbest, overestimate, underestimate) ); 716 717 return SCIP_OKAY; 718 } 719 720 /** reset number of detections counter for last round */ 721 void SCIPnlhdlrResetNDetectionslast( 722 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 723 ) 724 { 725 assert(nlhdlr != NULL); 726 nlhdlr->ndetectionslast = 0; 727 } 728 729 /** increments number of cutoffs in statistics */ 730 void SCIPnlhdlrIncrementNCutoffs( 731 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 732 ) 733 { 734 assert(nlhdlr != NULL); 735 ++nlhdlr->ncutoffs; 736 } 737 738 /** increments number of separations in statistics */ 739 void SCIPnlhdlrIncrementNSeparated( 740 SCIP_NLHDLR* nlhdlr /**< nonlinear handler */ 741 ) 742 { 743 assert(nlhdlr != NULL); 744 ++nlhdlr->nseparated; 745 } 746 747 /** print statistics for nonlinear handlers */ 748 void SCIPnlhdlrPrintStatistics( 749 SCIP* scip, /**< SCIP data structure */ 750 SCIP_NLHDLR** nlhdlrs, /**< nonlinear handlers */ 751 int nnlhdlrs, /**< number of nonlinear handlers */ 752 FILE* file /**< file handle, or NULL for standard out */ 753 ) 754 { 755 int i; 756 757 SCIPinfoMessage(scip, file, "Nlhdlrs : %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", 758 "Detects", "DetectAll", "DetectTime", 759 "#IntEval", "IntEvalTi", 760 "#RevProp", "RevPropTi", "DomReds", "Cutoffs", 761 "#Enforce", "EnfoTime", "Cuts", "Branching"); 762 763 for( i = 0; i < nnlhdlrs; ++i ) 764 { 765 /* skip disabled nlhdlr */ 766 if( !nlhdlrs[i]->enabled ) 767 continue; 768 769 SCIPinfoMessage(scip, file, " %-17s:", nlhdlrs[i]->name); 770 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndetectionslast); 771 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndetections); 772 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->detecttime)); 773 774 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nintevalcalls); 775 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->intevaltime)); 776 777 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->npropcalls); 778 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->proptime)); 779 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ndomreds); 780 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->ncutoffs); 781 782 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nenfocalls); 783 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, nlhdlrs[i]->enfotime)); 784 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nseparated); 785 SCIPinfoMessage(scip, file, " %10lld", nlhdlrs[i]->nbranchscores); 786 787 SCIPinfoMessage(scip, file, "\n"); 788 } 789 } 790