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 concsolver.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for concurrent solvers 28 * @author Leona Gottwald 29 */ 30 31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 32 33 #include <assert.h> 34 #include <string.h> 35 36 #include "scip/concsolver.h" 37 #include "scip/set.h" 38 #include "scip/scip.h" 39 #include "scip/concurrent.h" 40 41 #include "scip/struct_concsolver.h" 42 #include "scip/struct_stat.h" 43 #include "scip/struct_scip.h" 44 #include "blockmemshell/memory.h" 45 #include "scip/syncstore.h" 46 #include "scip/boundstore.h" 47 #include "scip/clock.h" 48 49 50 /** internal method for creating a concurrent solver type */ 51 static 52 SCIP_RETCODE doConcsolverTypeCreate( 53 SCIP_CONCSOLVERTYPE** concsolvertype, /**< pointer to concurrent solver data structure */ 54 SCIP_SET* set, /**< global SCIP settings */ 55 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 56 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 57 const char* name, /**< name of concurrent solver */ 58 SCIP_Real prefpriodefault, /**< the default preferred priority of this concurrent solver type */ 59 SCIP_DECL_CONCSOLVERCREATEINST ((*concsolvercreateinst)),/**< data copy method of concurrent solver */ 60 SCIP_DECL_CONCSOLVERDESTROYINST ((*concsolverdestroyinst)),/**< data copy method of concurrent solver */ 61 SCIP_DECL_CONCSOLVERINITSEEDS ((*concsolverinitseeds)),/**< initialize random seeds of concurrent solver */ 62 SCIP_DECL_CONCSOLVEREXEC ((*concsolverexec)),/**< execution method of concurrent solver */ 63 SCIP_DECL_CONCSOLVERCOPYSOLVINGDATA ((*concsolvercopysolvdata)),/**< method to copy solving data */ 64 SCIP_DECL_CONCSOLVERSTOP ((*concsolverstop)),/**< terminate solving in concurrent solver */ 65 SCIP_DECL_CONCSOLVERSYNCWRITE ((*concsolversyncwrite)),/**< synchronization method of concurrent solver */ 66 SCIP_DECL_CONCSOLVERSYNCREAD ((*concsolversyncread)),/**< synchronization method of concurrent solver */ 67 SCIP_DECL_CONCSOLVERTYPEFREEDATA ((*concsolvertypefreedata)),/**< method to free data of concurrent solver type */ 68 SCIP_CONCSOLVERTYPEDATA* data /**< the concurent solver type's data */ 69 ) 70 { 71 char paramname[SCIP_MAXSTRLEN]; 72 char paramdesc[SCIP_MAXSTRLEN]; 73 74 assert(concsolvertype != NULL); 75 assert(name != NULL); 76 assert(prefpriodefault >= 0.0 && prefpriodefault <= 1.0); 77 78 assert(concsolvercreateinst != NULL); 79 assert(concsolverdestroyinst != NULL); 80 assert(concsolverexec != NULL); 81 assert(concsolvercopysolvdata != NULL); 82 assert(concsolverstop != NULL); 83 assert(concsolversyncwrite != NULL); 84 assert(concsolversyncread != NULL); 85 86 SCIP_ALLOC( BMSallocMemory(concsolvertype) ); 87 BMSclearMemory(*concsolvertype); 88 89 SCIP_ALLOC( BMSduplicateMemoryArray(&(*concsolvertype)->name, name, strlen(name) + 1) ); 90 91 (*concsolvertype)->data = data; 92 (*concsolvertype)->ninstances = 0; 93 (*concsolvertype)->concsolvercreateinst = concsolvercreateinst; 94 (*concsolvertype)->concsolverdestroyinst = concsolverdestroyinst; 95 (*concsolvertype)->concsolverinitseeds = concsolverinitseeds; 96 (*concsolvertype)->concsolverexec = concsolverexec; 97 (*concsolvertype)->concsolvercopysolvdata = concsolvercopysolvdata; 98 (*concsolvertype)->concsolverstop = concsolverstop; 99 (*concsolvertype)->concsolversyncwrite = concsolversyncwrite; 100 (*concsolvertype)->concsolversyncread = concsolversyncread; 101 (*concsolvertype)->concsolvertypefreedata = concsolvertypefreedata; 102 103 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "concurrent/%s/prefprio", name); 104 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "the preferred number concurrent solvers of type <%s> with respect to the number of threads", name); 105 SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname, paramdesc, 106 &(*concsolvertype)->prefprio, FALSE, prefpriodefault, 0.0, 1.0, 107 NULL, NULL) ); /*lint !e740*/ 108 109 return SCIP_OKAY; 110 } 111 112 /** creates a concurrent solver type */ 113 SCIP_RETCODE SCIPconcsolverTypeCreate( 114 SCIP_CONCSOLVERTYPE** concsolvertype, /**< pointer to concurrent solver data structure */ 115 SCIP_SET* set, /**< global SCIP settings */ 116 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 117 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 118 const char* name, /**< name of concurrent solver */ 119 SCIP_Real prefpriodefault, /**< the default preferred priority of this concurrent solver type */ 120 SCIP_DECL_CONCSOLVERCREATEINST ((*concsolvercreateinst)),/**< data copy method of concurrent solver */ 121 SCIP_DECL_CONCSOLVERDESTROYINST ((*concsolverdestroyinst)),/**< data copy method of concurrent solver */ 122 SCIP_DECL_CONCSOLVERINITSEEDS ((*concsolverinitseeds)),/**< initialize random seeds of concurrent solver */ 123 SCIP_DECL_CONCSOLVEREXEC ((*concsolverexec)),/**< execution method of concurrent solver */ 124 SCIP_DECL_CONCSOLVERCOPYSOLVINGDATA ((*concsolvercopysolvdata)),/**< method to copy solving data */ 125 SCIP_DECL_CONCSOLVERSTOP ((*concsolverstop)),/**< terminate solving in concurrent solver */ 126 SCIP_DECL_CONCSOLVERSYNCWRITE ((*concsolversyncwrite)),/**< synchronization method of concurrent solver */ 127 SCIP_DECL_CONCSOLVERSYNCREAD ((*concsolversyncread)),/**< synchronization method of concurrent solver */ 128 SCIP_DECL_CONCSOLVERTYPEFREEDATA ((*concsolvertypefreedata)),/**< method to free data of concurrent solver type */ 129 SCIP_CONCSOLVERTYPEDATA* data /**< the concurent solver type's data */ 130 ) 131 { 132 assert(concsolvertype != NULL); 133 assert(name != NULL); 134 assert(prefpriodefault >= 0.0 && prefpriodefault <= 1.0); 135 136 assert(concsolvercreateinst != NULL); 137 assert(concsolverdestroyinst != NULL); 138 assert(concsolverexec != NULL); 139 assert(concsolvercopysolvdata != NULL); 140 assert(concsolverstop != NULL); 141 assert(concsolversyncwrite != NULL); 142 assert(concsolversyncread != NULL); 143 144 SCIP_CALL_FINALLY( doConcsolverTypeCreate(concsolvertype, set, messagehdlr, blkmem, 145 name, prefpriodefault, concsolvercreateinst, concsolverdestroyinst, concsolverinitseeds, concsolverexec, 146 concsolvercopysolvdata, concsolverstop, concsolversyncwrite, concsolversyncread, concsolvertypefreedata, data), 147 SCIPconcsolverTypeFree(concsolvertype) ); 148 149 return SCIP_OKAY; 150 } 151 152 /** frees all memory of a concurrent solver type */ 153 void SCIPconcsolverTypeFree( 154 SCIP_CONCSOLVERTYPE** concsolvertype /**< pointer to concurrent solver data structure */ 155 ) 156 { 157 assert(concsolvertype != NULL); 158 if( *concsolvertype == NULL ) 159 return; 160 161 if( (*concsolvertype)->concsolvertypefreedata != NULL ) 162 (*concsolvertype)->concsolvertypefreedata(&(*concsolvertype)->data); 163 164 BMSfreeMemoryArrayNull(&(*concsolvertype)->name); 165 BMSfreeMemory(concsolvertype); 166 } 167 168 /** gets the data of a concurrent solver type */ 169 SCIP_CONCSOLVERTYPEDATA* SCIPconcsolverTypeGetData( 170 SCIP_CONCSOLVERTYPE* concsolvertype /**< concurrent solver type */ 171 ) 172 { 173 assert(concsolvertype != NULL); 174 175 return concsolvertype->data; 176 } 177 178 /** sets the data of a concurrent solver type */ 179 void SCIPconcsolverTypeSetData( 180 SCIP_CONCSOLVERTYPE* concsolvertype, /**< concurrent solver type */ 181 SCIP_CONCSOLVERTYPEDATA* data /**< the concurrent solver's data */ 182 ) 183 { 184 assert(concsolvertype != NULL); 185 186 concsolvertype->data = data; 187 } 188 189 /** gets the name of a concurrent solver type */ 190 char* SCIPconcsolverTypeGetName( 191 SCIP_CONCSOLVERTYPE* concsolvertype /**< concurrent solver type */ 192 ) 193 { 194 assert(concsolvertype != NULL); 195 196 return concsolvertype->name; 197 } 198 199 /** gets the preferred priority from a concurrent solver type */ 200 SCIP_Real SCIPconcsolverTypeGetPrefPrio( 201 SCIP_CONCSOLVERTYPE* concsolvertype /**< concurrent solver type */ 202 ) 203 { 204 assert(concsolvertype != NULL); 205 206 return concsolvertype->prefprio; 207 } 208 209 /** creates an instance of the given concurrent solver type */ 210 SCIP_RETCODE SCIPconcsolverCreateInstance( 211 SCIP_SET* set, /**< global SCIP settings */ 212 SCIP_CONCSOLVERTYPE* concsolvertype, /**< concurrent solver type to create */ 213 SCIP_CONCSOLVER** concsolver /**< pointer to return concurrent solver instance */ 214 ) 215 { 216 char instancename[SCIP_MAXSTRLEN]; 217 218 ++concsolvertype->ninstances; 219 (void) SCIPsnprintf(instancename, SCIP_MAXSTRLEN, "%s-%i", concsolvertype->name, concsolvertype->ninstances); 220 221 SCIP_ALLOC( BMSallocMemory(concsolver) ); 222 SCIP_ALLOC( BMSduplicateMemoryArray(&(*concsolver)->name, instancename, strlen(instancename) + 1) ); 223 224 (*concsolver)->type = concsolvertype; 225 226 /* initialize counters for statistics */ 227 (*concsolver)->nsolsrecvd = 0; 228 (*concsolver)->nsolsshared = 0; 229 (*concsolver)->ntighterbnds = 0; 230 (*concsolver)->ntighterintbnds = 0; 231 SCIP_CALL( SCIPcreateWallClock(set->scip, &(*concsolver)->totalsynctime) ); 232 233 /* initialize synchronization fields */ 234 (*concsolver)->nsyncs = 0; 235 (*concsolver)->syncdelay = 0.0; 236 237 /* in deterministic mode use number of nonzeros and variables to get a good initial synchronization frequency 238 * in opportunistic mode use the frequency as set by the user 239 */ 240 if( set->parallel_mode == (int) SCIP_PARA_DETERMINISTIC ) 241 (*concsolver)->syncfreq = 0.01 * set->scip->stat->nnz * SCIPgetNVars(set->scip) * set->concurrent_freqinit; 242 else 243 (*concsolver)->syncfreq = set->concurrent_freqinit; 244 245 (*concsolver)->syncdata = NULL; 246 247 SCIPdebugMessage("concsolver %s initialized sync freq to %f\n", (*concsolver)->name, (*concsolver)->syncfreq); 248 /* register concurrent solver */ 249 (*concsolver)->idx = SCIPgetNConcurrentSolvers(set->scip); 250 SCIP_CALL( concsolvertype->concsolvercreateinst(set->scip, concsolvertype, *concsolver) ); 251 SCIP_CALL( SCIPaddConcurrentSolver(set->scip, *concsolver) ); 252 253 return SCIP_OKAY; 254 } 255 256 /** destroys an instance of the given concurrent solver */ 257 SCIP_RETCODE SCIPconcsolverDestroyInstance( 258 SCIP_SET* set, /**< global SCIP settings */ 259 SCIP_CONCSOLVER** concsolver /**< concurrent solver */ 260 ) 261 { 262 assert(concsolver != NULL); 263 assert((*concsolver)->type != NULL); 264 assert(set != NULL); 265 assert((*concsolver)->type->concsolverdestroyinst != NULL); 266 267 SCIP_CALL( (*concsolver)->type->concsolverdestroyinst(set->scip, *concsolver) ); 268 --(*concsolver)->type->ninstances; 269 270 SCIP_CALL( SCIPfreeClock(set->scip, &(*concsolver)->totalsynctime) ); 271 BMSfreeMemoryArray(&(*concsolver)->name); 272 273 BMSfreeMemory(concsolver); 274 275 return SCIP_OKAY; 276 } 277 278 /** gets the data of a concurrent solver */ 279 SCIP_CONCSOLVERDATA* SCIPconcsolverGetData( 280 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 281 ) 282 { 283 assert(concsolver != NULL); 284 285 return concsolver->data; 286 } 287 288 /** sets the data of a concurrent solver */ 289 void SCIPconcsolverSetData( 290 SCIP_CONCSOLVER* concsolver, /**< concurrent solver */ 291 SCIP_CONCSOLVERDATA* data /**< the concurrent solver's data */ 292 ) 293 { 294 assert(concsolver != NULL); 295 296 concsolver->data = data; 297 } 298 299 /** gets the name of a concurrent solver */ 300 char* SCIPconcsolverGetName( 301 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 302 ) 303 { 304 assert(concsolver != NULL); 305 306 return concsolver->name; 307 } 308 309 /** initializes the random seeds of a concurrent solver */ 310 SCIP_RETCODE SCIPconcsolverInitSeeds( 311 SCIP_CONCSOLVER* concsolver, /**< concurrent solver */ 312 unsigned int seed /**< seed for initializing the solver's internal random seeds */ 313 ) 314 { 315 assert(concsolver != NULL); 316 assert(concsolver->type != NULL); 317 318 if( concsolver->type->concsolverinitseeds != NULL ) 319 SCIP_CALL( concsolver->type->concsolverinitseeds(concsolver, seed) ); 320 321 return SCIP_OKAY; 322 } 323 324 /** start the solving process of a concurrent solver */ 325 SCIP_RETCODE SCIPconcsolverExec( 326 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 327 ) 328 { 329 assert(concsolver != NULL); 330 assert(concsolver->type != NULL); 331 assert(concsolver->type->concsolverexec != NULL); 332 333 /* set the stopped flag to false */ 334 concsolver->stopped = FALSE; 335 336 /* then call the execute callback */ 337 SCIP_CALL( concsolver->type->concsolverexec(concsolver, &concsolver->solvingtime, &concsolver->nlpiterations, &concsolver->nnodes) ); 338 339 return SCIP_OKAY; 340 } 341 342 /** gets solving data of concurrent solver and stores it in the given SCIP instance */ 343 SCIP_RETCODE SCIPconcsolverGetSolvingData( 344 SCIP_CONCSOLVER* concsolver, /**< concurrent solver */ 345 SCIP* scip /**< SCIP datastructure */ 346 ) 347 { 348 assert(concsolver != NULL); 349 assert(concsolver->type != NULL); 350 assert(concsolver->type->concsolvercopysolvdata != NULL); 351 352 return concsolver->type->concsolvercopysolvdata(concsolver, scip); 353 } 354 355 /** interrupt solving in a concurrent solver */ 356 SCIP_RETCODE SCIPconcsolverStop( 357 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 358 ) 359 { 360 assert(concsolver != NULL); 361 assert(concsolver->type != NULL); 362 assert(concsolver->type->concsolverstop != NULL); 363 364 SCIP_CALL( concsolver->type->concsolverstop(concsolver) ); 365 366 /* set the stopped flag to true */ 367 concsolver->stopped = TRUE; 368 369 return SCIP_OKAY; 370 } 371 372 /** let the given concurrent solver synchronize, i.e. pass its own solutions and bounds to 373 * the SPI. 374 */ 375 SCIP_RETCODE SCIPconcsolverSync( 376 SCIP_CONCSOLVER* concsolver, /**< concurrent solver */ 377 SCIP_SET* set /**< global SCIP settings */ 378 ) 379 { 380 SCIP_SYNCDATA* syncdata; 381 SCIP_SYNCSTORE* syncstore; 382 int nsols; 383 int ntighterintbnds; 384 int ntighterbnds; 385 SCIP_CONCSOLVERTYPE* concsolvertype; 386 387 assert(concsolver != NULL); 388 assert(concsolver->type != NULL); 389 assert(concsolver->type->concsolversyncwrite != NULL); 390 assert(concsolver->type->concsolversyncread != NULL); 391 392 if( concsolver->stopped ) 393 return SCIP_OKAY; 394 395 SCIP_CALL( SCIPstartClock(set->scip, concsolver->totalsynctime) ); 396 397 concsolvertype = concsolver->type; 398 399 syncstore = SCIPgetSyncstore(set->scip); 400 assert(syncstore != NULL); 401 402 SCIP_CALL( SCIPsyncstoreStartSync(syncstore, concsolver->nsyncs, &syncdata) ); 403 404 if( syncdata == NULL ) 405 { 406 SCIP_CALL( SCIPstopClock(set->scip, concsolver->totalsynctime) ); 407 return SCIP_OKAY; 408 } 409 410 SCIPdebugMessage("concsolver %s starts sync %lli\n", concsolver->name, concsolver->nsyncs); 411 412 SCIP_CALL( concsolvertype->concsolversyncwrite(concsolver, syncstore, syncdata, set->concurrent_nbestsols, set->concurrent_maxnsols, &nsols) ); 413 concsolver->nsolsshared += nsols; 414 415 if( SCIPsyncdataGetStatus(syncdata) != SCIP_STATUS_UNKNOWN ) 416 { 417 SCIP_CALL( SCIPconcsolverStop(concsolver) ); 418 } 419 else if( SCIPsyncdataGetNSynced(syncdata) == SCIPsyncstoreGetNSolvers(syncstore) - 1 ) 420 { 421 /* if this is the last concurrent solver that is synchronizing for this synchronization data 422 * it will adjust the synchronization frequency using the progress on the gap 423 */ 424 SCIP_Bool lbok; 425 SCIP_Bool ubok; 426 SCIP_Real progress; 427 SCIP_Real prevub; 428 SCIP_Real prevlb; 429 SCIP_Real newub; 430 SCIP_Real newlb; 431 SCIP_Real freqfactor; 432 SCIP_Real newsyncfreq; 433 SCIP_SYNCDATA* prevsync; 434 435 if( concsolver->nsyncs == 0 ) 436 { 437 SCIPsyncdataSetSyncFreq(syncstore, syncdata, concsolver->syncfreq); 438 } 439 else 440 { 441 prevsync = SCIPsyncstoreGetSyncdata(syncstore, concsolver->nsyncs - 1); 442 assert(SCIPsyncdataGetNSynced(prevsync) == SCIPsyncstoreGetNSolvers(syncstore)); 443 444 prevub = SCIPsyncdataGetUpperbound(prevsync); 445 prevlb = SCIPsyncdataGetLowerbound(prevsync); 446 newub = SCIPsyncdataGetUpperbound(syncdata); 447 newlb = SCIPsyncdataGetLowerbound(syncdata); 448 lbok = prevlb > -SCIPsetInfinity(set); 449 ubok = prevub < SCIPsetInfinity(set); 450 451 if( lbok && ubok ) 452 progress = SCIPrelDiff(prevub - prevlb, newub - newlb); 453 else if( lbok ) 454 progress = SCIPrelDiff(newlb, prevlb); 455 else if( ubok ) 456 progress = SCIPrelDiff(prevub, newub); 457 else if( !SCIPsetIsInfinity(set, -newlb) || !SCIPsetIsInfinity(set, newub) || 458 SCIPboundstoreGetNChgs(SCIPsyncdataGetBoundChgs(syncdata)) > 0 ) 459 progress = set->concurrent_targetprogress; 460 else 461 progress = 0.0; 462 463 /* should not be negative */ 464 progress = MAX(progress, 0.0); 465 assert(SCIPsetIsGE(set, progress, 0.0)); 466 467 if( progress < 0.5 * set->concurrent_targetprogress ) 468 freqfactor = set->concurrent_freqfactor; 469 else if( progress > 2 * set->concurrent_targetprogress ) 470 freqfactor = 0.5 + 0.5 / set->concurrent_freqfactor; 471 else 472 freqfactor = 1.0; 473 474 SCIPdebugMessage("syncfreq is %g and freqfactor is %f due to progress %f\n", concsolver->syncfreq, freqfactor, progress); 475 newsyncfreq = concsolver->syncfreq * freqfactor; 476 SCIPsyncdataSetSyncFreq(syncstore, syncdata, newsyncfreq); 477 SCIPdebugMessage("new syncfreq is %g\n", SCIPsyncdataGetSyncFreq(syncdata)); 478 } 479 } 480 481 SCIPdebugMessage("concsolver %s finishing sync %lli\n", concsolver->name, concsolver->nsyncs); 482 483 SCIP_CALL( SCIPsyncstoreFinishSync(syncstore, &syncdata) ); 484 ++concsolver->nsyncs; 485 486 concsolver->syncdelay += concsolver->timesincelastsync; 487 488 syncdata = SCIPsyncstoreGetNextSyncdata(syncstore, concsolver->syncdata, concsolver->syncfreq, concsolver->nsyncs, &concsolver->syncdelay); 489 490 while( syncdata != NULL ) 491 { 492 SCIP_CALL( SCIPsyncstoreEnsureAllSynced(syncstore, syncdata) ); 493 concsolver->syncdata = syncdata; 494 SCIP_CALL( concsolvertype->concsolversyncread(concsolver, syncstore, syncdata, &nsols, &ntighterbnds, &ntighterintbnds) ); 495 concsolver->ntighterbnds += ntighterbnds; 496 concsolver->ntighterintbnds += ntighterintbnds; 497 concsolver->nsolsrecvd += nsols; 498 SCIPdebugMessage("syncfreq before reading the next syncdata is %g\n", concsolver->syncfreq); 499 concsolver->syncfreq = SCIPsyncdataGetSyncFreq(concsolver->syncdata); 500 SCIPdebugMessage("syncfreq after reading the next syncdata is %g\n", concsolver->syncfreq); 501 syncdata = SCIPsyncstoreGetNextSyncdata(syncstore, concsolver->syncdata, concsolver->syncfreq, concsolver->nsyncs, &concsolver->syncdelay); 502 } 503 504 SCIP_CALL( SCIPstopClock(set->scip, concsolver->totalsynctime) ); 505 506 return SCIP_OKAY; 507 } 508 509 /** gets the current synchronization frequency of the concurent solver */ 510 SCIP_Real SCIPconcsolverGetSyncFreq( 511 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 512 ) 513 { 514 assert(concsolver != NULL); 515 516 return concsolver->syncfreq; 517 } 518 519 /** gets the total memory used by the concurent solver */ 520 SCIP_Longint SCIPconcsolverGetMemTotal( 521 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 522 ) 523 { 524 assert(concsolver != NULL); 525 526 return concsolver->syncdata != NULL ? SCIPsyncdataGetMemTotal(concsolver->syncdata) : 0; 527 } 528 529 /** sets the time elapsed since the last synchronization. Must be set before the synchronization is 530 * started. 531 */ 532 void SCIPconcsolverSetTimeSinceLastSync( 533 SCIP_CONCSOLVER* concsolver, /**< concurrent solver */ 534 SCIP_Real time /**< the time passed since the last synchronization */ 535 ) 536 { 537 assert(concsolver != NULL); 538 539 concsolver->timesincelastsync = time; 540 } 541 542 /** gets the solving time of the concurrent solver */ 543 SCIP_Real SCIPconcsolverGetSolvingTime( 544 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 545 ) 546 { 547 assert(concsolver != NULL); 548 549 return concsolver->solvingtime; 550 } 551 552 /** gets the time spent for synchronization for the concurrent solver */ 553 SCIP_Real SCIPconcsolverGetSyncTime( 554 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 555 ) 556 { 557 assert(concsolver != NULL); 558 559 return SCIPclockGetTime(concsolver->totalsynctime); 560 } 561 562 /** gets the number of lp iterations the concurrent solver used */ 563 SCIP_Longint SCIPconcsolverGetNLPIterations( 564 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 565 ) 566 { 567 assert(concsolver != NULL); 568 569 return concsolver->nlpiterations; 570 } 571 572 /** gets the number of branch and bound nodes the concurrent solver used */ 573 SCIP_Longint SCIPconcsolverGetNNodes( 574 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 575 ) 576 { 577 assert(concsolver != NULL); 578 579 return concsolver->nnodes; 580 } 581 582 /** gets the number of solutions the concurrent solver received during synchronization */ 583 SCIP_Longint SCIPconcsolverGetNSolsRecvd( 584 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 585 ) 586 { 587 assert(concsolver != NULL); 588 589 return concsolver->nsolsrecvd; 590 } 591 592 /** gets the number of solutions the concurrent solver shared during synchronization */ 593 SCIP_Longint SCIPconcsolverGetNSolsShared( 594 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 595 ) 596 { 597 assert(concsolver != NULL); 598 599 return concsolver->nsolsshared; 600 } 601 602 /** gets the number of tighter global variable bounds the solver received */ 603 SCIP_Longint SCIPconcsolverGetNTighterBnds( 604 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 605 ) 606 { 607 assert(concsolver != NULL); 608 609 return concsolver->ntighterbnds; 610 } 611 612 /** gets the number of tighter global variable bounds of integer variables the solver received */ 613 SCIP_Longint SCIPconcsolverGetNTighterIntBnds( 614 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 615 ) 616 { 617 assert(concsolver != NULL); 618 619 return concsolver->ntighterintbnds; 620 } 621 622 /** gets index of concurrent solver */ 623 int SCIPconcsolverGetIdx( 624 SCIP_CONCSOLVER* concsolver /**< concurrent solver */ 625 ) 626 { 627 assert(concsolver != NULL); 628 629 return concsolver->idx; 630 } 631