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