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 concurrent.c 26 * @ingroup PARALLEL 27 * @brief helper functions for concurrent SCIP solvers 28 * @author Leona Gottwald 29 */ 30 31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 32 33 #include "scip/concurrent.h" 34 #include "scip/struct_concurrent.h" 35 #include "scip/concsolver.h" 36 #include "scip/event.h" 37 #include "scip/struct_scip.h" 38 #include "scip/stat.h" 39 #include "scip/struct_set.h" 40 #include "scip/struct_primal.h" 41 #include "scip/struct_stat.h" 42 #include "scip/struct_sol.h" 43 #include "scip/struct_prop.h" 44 #include "scip/struct_heur.h" 45 #include "scip/struct_sepa.h" 46 #include "scip/struct_presol.h" 47 #include "scip/prob.h" 48 #include "scip/prop_sync.h" 49 #include "scip/heur_sync.h" 50 #include "scip/event_globalbnd.h" 51 #include "scip/scip.h" 52 #include "scip/syncstore.h" 53 #include "scip/set.h" 54 #include "tpi/tpi.h" 55 #include "tpi/def_openmp.h" 56 57 /** create concurrent data */ 58 SCIP_RETCODE SCIPcreateConcurrent( 59 SCIP* scip, /**< SCIP datastructure */ 60 SCIP_CONCSOLVER* concsolver, /**< concurrent solver of given SCIP instance */ 61 int* varperm /**< permutation of variables for communication */ 62 ) 63 { 64 int nvars; 65 66 assert(scip != NULL); 67 assert(concsolver != NULL); 68 assert(varperm != NULL); 69 assert(scip->concurrent == NULL); 70 71 SCIP_CALL( SCIPallocBlockMemory(scip, &scip->concurrent) ); 72 73 nvars = SCIPgetNOrigVars(scip); 74 scip->concurrent->varperm = NULL; 75 76 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &scip->concurrent->varperm, varperm, nvars) ); 77 78 scip->concurrent->concsolver = concsolver; 79 scip->concurrent->mainscip = scip; 80 scip->concurrent->solidx = scip->stat->solindex; 81 scip->stat->subscipdepth = 0; 82 83 if( scip->set->parallel_mode == (int) SCIP_PARA_DETERMINISTIC ) 84 { 85 scip->concurrent->dettime = 0.0; 86 scip->concurrent->wallclock = NULL; 87 } 88 else 89 { 90 SCIP_CALL( SCIPcreateWallClock(scip, &scip->concurrent->wallclock) ); 91 SCIP_CALL( SCIPstartClock(scip, scip->concurrent->wallclock) ); 92 } 93 94 assert(SCIPfindHeur(scip, "sync") == NULL); 95 96 SCIP_CALL( SCIPincludeHeurSync(scip) ); 97 scip->concurrent->heursync = SCIPfindHeur(scip, "sync"); 98 99 assert(SCIPfindProp(scip, "sync") == NULL); 100 101 SCIP_CALL( SCIPincludePropSync(scip) ); 102 scip->concurrent->propsync = SCIPfindProp(scip, "sync"); 103 104 scip->concurrent->eventglobalbnd = NULL; 105 assert(SCIPfindEventhdlr(scip, "globalbnd") == NULL); 106 107 if( scip->set->concurrent_commvarbnds ) 108 { 109 SCIP_CALL( SCIPincludeEventHdlrGlobalbnd(scip) ); 110 scip->concurrent->eventglobalbnd = SCIPfindEventhdlr(scip, "globalbnd"); 111 } 112 113 return SCIP_OKAY; 114 } 115 116 /** get number of initialized concurrent solvers */ 117 int SCIPgetNConcurrentSolvers( 118 SCIP* scip /**< SCIP datastructure */ 119 ) 120 { 121 assert(scip != NULL); 122 assert(scip->set != NULL); 123 124 return scip->set->nconcsolvers; 125 } 126 127 /** gets the initialized concurrent solvers */ 128 SCIP_CONCSOLVER** SCIPgetConcurrentSolvers( 129 SCIP* scip /**< SCIP datastructure */ 130 ) 131 { 132 assert(scip != NULL); 133 assert(scip->set != NULL); 134 135 return scip->set->concsolvers; 136 } 137 138 /** adds an initialized concurrent solver */ 139 SCIP_RETCODE SCIPaddConcurrentSolver( 140 SCIP* scip, /**< SCIP datastructure */ 141 SCIP_CONCSOLVER* concsolver /**< concurrent solver of given SCIP instance */ 142 ) 143 { 144 assert(scip != NULL); 145 146 SCIP_CALL( SCIPsetIncludeConcsolver(scip->set, concsolver) ); 147 148 return SCIP_OKAY; 149 } 150 151 /** frees concurrent data */ 152 SCIP_RETCODE SCIPfreeConcurrent( 153 SCIP* scip /**< SCIP datastructure */ 154 ) 155 { 156 assert(scip != NULL); 157 158 if( scip->concurrent == NULL ) 159 return SCIP_OKAY; 160 161 assert(scip->concurrent->varperm != NULL); 162 163 /* check if we are the SCIP that is responsible for freeing this concurrent struct 164 * or just a subscip */ 165 if( scip->concurrent->mainscip != scip ) 166 { 167 /* we are just a subscip, so don't free the concurrent structure and add the 168 * deterministic time that was counted in the subscip but not yet added to the main SCIP */ 169 scip->concurrent->mainscip->stat->detertimecnt += scip->stat->detertimecnt; 170 scip->stat->detertimecnt = 0; 171 scip->concurrent = NULL; 172 } 173 else 174 { 175 /* we are in the main SCIP so free the concurrent structure */ 176 if( scip->concurrent->wallclock != NULL ) 177 { 178 SCIP_CALL( SCIPfreeClock(scip, &scip->concurrent->wallclock) ); 179 } 180 181 SCIPfreeBlockMemoryArray(scip, &scip->concurrent->varperm, SCIPgetNOrigVars(scip)); 182 183 SCIPfreeBlockMemory(scip, &scip->concurrent); 184 } 185 186 return SCIP_OKAY; 187 } 188 189 /** increments the time counter for synchronization */ 190 SCIP_RETCODE SCIPincrementConcurrentTime( 191 SCIP* scip, /**< SCIP datastructure */ 192 SCIP_Real val /**< value by which the time counter for synchronization is incremented */ 193 ) 194 { 195 SCIP_Real syncfreq; 196 SCIP* mainscip; 197 SCIP_CLOCK* wallclock; 198 199 assert(scip != NULL); 200 201 if( scip->concurrent == NULL ) 202 return SCIP_OKAY; 203 204 syncfreq = SCIPconcsolverGetSyncFreq(scip->concurrent->concsolver); 205 wallclock = scip->concurrent->wallclock; 206 mainscip = scip->concurrent->mainscip; 207 208 if( wallclock == NULL ) 209 { 210 scip->concurrent->dettime += val; 211 212 if( scip->concurrent->dettime >= syncfreq ) 213 { 214 SCIP_EVENT* event; 215 SCIPconcsolverSetTimeSinceLastSync(scip->concurrent->concsolver, scip->concurrent->dettime); 216 scip->concurrent->dettime = 0.0; 217 SCIP_CALL( SCIPeventCreateSync(&event, SCIPblkmem(mainscip)) ); 218 SCIP_CALL( SCIPeventqueueAdd(mainscip->eventqueue, SCIPblkmem(mainscip), mainscip->set, 219 NULL, NULL, NULL, mainscip->eventfilter, &event) ); 220 } 221 } 222 else 223 { 224 SCIP_Real timesincelastsync; 225 timesincelastsync = SCIPgetClockTime(mainscip, wallclock); 226 227 if( timesincelastsync >= syncfreq ) 228 { 229 SCIP_EVENT* event; 230 SCIPconcsolverSetTimeSinceLastSync(scip->concurrent->concsolver, timesincelastsync); 231 232 SCIP_CALL( SCIPeventCreateSync(&event, SCIPblkmem(mainscip)) ); 233 SCIP_CALL( SCIPeventqueueAdd(mainscip->eventqueue, SCIPblkmem(mainscip), mainscip->set, 234 NULL, NULL, NULL, mainscip->eventfilter, &event) ); 235 236 SCIP_CALL( SCIPresetClock(mainscip, wallclock) ); 237 SCIP_CALL( SCIPstartClock(mainscip, wallclock) ); 238 } 239 } 240 241 return SCIP_OKAY; 242 } 243 244 245 /** synchronize with other concurrent solvers */ 246 SCIP_RETCODE SCIPsynchronize( 247 SCIP* scip /**< SCIP datastructure */ 248 ) 249 { 250 assert(scip != NULL); 251 assert(scip->concurrent != NULL); 252 253 SCIP_CALL( SCIPconcsolverSync(scip->concurrent->concsolver, scip->concurrent->mainscip->set) ); 254 255 scip->concurrent->mainscip->concurrent->solidx = scip->concurrent->mainscip->stat->solindex; 256 257 if( scip->concurrent->eventglobalbnd != NULL ) 258 SCIPeventGlobalbndClearBoundChanges(scip->concurrent->eventglobalbnd); 259 260 return SCIP_OKAY; 261 } 262 263 /** disables storing global bound changes */ 264 void SCIPdisableConcurrentBoundStorage( 265 SCIP* scip /**< SCIP data structure */ 266 ) 267 { 268 assert(scip != NULL); 269 assert(scip->concurrent != NULL); 270 271 if( scip->concurrent->eventglobalbnd != NULL ) 272 SCIPeventGlobalbndDisableBoundStorage(scip->concurrent->eventglobalbnd); 273 } 274 275 /** enables storing global bound changes */ 276 void SCIPenableConcurrentBoundStorage( 277 SCIP* scip /**< SCIP data structure */ 278 ) 279 { 280 assert(scip != NULL); 281 assert(scip->concurrent != NULL); 282 283 if( scip->concurrent->eventglobalbnd != NULL ) 284 SCIPeventGlobalbndEnableBoundStorage(scip->concurrent->eventglobalbnd); 285 } 286 287 /** gets total memory usage of all concurrent solvers together */ 288 SCIP_Longint SCIPgetConcurrentMemTotal( 289 SCIP* scip /**< SCIP data structure */ 290 ) 291 { 292 SCIP_Longint memtotal = SCIPgetMemTotal(scip); 293 294 assert(scip != NULL); 295 296 if( scip->concurrent == NULL || scip->concurrent->mainscip != scip || scip->concurrent->concsolver == NULL ) 297 return memtotal; 298 else 299 { 300 SCIP_Longint concmemtotal = SCIPconcsolverGetMemTotal(scip->concurrent->concsolver); 301 return MAX(memtotal, concmemtotal); 302 } 303 } 304 305 /** gets the dualbound in the last synchronization */ 306 SCIP_Real SCIPgetConcurrentDualbound( 307 SCIP* scip /**< SCIP data structure */ 308 ) 309 { 310 SCIP_SYNCSTORE* syncstore; 311 312 assert(scip != NULL); 313 314 syncstore = SCIPgetSyncstore(scip); 315 assert(syncstore != NULL); 316 317 return SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, SCIPsyncstoreGetLastLowerbound(syncstore)); 318 } 319 320 /** gets the primalbound in the last synchronization */ 321 SCIP_Real SCIPgetConcurrentPrimalbound( 322 SCIP* scip /**< SCIP data structure */ 323 ) 324 { 325 SCIP_SYNCSTORE* syncstore; 326 327 assert(scip != NULL); 328 329 syncstore = SCIPgetSyncstore(scip); 330 assert(syncstore != NULL); 331 332 return SCIPprobExternObjval(scip->transprob, scip->origprob, scip->set, SCIPsyncstoreGetLastUpperbound(syncstore)); 333 } 334 335 /** gets the gap in the last synchronization */ 336 SCIP_Real SCIPgetConcurrentGap( 337 SCIP* scip /**< SCIP data structure */ 338 ) 339 { 340 SCIP_Real primalbound; 341 SCIP_Real dualbound; 342 343 primalbound = SCIPgetConcurrentPrimalbound(scip); 344 dualbound = SCIPgetConcurrentDualbound(scip); 345 346 return SCIPcomputeGap(SCIPepsilon(scip), SCIPinfinity(scip), primalbound, dualbound); 347 } 348 349 /** gives the total number of tightened bounds received from other concurrent solvers */ 350 SCIP_Longint SCIPgetConcurrentNTightenedBnds( 351 SCIP* scip /**< SCIP data structure */ 352 ) 353 { 354 assert(scip->concurrent != NULL); 355 356 return scip->concurrent->propsync != NULL ? SCIPpropSyncGetNTightenedBnds(scip->concurrent->propsync) : 0; 357 } 358 359 /** gives the total number of tightened bounds for integer variables received from 360 * other concurrent solvers */ 361 SCIP_Longint SCIPgetConcurrentNTightenedIntBnds( 362 SCIP* scip /**< SCIP data structure */ 363 ) 364 { 365 assert(scip->concurrent != NULL); 366 367 return scip->concurrent->propsync != NULL ? SCIPpropSyncGetNTightenedIntBnds(scip->concurrent->propsync) : 0; 368 } 369 370 /** pass a solution to the given SCIP instance using that was received via synchronization by using 371 * the sync heuristic */ 372 SCIP_RETCODE SCIPaddConcurrentSol( 373 SCIP* scip, /**< SCIP datastructure */ 374 SCIP_SOL* sol /**< solution */ 375 ) 376 { 377 assert(scip != NULL); 378 assert(scip->concurrent != NULL); 379 assert(sol != NULL); 380 381 SCIP_CALL( SCIPheurSyncPassSol(scip, scip->concurrent->heursync, sol) ); 382 383 return SCIP_OKAY; 384 } 385 386 /** adds a global boundchange to the given SCIP, by passing it to the sync propagator */ 387 SCIP_RETCODE SCIPaddConcurrentBndchg( 388 SCIP* scip, /**< SCIP data structure */ 389 SCIP_VAR* var, /**< variable for bound */ 390 SCIP_Real val, /**< value of bound */ 391 SCIP_BOUNDTYPE bndtype /**< type of bound */ 392 ) 393 { 394 assert(scip != NULL); 395 assert(var != NULL); 396 assert(scip->concurrent != NULL); 397 assert(scip->concurrent->propsync != NULL); 398 399 SCIP_CALL( SCIPpropSyncAddBndchg(scip->concurrent->mainscip, scip->concurrent->propsync, var, val, bndtype) ); 400 401 return SCIP_OKAY; 402 } 403 404 /** copy the nodenumber, depth, time, and runnumber of one solution to another one */ 405 SCIP_RETCODE SCIPcopySolStats( 406 SCIP_SOL* source, /**< source for solution statistics */ 407 SCIP_SOL* target /**< target for solution statistics */ 408 ) 409 { 410 assert(source != NULL); 411 assert(target != NULL); 412 413 target->depth = source->depth; 414 target->time = source->time; 415 target->nodenum = source->nodenum; 416 target->runnum = source->runnum; 417 418 return SCIP_OKAY; 419 } 420 421 422 /** get variable index of original variable that is the same between concurrent solvers */ 423 int SCIPgetConcurrentVaridx( 424 SCIP* scip, /**< SCIP data structure */ 425 SCIP_VAR* var /**< variable */ 426 ) 427 { 428 assert(scip != NULL); 429 assert(scip->concurrent != NULL); 430 assert(scip->concurrent->varperm != NULL); 431 assert(var != NULL); 432 assert(SCIPvarIsOriginal(var)); 433 assert(SCIPvarGetIndex(var) < SCIPgetNOrigVars(scip)); 434 435 return scip->concurrent->varperm[SCIPvarGetIndex(var)]; 436 } 437 438 /** is the solution new since the last synchronization point */ 439 SCIP_Bool SCIPIsConcurrentSolNew( 440 SCIP* scip, /**< SCIP data structure */ 441 SCIP_SOL* sol /**< the solution */ 442 ) 443 { 444 assert(scip != NULL); 445 assert(scip->concurrent != NULL); 446 assert(sol != NULL); 447 448 return SCIPsolGetIndex(sol) >= scip->concurrent->solidx; 449 } 450 451 /** gets the global lower bound changes since the last synchronization point */ 452 SCIP_BOUNDSTORE* SCIPgetConcurrentGlobalBoundChanges( 453 SCIP* scip /**< SCIP data structure */ 454 ) 455 { 456 assert(scip != NULL); 457 assert(scip->concurrent != NULL); 458 459 if( scip->concurrent->eventglobalbnd != NULL ) 460 return SCIPeventGlobalbndGetBoundChanges(scip->concurrent->eventglobalbnd); 461 462 return NULL; 463 } 464 465 /** executes the concurrent solver corresponding to the current thread */ 466 static 467 SCIP_RETCODE execConcsolver( 468 void* args /**< SCIP data structure passed in as a void pointer */ 469 ) 470 { 471 SCIP* scip; 472 473 assert(args != NULL); 474 475 scip = (SCIP*) args; 476 477 SCIP_CALL( SCIPconcsolverExec(scip->set->concsolvers[SCIPtpiGetThreadNum()]) ); 478 SCIP_CALL( SCIPconcsolverSync(scip->set->concsolvers[SCIPtpiGetThreadNum()], scip->set) ); 479 480 return SCIP_OKAY; 481 } 482 483 /** start solving in parallel using the given set of concurrent solvers */ 484 SCIP_RETCODE SCIPconcurrentSolve( 485 SCIP* scip /**< pointer to scip datastructure */ 486 ) 487 { 488 SCIP_SYNCSTORE* syncstore; 489 int idx; 490 int jobid; 491 int i; 492 SCIP_RETCODE retcode; 493 SCIP_CONCSOLVER** concsolvers; 494 int nconcsolvers; 495 496 assert(scip != NULL); 497 498 syncstore = SCIPgetSyncstore(scip); 499 concsolvers = scip->set->concsolvers; 500 nconcsolvers = scip->set->nconcsolvers; 501 502 assert(SCIPsyncstoreIsInitialized(syncstore)); 503 assert(SCIPsyncstoreGetNSolvers(syncstore) == nconcsolvers); 504 505 SCIPsyncstoreSetSolveIsStopped(syncstore, FALSE); 506 jobid = SCIPtpiGetNewJobID(); 507 508 TPI_PARA 509 { 510 TPI_SINGLE 511 { 512 for( i = 0; i < nconcsolvers; ++i ) 513 { 514 /* cppcheck-suppress unassignedVariable */ 515 SCIP_JOB* job; 516 SCIP_SUBMITSTATUS status; 517 518 SCIP_CALL_ABORT( SCIPtpiCreateJob(&job, jobid, execConcsolver, scip) ); 519 SCIP_CALL_ABORT( SCIPtpiSubmitJob(job, &status) ); 520 521 assert(status == SCIP_SUBMIT_SUCCESS); 522 } 523 } 524 } 525 526 retcode = SCIPtpiCollectJobs(jobid); 527 idx = SCIPsyncstoreGetWinner(syncstore); 528 assert(idx >= 0 && idx < nconcsolvers); 529 530 /* a paranoid safeguard for running in optimized mode */ 531 if( idx < 0 || idx >= nconcsolvers ) 532 idx = 0; 533 534 SCIP_CALL( SCIPconcsolverGetSolvingData(concsolvers[idx], scip) ); 535 536 return retcode; 537 } 538 539 /** copy solving statistics */ 540 SCIP_RETCODE SCIPcopyConcurrentSolvingStats( 541 SCIP* source, /**< SCIP data structure */ 542 SCIP* target /**< target SCIP data structure */ 543 ) 544 { 545 SCIP_Real tmptime; 546 SCIP_HEUR* heur; 547 SCIP_NODE* root; 548 SCIP_PROP* prop; 549 SCIP_SEPA* sepa; 550 SCIP_PRESOL* presol; 551 SCIP_HEUR** heurs; 552 int nheurs; 553 SCIP_PROP** props; 554 int nprops; 555 SCIP_SEPA** sepas; 556 int nsepas; 557 SCIP_PRESOL** presols; 558 int npresols; 559 int i; 560 561 assert(source != NULL); 562 assert(target != NULL); 563 564 heurs = SCIPgetHeurs(target); 565 nheurs = SCIPgetNHeurs(target); 566 567 for( i = 0; i < nheurs; ++i ) 568 { 569 heur = SCIPfindHeur(source, SCIPheurGetName(heurs[i])); 570 571 if( heur != NULL ) 572 { 573 heurs[i]->nbestsolsfound += heur->nbestsolsfound; 574 heurs[i]->ncalls += heur->ncalls; 575 heurs[i]->nsolsfound += heur->nsolsfound; 576 /* TODO divesets */ 577 tmptime = SCIPgetClockTime(target, heurs[i]->setuptime); 578 tmptime += SCIPgetClockTime(source, heur->setuptime); 579 SCIP_CALL( SCIPsetClockTime(target, heurs[i]->setuptime, tmptime) ); 580 581 tmptime = SCIPgetClockTime(target, heurs[i]->heurclock); 582 tmptime += SCIPgetClockTime(source, heur->heurclock); 583 SCIP_CALL( SCIPsetClockTime(target, heurs[i]->heurclock, tmptime) ); 584 } 585 } 586 587 props = SCIPgetProps(target); 588 nprops = SCIPgetNProps(target); 589 590 for( i = 0; i < nprops; ++i ) 591 { 592 prop = SCIPfindProp(source, SCIPpropGetName(props[i])); 593 594 if( prop != NULL ) 595 { 596 props[i]->ncalls += prop->ncalls; 597 props[i]->nrespropcalls += prop->nrespropcalls; 598 props[i]->ncutoffs += prop->ncutoffs; 599 props[i]->ndomredsfound += prop->ndomredsfound; 600 601 tmptime = SCIPgetClockTime(target, props[i]->proptime); 602 tmptime += SCIPgetClockTime(source, prop->proptime); 603 SCIP_CALL( SCIPsetClockTime(target, props[i]->proptime, tmptime) ); 604 605 tmptime = SCIPgetClockTime(target, props[i]->sbproptime); 606 tmptime += SCIPgetClockTime(source, prop->sbproptime); 607 SCIP_CALL( SCIPsetClockTime(target, props[i]->sbproptime, tmptime) ); 608 609 tmptime = SCIPgetClockTime(target, props[i]->resproptime); 610 tmptime += SCIPgetClockTime(source, prop->resproptime); 611 SCIP_CALL( SCIPsetClockTime(target, props[i]->resproptime, tmptime) ); 612 613 tmptime = SCIPgetClockTime(target, props[i]->presoltime); 614 tmptime += SCIPgetClockTime(source, prop->presoltime); 615 SCIP_CALL( SCIPsetClockTime(target, props[i]->presoltime, tmptime) ); 616 617 tmptime = SCIPgetClockTime(target, props[i]->setuptime); 618 tmptime += SCIPgetClockTime(source, prop->setuptime); 619 SCIP_CALL( SCIPsetClockTime(target, props[i]->setuptime, tmptime) ); 620 } 621 } 622 623 presols = SCIPgetPresols(target); 624 npresols = SCIPgetNPresols(target); 625 626 for( i = 0; i < npresols; ++i ) 627 { 628 presol = SCIPfindPresol(source, SCIPpresolGetName(presols[i])); 629 630 if( presol != NULL ) 631 { 632 presols[i]->ncalls += presol->ncalls; 633 presols[i]->nfixedvars += presol->nfixedvars; 634 presols[i]->naggrvars += presol->naggrvars; 635 presols[i]->nchgvartypes += presol->nchgvartypes; 636 presols[i]->nchgbds += presol->nchgbds; 637 presols[i]->naddholes += presol->naddholes; 638 presols[i]->ndelconss += presol->ndelconss; 639 presols[i]->naddconss += presol->naddconss; 640 presols[i]->nupgdconss += presol->nupgdconss; 641 presols[i]->nchgcoefs += presol->nchgcoefs; 642 presols[i]->nchgsides += presol->nchgsides; 643 presols[i]->nfixedvars += presol->nfixedvars; 644 presols[i]->nfixedvars += presol->nfixedvars; 645 presols[i]->nfixedvars += presol->nfixedvars; 646 647 tmptime = SCIPgetClockTime(target, presols[i]->setuptime); 648 tmptime += SCIPgetClockTime(source, presol->setuptime); 649 SCIP_CALL( SCIPsetClockTime(target, presols[i]->setuptime, tmptime) ); 650 651 tmptime = SCIPgetClockTime(target, presols[i]->presolclock); 652 tmptime += SCIPgetClockTime(source, presol->presolclock); 653 SCIP_CALL( SCIPsetClockTime(target, presols[i]->presolclock, tmptime) ); 654 } 655 } 656 657 sepas = SCIPgetSepas(target); 658 nsepas = SCIPgetNSepas(target); 659 660 for( i = 0; i < nsepas; ++i ) 661 { 662 sepa = SCIPfindSepa(source, SCIPsepaGetName(sepas[i])); 663 664 if( sepa != NULL ) 665 { 666 sepas[i]->lastsepanode = sepa->lastsepanode; 667 sepas[i]->ncalls += sepa->ncalls; 668 sepas[i]->nrootcalls += sepa->nrootcalls; 669 sepas[i]->ncutoffs += sepa->ncutoffs; 670 sepas[i]->ncutsfound += sepa->ncutsfound; 671 sepas[i]->ncutsaddedviapool += sepa->ncutsaddedviapool; 672 sepas[i]->ncutsaddeddirect += sepa->ncutsaddeddirect; 673 sepas[i]->ncutsappliedviapool += sepa->ncutsappliedviapool; 674 sepas[i]->ncutsapplieddirect += sepa->ncutsapplieddirect; 675 sepas[i]->nconssfound += sepa->nconssfound; 676 sepas[i]->ndomredsfound += sepa->ndomredsfound; 677 sepas[i]->maxbounddist = MAX(sepas[i]->maxbounddist, sepa->maxbounddist); 678 679 tmptime = SCIPgetClockTime(target, sepas[i]->setuptime); 680 tmptime += SCIPgetClockTime(source, sepa->setuptime); 681 SCIP_CALL( SCIPsetClockTime(target, sepas[i]->setuptime, tmptime) ); 682 683 tmptime = SCIPgetClockTime(target, sepas[i]->sepaclock); 684 tmptime += SCIPgetClockTime(source, sepa->sepaclock); 685 SCIP_CALL( SCIPsetClockTime(target, sepas[i]->sepaclock, tmptime) ); 686 } 687 } 688 689 target->primal->nsolsfound = source->primal->nsolsfound; 690 target->primal->nbestsolsfound = source->primal->nbestsolsfound; 691 target->primal->nlimsolsfound = source->primal->nlimsolsfound; 692 SCIPprobSetDualbound(target->transprob, SCIPprobExternObjval(target->transprob, target->origprob, target->set, SCIPgetDualbound(source))); 693 root = SCIPgetRootNode(target); 694 695 if( root != NULL ) 696 { 697 /* in the copied SCIP the dualbound is in the transformed space of the target */ 698 SCIP_CALL( SCIPupdateNodeLowerbound(target, root, SCIPgetDualbound(source)) ); 699 } 700 701 target->stat->nlpiterations = source->stat->nlpiterations; 702 target->stat->nrootlpiterations = source->stat->nrootlpiterations; 703 target->stat->nrootfirstlpiterations = source->stat->nrootfirstlpiterations; 704 target->stat->nprimallpiterations = source->stat->nprimallpiterations; 705 target->stat->nduallpiterations = source->stat->nduallpiterations; 706 target->stat->nlexduallpiterations = source->stat->nlexduallpiterations; 707 target->stat->nbarrierlpiterations = source->stat->nbarrierlpiterations; 708 target->stat->nprimalresolvelpiterations = source->stat->nprimalresolvelpiterations; 709 target->stat->ndualresolvelpiterations = source->stat->ndualresolvelpiterations; 710 target->stat->nlexdualresolvelpiterations = source->stat->nlexdualresolvelpiterations; 711 target->stat->nnodelpiterations = source->stat->nnodelpiterations; 712 target->stat->ninitlpiterations = source->stat->ninitlpiterations; 713 target->stat->ndivinglpiterations = source->stat->ndivinglpiterations; 714 target->stat->ndivesetlpiterations = source->stat->ndivesetlpiterations; 715 target->stat->nsbdivinglpiterations = source->stat->nsbdivinglpiterations; 716 target->stat->nsblpiterations = source->stat->nsblpiterations; 717 target->stat->nrootsblpiterations = source->stat->nrootsblpiterations; 718 target->stat->nconflictlpiterations = source->stat->nconflictlpiterations; 719 target->stat->nnodes = source->stat->nnodes; 720 target->stat->ninternalnodes = source->stat->ninternalnodes; 721 target->stat->nobjleaves = source->stat->nobjleaves; 722 target->stat->nfeasleaves = source->stat->nfeasleaves; 723 target->stat->ninfeasleaves = source->stat->ninfeasleaves; 724 target->stat->ntotalnodes = source->stat->ntotalnodes; 725 target->stat->ntotalinternalnodes = source->stat->ntotalinternalnodes; 726 target->stat->ncreatednodes = source->stat->ncreatednodes; 727 target->stat->ncreatednodesrun = source->stat->ncreatednodesrun; 728 target->stat->nactivatednodes = source->stat->nactivatednodes; 729 target->stat->ndeactivatednodes = source->stat->ndeactivatednodes; 730 target->stat->nearlybacktracks = source->stat->nearlybacktracks; 731 target->stat->nnodesaboverefbound = source->stat->nnodesaboverefbound; 732 target->stat->nbacktracks = source->stat->nbacktracks; 733 target->stat->ndelayedcutoffs = source->stat->ndelayedcutoffs; 734 target->stat->nreprops = source->stat->nreprops; 735 target->stat->nrepropboundchgs = source->stat->nrepropboundchgs; 736 target->stat->nrepropcutoffs = source->stat->nrepropcutoffs; 737 target->stat->nlpsolsfound = source->stat->nlpsolsfound; 738 target->stat->npssolsfound = source->stat->npssolsfound; 739 target->stat->nsbsolsfound = source->stat->nsbsolsfound; 740 target->stat->nlpbestsolsfound = source->stat->nlpbestsolsfound; 741 target->stat->npsbestsolsfound = source->stat->npsbestsolsfound; 742 target->stat->nsbbestsolsfound = source->stat->nsbbestsolsfound; 743 target->stat->nexternalsolsfound = source->stat->nexternalsolsfound; 744 target->stat->lastdispnode = source->stat->lastdispnode; 745 target->stat->lastdivenode = source->stat->lastdivenode; 746 target->stat->lastconflictnode = source->stat->lastconflictnode; 747 target->stat->bestsolnode = source->stat->bestsolnode; 748 target->stat->domchgcount = source->stat->domchgcount; 749 target->stat->nboundchgs = source->stat->nboundchgs; 750 target->stat->nholechgs = source->stat->nholechgs; 751 target->stat->nprobboundchgs = source->stat->nprobboundchgs; 752 target->stat->nprobholechgs = source->stat->nprobholechgs; 753 target->stat->nsbdowndomchgs = source->stat->nsbdowndomchgs; 754 target->stat->nsbupdomchgs = source->stat->nsbupdomchgs; 755 target->stat->nsbtimesiterlimhit = source->stat->nsbtimesiterlimhit; 756 target->stat->nnodesbeforefirst = source->stat->nnodesbeforefirst; 757 target->stat->ninitconssadded = source->stat->ninitconssadded; 758 target->stat->firstlpdualbound = SCIPprobExternObjval(target->transprob, target->origprob, target->set, source->stat->firstlpdualbound); 759 target->stat->rootlowerbound = SCIPprobExternObjval(source->transprob, source->origprob, source->set, source->stat->rootlowerbound); 760 target->stat->vsidsweight = source->stat->vsidsweight; 761 target->stat->firstprimalbound = SCIPprobExternObjval(target->transprob, target->origprob, target->set, source->stat->firstprimalbound); 762 target->stat->firstprimaltime = source->stat->firstprimaltime; 763 target->stat->firstsolgap = source->stat->firstsolgap; 764 target->stat->lastsolgap = source->stat->lastsolgap; 765 target->stat->primalzeroittime = source->stat->primalzeroittime; 766 target->stat->dualzeroittime = source->stat->dualzeroittime; 767 target->stat->barrierzeroittime = source->stat->barrierzeroittime; 768 target->stat->maxcopytime = MAX(source->stat->maxcopytime, target->stat->maxcopytime); 769 target->stat->mincopytime = MIN(source->stat->mincopytime, target->stat->mincopytime); 770 target->stat->firstlptime = source->stat->firstlptime; 771 target->stat->lastbranchvalue = source->stat->lastbranchvalue; 772 target->stat->dualrefintegral = source->stat->dualrefintegral; 773 target->stat->primalrefintegral = source->stat->primalrefintegral; 774 target->stat->primaldualintegral = source->stat->primaldualintegral; 775 target->stat->previousgap = source->stat->previousgap; 776 target->stat->previousdualrefgap = source->stat->previousdualrefgap; 777 target->stat->previousprimalrefgap = source->stat->previousprimalrefgap; 778 target->stat->previntegralevaltime = source->stat->previntegralevaltime; 779 target->stat->lastprimalbound = SCIPprobExternObjval(source->transprob, source->origprob, source->set, source->stat->lastprimalbound); 780 target->stat->lastdualbound = SCIPprobExternObjval(source->transprob, source->origprob, source->set, source->stat->lastdualbound); 781 target->stat->lastlowerbound = SCIPprobExternObjval(source->transprob, source->origprob, source->set, source->stat->lastlowerbound); 782 target->stat->lastupperbound = SCIPprobExternObjval(source->transprob, source->origprob, source->set, source->stat->lastupperbound); 783 target->stat->rootlpbestestimate = source->stat->rootlpbestestimate; 784 target->stat->referencebound = source->stat->referencebound; 785 786 /*tmptime = SCIPgetClockTime(target, target->stat->solvingtime); 787 tmptime += SCIPgetClockTime(source, source->stat->solvingtime); 788 SCIP_CALL( SCIPsetClockTime(target, target->stat->solvingtime, tmptime) );*/ 789 790 /* TODO */ 791 tmptime = SCIPgetClockTime(target, target->stat->solvingtimeoverall); 792 tmptime += SCIPgetClockTime(source, source->stat->solvingtimeoverall); 793 SCIP_CALL( SCIPsetClockTime(target, target->stat->solvingtimeoverall, tmptime) ); 794 795 tmptime = SCIPgetClockTime(target, target->stat->presolvingtime); 796 tmptime += SCIPgetClockTime(source, source->stat->presolvingtime); 797 SCIP_CALL( SCIPsetClockTime(target, target->stat->presolvingtime, tmptime) ); 798 799 tmptime = SCIPgetClockTime(target, target->stat->presolvingtimeoverall); 800 tmptime += SCIPgetClockTime(source, source->stat->presolvingtimeoverall); 801 SCIP_CALL( SCIPsetClockTime(target, target->stat->presolvingtimeoverall, tmptime) ); 802 803 tmptime = SCIPgetClockTime(target, target->stat->primallptime); 804 tmptime += SCIPgetClockTime(source, source->stat->primallptime); 805 SCIP_CALL( SCIPsetClockTime(target, target->stat->primallptime, tmptime) ); 806 807 tmptime = SCIPgetClockTime(target, target->stat->duallptime); 808 tmptime += SCIPgetClockTime(source, source->stat->duallptime); 809 SCIP_CALL( SCIPsetClockTime(target, target->stat->duallptime, tmptime) ); 810 811 tmptime = SCIPgetClockTime(target, target->stat->lexduallptime); 812 tmptime += SCIPgetClockTime(source, source->stat->lexduallptime); 813 SCIP_CALL( SCIPsetClockTime(target, target->stat->lexduallptime, tmptime) ); 814 815 tmptime = SCIPgetClockTime(target, target->stat->barrierlptime); 816 tmptime += SCIPgetClockTime(source, source->stat->barrierlptime); 817 SCIP_CALL( SCIPsetClockTime(target, target->stat->barrierlptime, tmptime) ); 818 819 tmptime = SCIPgetClockTime(target, target->stat->divinglptime); 820 tmptime += SCIPgetClockTime(source, source->stat->divinglptime); 821 SCIP_CALL( SCIPsetClockTime(target, target->stat->divinglptime, tmptime) ); 822 823 tmptime = SCIPgetClockTime(target, target->stat->strongbranchtime); 824 tmptime += SCIPgetClockTime(source, source->stat->strongbranchtime); 825 SCIP_CALL( SCIPsetClockTime(target, target->stat->strongbranchtime, tmptime) ); 826 827 tmptime = SCIPgetClockTime(target, target->stat->conflictlptime); 828 tmptime += SCIPgetClockTime(source, source->stat->conflictlptime); 829 SCIP_CALL( SCIPsetClockTime(target, target->stat->conflictlptime, tmptime) ); 830 831 tmptime = SCIPgetClockTime(target, target->stat->lpsoltime); 832 tmptime += SCIPgetClockTime(source, source->stat->lpsoltime); 833 SCIP_CALL( SCIPsetClockTime(target, target->stat->lpsoltime, tmptime) ); 834 835 tmptime = SCIPgetClockTime(target, target->stat->pseudosoltime); 836 tmptime += SCIPgetClockTime(source, source->stat->pseudosoltime); 837 SCIP_CALL( SCIPsetClockTime(target, target->stat->pseudosoltime, tmptime) ); 838 839 tmptime = SCIPgetClockTime(target, target->stat->sbsoltime); 840 tmptime += SCIPgetClockTime(source, source->stat->sbsoltime); 841 SCIP_CALL( SCIPsetClockTime(target, target->stat->sbsoltime, tmptime) ); 842 843 tmptime = SCIPgetClockTime(target, target->stat->nodeactivationtime); 844 tmptime += SCIPgetClockTime(source, source->stat->nodeactivationtime); 845 SCIP_CALL( SCIPsetClockTime(target, target->stat->nodeactivationtime, tmptime) ); 846 847 tmptime = SCIPgetClockTime(target, target->stat->nlpsoltime); 848 tmptime += SCIPgetClockTime(source, source->stat->nlpsoltime); 849 SCIP_CALL( SCIPsetClockTime(target, target->stat->nlpsoltime, tmptime) ); 850 851 tmptime = SCIPgetClockTime(target, target->stat->strongpropclock); 852 tmptime += SCIPgetClockTime(source, source->stat->strongpropclock); 853 SCIP_CALL( SCIPsetClockTime(target, target->stat->strongpropclock, tmptime) ); 854 855 tmptime = SCIPgetClockTime(target, target->stat->reoptupdatetime); 856 tmptime += SCIPgetClockTime(source, source->stat->reoptupdatetime); 857 SCIP_CALL( SCIPsetClockTime(target, target->stat->reoptupdatetime, tmptime) ); 858 859 heur = source->stat->firstprimalheur; 860 861 if( heur != NULL ) 862 target->stat->firstprimalheur = SCIPfindHeur(target, SCIPheurGetName(heur)); 863 864 target->stat->status = source->stat->status; 865 target->stat->lastbranchdir = source->stat->lastbranchdir; 866 target->stat->lastsblpsolstats[0] = source->stat->lastsblpsolstats[0]; 867 target->stat->lastsblpsolstats[1] = source->stat->lastsblpsolstats[1]; 868 target->stat->nnz = source->stat->nnz; 869 target->stat->lpcount = source->stat->lpcount; 870 target->stat->nlps = source->stat->nlps; 871 target->stat->nrootlps = source->stat->nrootlps; 872 target->stat->nprimallps = source->stat->nprimallps; 873 target->stat->nprimalzeroitlps = source->stat->nprimalzeroitlps; 874 target->stat->nduallps = source->stat->nduallps; 875 target->stat->ndualzeroitlps = source->stat->ndualzeroitlps; 876 target->stat->nlexduallps = source->stat->nlexduallps; 877 target->stat->nbarrierlps = source->stat->nbarrierlps; 878 target->stat->nbarrierzeroitlps = source->stat->nbarrierzeroitlps; 879 target->stat->nprimalresolvelps = source->stat->nprimalresolvelps; 880 target->stat->ndualresolvelps = source->stat->ndualresolvelps; 881 target->stat->nlexdualresolvelps = source->stat->nlexdualresolvelps; 882 target->stat->nnodelps = source->stat->nnodelps; 883 target->stat->ninitlps = source->stat->ninitlps; 884 target->stat->ndivinglps = source->stat->ndivinglps; 885 target->stat->ndivesetlps = source->stat->ndivesetlps; 886 target->stat->nsbdivinglps = source->stat->nsbdivinglps; 887 target->stat->nstrongbranchs = source->stat->nstrongbranchs; 888 target->stat->nrootstrongbranchs = source->stat->nrootstrongbranchs; 889 target->stat->nconflictlps = source->stat->nconflictlps; 890 target->stat->nnlps = source->stat->nnlps; 891 target->stat->nisstoppedcalls = source->stat->nisstoppedcalls; 892 target->stat->totaldivesetdepth = source->stat->totaldivesetdepth; 893 target->stat->ndivesetcalls = source->stat->ndivesetcalls; 894 target->stat->nruns = source->stat->nruns; 895 target->stat->nconfrestarts = source->stat->nconfrestarts; 896 target->stat->nrootboundchgs = source->stat->nrootboundchgs; 897 target->stat->nrootboundchgsrun = source->stat->nrootboundchgsrun; 898 target->stat->nrootintfixings = source->stat->nrootintfixings; 899 target->stat->nrootintfixingsrun = source->stat->nrootintfixingsrun; 900 target->stat->prevrunnvars = source->stat->prevrunnvars; 901 target->stat->npricerounds = source->stat->npricerounds; 902 target->stat->nseparounds = source->stat->nseparounds; 903 target->stat->maxdepth = source->stat->maxdepth; 904 target->stat->maxtotaldepth = source->stat->maxtotaldepth; 905 target->stat->plungedepth = source->stat->plungedepth; 906 target->stat->npresolrounds += source->stat->npresolrounds; 907 target->stat->npresolroundsfast += source->stat->npresolroundsfast; 908 target->stat->npresolroundsmed += source->stat->npresolroundsmed; 909 target->stat->npresolroundsext += source->stat->npresolroundsext; 910 target->stat->npresolfixedvars += source->stat->npresolfixedvars; 911 target->stat->npresolaggrvars += source->stat->npresolaggrvars; 912 target->stat->npresolchgvartypes += source->stat->npresolchgvartypes; 913 target->stat->npresolchgbds += source->stat->npresolchgbds; 914 target->stat->npresoladdholes += source->stat->npresoladdholes; 915 target->stat->npresoldelconss += source->stat->npresoldelconss; 916 target->stat->npresoladdconss += source->stat->npresoladdconss; 917 target->stat->npresolupgdconss += source->stat->npresolupgdconss; 918 target->stat->npresolchgcoefs += source->stat->npresolchgcoefs; 919 target->stat->npresolchgsides += source->stat->npresolchgsides; 920 target->stat->nrunsbeforefirst = source->stat->nrunsbeforefirst; 921 target->stat->firstprimaldepth = source->stat->firstprimaldepth; 922 target->stat->ncopies += source->stat->ncopies; 923 target->stat->nreoptruns = source->stat->nreoptruns; 924 925 /* set the stage but do not set to earlier stage */ 926 target->set->stage = MAX(source->set->stage, target->set->stage); 927 928 return SCIP_OKAY; 929 } 930