Scippy

SCIP

Solving Constraint Integer Programs

syncstore.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 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 syncstore.c
26 * @ingroup PARALLEL
27 * @brief the function definitions of the synchronization store
28 * @author Leona Gottwald
29 * @author Stephen J. Maher
30 * @author Marc Pfetsch
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
35#include <assert.h>
36
37#include "scip/def.h"
38#include "scip/pub_message.h"
39#include "scip/concsolver.h"
41#include "scip/prob.h"
42#include "scip/scip.h"
44#include "tpi/tpi.h"
46#include "scip/concurrent.h"
47#include "scip/syncstore.h"
48#include "scip/boundstore.h"
49
50
51/** computes the size of the array of synchronization datas, such that
52 * it cannot ever happen that a synchronization data is reused while still
53 * not read by any thread */
54static
56 SCIP* scip /**< SCIP main datastructure */
57 )
58{
59 int maxnsyncdelay;
60
61 SCIP_CALL_ABORT( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &maxnsyncdelay) );
62
63 return 2 * (maxnsyncdelay + 1);
64}
65
66/** creates and captures a new synchronization store */
68 SCIP_SYNCSTORE** syncstore /**< pointer to return the created synchronization store */
69 )
70{
71 assert(syncstore != NULL);
72
73 SCIPdebugMessage("SCIPsyncstoreCreate()\n");
74
75 SCIP_ALLOC( BMSallocMemory(syncstore) );
76
77 (*syncstore)->mode = SCIP_PARA_DETERMINISTIC; /* initialising the mode */
78 (*syncstore)->initialized = FALSE;
79 (*syncstore)->syncdata = NULL;
80 (*syncstore)->stopped = FALSE;
81 (*syncstore)->nuses = 1;
82
83 SCIP_CALL( SCIPtpiInitLock(&(*syncstore)->lock) );
84
85 return SCIP_OKAY;
86}
87
88/** releases a synchronization store */
90 SCIP_SYNCSTORE** syncstore /**< pointer to the synchronization store */
91 )
92{
93 int references;
94
95 assert(syncstore != NULL);
96 if( *syncstore == NULL )
97 return SCIP_OKAY;
98
99 SCIP_CALL( SCIPtpiAcquireLock((*syncstore)->lock) );
100 (*syncstore)->nuses -= 1;
101 references = (*syncstore)->nuses;
102 SCIP_CALL( SCIPtpiReleaseLock((*syncstore)->lock) );
103
104 if( references == 0 )
105 {
106 if( (*syncstore)->initialized )
107 {
108 SCIP_CALL( SCIPsyncstoreExit(*syncstore) );
109 }
110
111 assert(!(*syncstore)->initialized);
112 SCIPtpiDestroyLock(&(*syncstore)->lock);
113 BMSfreeMemory(syncstore);
114 }
115 else
116 {
117 *syncstore = NULL;
118 }
119
120 return SCIP_OKAY;
121}
122
123/** captures a synchronization store */
125 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
126 )
127{
128 SCIP_CALL( SCIPtpiAcquireLock(syncstore->lock) );
129
130 ++(syncstore->nuses);
131
132 SCIP_CALL( SCIPtpiReleaseLock(syncstore->lock) );
133
134 return SCIP_OKAY;
135}
136
137/** initialize the syncstore for the given SCIP instance */
139 SCIP* scip /**< SCIP main datastructure */
140 )
141{
142 SCIP_SYNCSTORE* syncstore;
143 int i;
144 int j;
145 int paramode;
146
147 assert(scip != NULL);
148 syncstore = SCIPgetSyncstore(scip);
149 assert(syncstore != NULL);
150 syncstore->mainscip = scip;
151 SCIP_CALL( SCIPgetRealParam(scip, "limits/gap", &syncstore->limit_gap) );
152 SCIP_CALL( SCIPgetRealParam(scip, "limits/absgap", &syncstore->limit_absgap) );
153 syncstore->lastsync = NULL;
155
156 syncstore->ninitvars = SCIPgetNVars(scip);
157 SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsols", &syncstore->maxnsols) );
158 SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &syncstore->maxnsyncdelay) );
159 SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/minsyncdelay", &syncstore->minsyncdelay) );
160 SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqinit", &syncstore->syncfreqinit) );
161 SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqmax", &syncstore->syncfreqmax) );
162 syncstore->nsyncdata = getNSyncdata(scip);
163 SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &(syncstore->syncdata), syncstore->nsyncdata) );
164
165 for( i = 0; i < syncstore->nsyncdata; ++i )
166 {
167 syncstore->syncdata[i].syncnum = -1;
168 SCIP_CALL( SCIPboundstoreCreate(syncstore->mainscip, &syncstore->syncdata[i].boundstore, syncstore->ninitvars) );
169 SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols) );
170 SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols) );
171 SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols) );
172
173 for( j = 0; j < syncstore->maxnsols; ++j )
174 {
175 SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars) );
176 }
177
178 SCIP_CALL( SCIPtpiInitLock(&(syncstore->syncdata[i].lock)) );
179 SCIP_CALL( SCIPtpiInitCondition(&(syncstore->syncdata[i].allsynced)) );
180 }
181
182 syncstore->initialized = TRUE;
183 syncstore->stopped = FALSE;
184
185 SCIP_CALL( SCIPgetIntParam(scip, "parallel/mode", &paramode) );
186 syncstore->mode = (SCIP_PARALLELMODE) paramode;
187
188 SCIP_CALL( SCIPtpiInit(syncstore->nsolvers, INT_MAX, FALSE) );
190
191 if( syncstore->mode == SCIP_PARA_DETERMINISTIC )
192 {
193 /* in deterministic mode use the number of non-zeros and the number of variables to get a good
194 * syncdelay and maximum syncfreq
195 */
196 syncstore->minsyncdelay *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip)); /*lint !e790*/
197 syncstore->syncfreqmax *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip)); /*lint !e790*/
198 }
199
200 return SCIP_OKAY;
201}
202
203/** deinitializes the synchronization store */
205 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
206 )
207{
208 int i;
209 int j;
210
211 assert(syncstore != NULL);
212 assert(syncstore->initialized);
213
215
216 for( i = 0; i < syncstore->nsyncdata; ++i )
217 {
218 SCIPtpiDestroyLock(&(syncstore->syncdata[i].lock));
219 SCIPtpiDestroyCondition(&(syncstore->syncdata[i].allsynced));
220 SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols);
221 SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols);
222 SCIPboundstoreFree(syncstore->mainscip, &syncstore->syncdata[i].boundstore);
223
224 for( j = 0; j < syncstore->maxnsols; ++j )
225 {
226 SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars);
227 }
228
229 SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols);
230 }
231
232 SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata, syncstore->nsyncdata);
233
234 syncstore->initialized = FALSE;
235 syncstore->stopped = FALSE;
236
237 return SCIP_OKAY;
238}
239
240/** checks whether the solve-is-stopped flag in the syncstore has been set by any thread */
242 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
243 )
244{
245 SCIP_Bool stopped;
246
248
249 stopped = syncstore->stopped;
250
252
253 return stopped;
254}
255
256/** sets the solve-is-stopped flag in the syncstore so that subsequent calls to
257 * SCIPsyncstoreSolveIsStopped will return the given value in any thread
258 */
260 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
261 SCIP_Bool stopped /**< flag if the solve is stopped */
262 )
263{
265
266 syncstore->stopped = stopped;
267
269}
270
271/** gets the upperbound from the last synchronization */
273 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
274 )
275{
276 assert(syncstore != NULL);
277 assert(syncstore->initialized);
278
279 return syncstore->lastsync == NULL ? SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestupperbound;
280}
281
282/** gets the lowerbound from the last synchronization */
284 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
285 )
286{
287 assert(syncstore != NULL);
288 assert(syncstore->initialized);
289
290 return syncstore->lastsync == NULL ? -SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestlowerbound;
291}
292
293/** gets the number of solutions from the last synchronization */
295 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
296 )
297{
298 assert(syncstore != NULL);
299 assert(syncstore->initialized);
300
301 return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->nsols;
302}
303
304/** gets the number of boundchanges from the last synchronization */
306 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
307 )
308{
309 assert(syncstore != NULL);
310 assert(syncstore->initialized);
311
312 return syncstore->lastsync == NULL ? 0 : SCIPboundstoreGetNChgs(syncstore->lastsync->boundstore);
313}
314
315/** gets total memory used by all solvers from the last synchronization */
317 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
318 )
319{
320 assert(syncstore != NULL);
321 assert(syncstore->initialized);
322
323 return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->memtotal;
324}
325
326/** gets the synchronization frequency from the last synchronization */
328 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
329 )
330{
331 assert(syncstore != NULL);
332 assert(syncstore->initialized);
333
334 return syncstore->lastsync == NULL ? 0.0 : syncstore->lastsync->syncfreq;
335}
336
337/** get synchronization data with given number. It is the responsibility of the caller
338 * to only ask for a synchronization number that still exists, which is checked
339 * with an assert in debug mode. */
341 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
342 SCIP_Longint syncnum /**< the number of the synchronization to start, which
343 * must be increasing between calls of the same thread */
344 )
345{
346 int j;
347
348 assert(syncstore != NULL);
349 assert(syncstore->initialized);
350
351 j = (int) syncnum % syncstore->nsyncdata;
352
353 /* check if requested syncnumber still exists if in debug mode */
354 assert(syncstore->syncdata[j].syncnum == syncnum);
355
356 return &syncstore->syncdata[j];
357}
358
359/** get the next synchronization data that should be read and
360 * adjust the delay. Returns NULL if no more data should be read due to minimum delay */
362 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
363 SCIP_SYNCDATA* syncdata, /**< the synchronization data */
364 SCIP_Real syncfreq, /**< the current synchronization frequency */
365 SCIP_Longint writenum, /**< number of synchronizations the solver has written to */
366 SCIP_Real* delay /**< pointer holding the current synchronization delay */
367 )
368{
369 SCIP_Real newdelay;
370 SCIP_Longint nextsyncnum;
371
372 assert(syncstore != NULL);
373 assert(syncstore->initialized);
374 assert(delay != NULL);
375
376 if( syncdata == NULL )
377 {
378 nextsyncnum = 0;
379 }
380 else
381 {
382 if( syncdata->status != SCIP_STATUS_UNKNOWN )
383 return NULL;
384
385 nextsyncnum = syncdata->syncnum + 1;
386 }
387
388 if( nextsyncnum == writenum )
389 return NULL;
390
391 newdelay = *delay - syncfreq;
392
393 /* if the delay would get too small we dont want to read the next syncdata.
394 * But due to the limited length of the syncdata array we might need to
395 * read this synchronization data anyways which is checked by the second part
396 * of the if condition
397 */
398 if( newdelay < syncstore->minsyncdelay && nextsyncnum >= writenum - syncstore->maxnsyncdelay )
399 return NULL;
400
401 *delay = newdelay;
402 assert(syncstore->syncdata[nextsyncnum % syncstore->nsyncdata].syncnum == nextsyncnum);
403
404 return &syncstore->syncdata[nextsyncnum % syncstore->nsyncdata];
405}
406
407/** ensures that the given synchronization data has been written by
408 * all solvers upon return of this function and blocks the caller if necessary. */
410 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
411 SCIP_SYNCDATA* syncdata /**< the synchronization data */
412 )
413{
414 assert(syncdata != NULL);
415 assert(syncstore != NULL);
416 assert(syncstore->initialized);
417
418 /* check if waiting is required, make sure to hold the lock */
419 SCIP_CALL( SCIPtpiAcquireLock(syncdata->lock) );
420
421 while( syncdata->syncedcount < syncstore->nsolvers )
422 {
423 /* yes, so wait on the condition variable
424 * (automatically releases the lock and reacquires it after the waiting)
425 */
426 SCIP_CALL( SCIPtpiWaitCondition(syncdata->allsynced, syncdata->lock) );
427 }
428
429 SCIP_CALL( SCIPtpiReleaseLock(syncdata->lock) );
430
431 return SCIP_OKAY;
432}
433
434/** Start synchronization for the given concurrent solver.
435 * Needs to be followed by a call to SCIPsyncstoreFinishSync if
436 * the syncdata that is returned is not NULL
437 */
439 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
440 SCIP_Longint syncnum, /**< the number of the synchronization to start, which
441 * must be increasing between calls of the same thread */
442 SCIP_SYNCDATA** syncdata /**< pointer to return the synchronization data */
443 )
444{
445 int i;
446
447 assert(syncdata != NULL);
448 assert(syncstore != NULL);
449 assert(syncstore->initialized);
450
451 if( SCIPsyncstoreSolveIsStopped(syncstore) )
452 {
453 *syncdata = NULL;
454 return SCIP_OKAY;
455 }
456
457 i = syncnum % syncstore->nsyncdata; /*lint !e712*/
458 *syncdata = &syncstore->syncdata[i];
459 assert(*syncdata != NULL);
460
461 SCIP_CALL( SCIPtpiAcquireLock((*syncdata)->lock) );
462
463 if( (*syncdata)->syncnum != syncnum )
464 {
465 SCIPboundstoreClear((*syncdata)->boundstore);
466 (*syncdata)->nsols = 0;
467 (*syncdata)->memtotal = SCIPgetMemTotal(syncstore->mainscip);
468 (*syncdata)->syncedcount = 0;
469 (*syncdata)->bestupperbound = SCIPinfinity(syncstore->mainscip);
470 (*syncdata)->bestlowerbound = -(*syncdata)->bestupperbound;
471 (*syncdata)->status = SCIP_STATUS_UNKNOWN;
472 (*syncdata)->winner = 0;
473 (*syncdata)->syncnum = syncnum;
474 (*syncdata)->syncfreq = 0.0;
475 }
476
477 return SCIP_OKAY;
478}
479
480/** finishes synchronization for the synchronization data */
482 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
483 SCIP_SYNCDATA** syncdata /**< the synchronization data */
484 )
485{
486 SCIP_Bool printline = FALSE;
487
488 assert(syncdata != NULL);
489 assert((*syncdata) != NULL);
490 assert(syncstore != NULL);
491 assert(syncstore->initialized);
492
493 ++(*syncdata)->syncedcount;
494
495 if( (*syncdata)->syncedcount == syncstore->nsolvers )
496 {
497 if( (*syncdata)->status != SCIP_STATUS_UNKNOWN ||
498 (SCIPgetConcurrentGap(syncstore->mainscip) <= syncstore->limit_gap) ||
501
502 syncstore->lastsync = *syncdata;
503 printline = TRUE;
504
505 SCIP_CALL( SCIPtpiBroadcastCondition((*syncdata)->allsynced) );
506 }
507
508 SCIP_CALL( SCIPtpiReleaseLock((*syncdata)->lock) );
509
510 if( printline )
511 {
513 }
514
515 *syncdata = NULL;
516
517 return SCIP_OKAY;
518}
519
520/** gets status in synchronization data */
522 SCIP_SYNCDATA* syncdata /**< the synchronization data */
523 )
524{
525 assert(syncdata != NULL);
526
527 return syncdata->status;
528}
529
530/** gets the solver that had the best status, or -1 if solve is not stopped yet */
532 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
533 )
534{
535 assert(syncstore != NULL);
536 assert(syncstore->initialized);
537
538 if( syncstore->lastsync == NULL || syncstore->lastsync->status == SCIP_STATUS_UNKNOWN )
539 return -1;
540
541 return syncstore->lastsync->winner;
542}
543
544/** how many solvers have already finished synchronizing on this sychronization data */
546 SCIP_SYNCDATA* syncdata /**< the synchronization data */
547 )
548{
549 assert(syncdata != NULL);
550
551 return syncdata->syncedcount;
552}
553
554/** how many solvers have are running concurrently */
556 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
557 )
558{
559 assert(syncstore != NULL);
560 assert(syncstore->initialized);
561
562 return syncstore->nsolvers;
563}
564
565/** read amount total memory used from synchronization data */
567 SCIP_SYNCDATA* syncdata /**< the synchronization data */
568 )
569{
570 assert(syncdata != NULL);
571
572 return syncdata->memtotal;
573}
574
575/** read the synchronization frequency from a synchronization data */
577 SCIP_SYNCDATA* syncdata /**< the synchronization data */
578 )
579{
580 assert(syncdata != NULL);
581
582 return syncdata->syncfreq;
583}
584
585/** read the upperbound stored in a synchronization data */
587 SCIP_SYNCDATA* syncdata /**< the synchronization data */
588 )
589{
590 assert(syncdata != NULL);
591
592 return syncdata->bestupperbound;
593}
594
595/** read the lowerbound stored in a synchronization data */
597 SCIP_SYNCDATA* syncdata /**< the synchronization data */
598 )
599{
600 assert(syncdata != NULL);
601
602 return syncdata->bestlowerbound;
603}
604
605/** read the solutions stored in a synchronization data */
607 SCIP_SYNCDATA* syncdata, /**< the synchronization data */
608 SCIP_Real*** solvalues, /**< array of buffers containing the solution values */
609 int** solowner, /**< array of ownerids of solutions */
610 int* nsols /**< pointer to return number of solutions */
611 )
612{
613 assert(syncdata != NULL);
614 assert(solvalues != NULL);
615 assert(solowner != NULL);
616 assert(nsols != NULL);
617
618 *solvalues = syncdata->sols;
619 *solowner = syncdata->solsource;
620 *nsols = syncdata->nsols;
621}
622
623/** read bound changes stored in the synchronization data */
625 SCIP_SYNCDATA* syncdata /**< the synchronization data */
626 )
627{
628 assert(syncdata != NULL);
629
630 return syncdata->boundstore;
631}
632
633/** write the synchronization frequency to a synchronization data */
635 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
636 SCIP_SYNCDATA* syncdata, /**< the synchronization data */
637 SCIP_Real syncfreq /**< the synchronization frequency */
638 )
639{
640 assert(syncstore != NULL);
641 assert(syncstore->initialized);
642 assert(syncdata != NULL);
643
644 syncdata->syncfreq = MIN(syncfreq, syncstore->syncfreqmax);
645}
646
647/** set status in the synchronization data */
649 SCIP_SYNCDATA* syncdata, /**< the synchronization data the upperbound should be added to */
650 SCIP_STATUS status, /**< the status */
651 int solverid /**< identifier of te solver that has this status */
652 )
653{
654 assert(syncdata != NULL);
655
656 /* check if status is better than current one (closer to SCIP_STATUS_OPTIMAL),
657 * break ties by the solverid, and remember the solver wit the best status
658 * so that the winner will be selected deterministically
659 */
660 if( syncdata->status < SCIP_STATUS_OPTIMAL )
661 {
662 if( status > syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
663 {
664 syncdata->status = status;
665 syncdata->winner = solverid;
666 }
667 }
668 else if( syncdata->status > SCIP_STATUS_OPTIMAL && status >= SCIP_STATUS_OPTIMAL )
669 {
670 if( status < syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
671 {
672 syncdata->status = status;
673 syncdata->winner = solverid;
674 }
675 }
676 else if( syncdata->winner < 0 )
677 {
678 syncdata->status = status;
679 syncdata->winner = solverid;
680 }
681}
682
683/** adds memory used to the synchronization data */
685 SCIP_SYNCDATA* syncdata, /**< the synchronization data the solution should be added to */
686 SCIP_Longint memtotal /**< the number of bytes used */
687 )
688{
689 assert(syncdata != NULL);
690
691 syncdata->memtotal += memtotal;
692}
693
694/** set upperbound to the synchronization data */
696 SCIP_SYNCDATA* syncdata, /**< the synchronization data the upperbound should be added to */
697 SCIP_Real upperbound /**< the upperbound */
698 )
699{
700 assert(syncdata != NULL);
701
702 syncdata->bestupperbound = MIN(syncdata->bestupperbound, upperbound);
703}
704
705/** set lowerbound to the synchronization data */
707 SCIP_SYNCDATA* syncdata, /**< the synchronization data the lowerbound should be added to */
708 SCIP_Real lowerbound /**< the lowerbound */
709 )
710{
711 assert(syncdata != NULL);
712
713 syncdata->bestlowerbound = MAX(syncdata->bestlowerbound, lowerbound);
714}
715
716/** gives a buffer to store the solution values, or NULL if solution should not be stored
717 * because there are already better solutions stored.
718 */
720 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
721 SCIP_SYNCDATA* syncdata, /**< the synchronization data the solution should be added to */
722 SCIP_Real solobj, /**< the objective value of the solution */
723 int ownerid, /**< an identifier for the owner of the solution, e.g. the thread number */
724 SCIP_Real** buffer /**< pointer to return a buffer for the solution values, which must be set
725 * if the buffer is not NULL */
726 )
727{
728 int pos;
729 int i;
730
731 assert(syncstore != NULL);
732 assert(syncstore->initialized);
733 assert(syncdata != NULL);
734 assert(buffer != NULL);
735
736 for( pos = 0; pos < syncdata->nsols; ++pos )
737 {
738 if( syncdata->solobj[pos] < solobj || (syncdata->solobj[pos] == solobj && ownerid < syncdata->solsource[pos]) ) /*lint !e777*/
739 break;
740 }
741
742 if( syncdata->nsols < syncstore->maxnsols )
743 {
744 for( i = syncdata->nsols; i > pos; --i )
745 {
746 syncdata->solobj[i] = syncdata->solobj[i - 1];
747 syncdata->solsource[i] = syncdata->solsource[i - 1];
748 SCIPswapPointers((void**) &syncdata->sols[i], (void**) &syncdata->sols[i - 1]);
749 }
750
751 ++syncdata->nsols;
752 }
753 else
754 {
755 --pos;
756
757 for( i = 0; i < pos; ++i )
758 {
759 syncdata->solobj[i] = syncdata->solobj[i + 1];
760 syncdata->solsource[i] = syncdata->solsource[i + 1];
761 SCIPswapPointers((void**) &syncdata->sols[i], (void**) &syncdata->sols[i + 1]);
762 }
763 }
764
765 if( pos >= 0 )
766 {
767 syncdata->solobj[pos] = solobj;
768 syncdata->solsource[pos] = ownerid;
769 *buffer = syncdata->sols[pos];
770 }
771 else
772 {
773 *buffer = NULL;
774 }
775}
776
777/** adds bound changes to the synchronization data */
779 SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
780 SCIP_SYNCDATA* syncdata, /**< the synchronization data */
781 SCIP_BOUNDSTORE* boundstore /**< bound store containing the bounds to add */
782 )
783{
784 assert(syncstore != NULL);
785 assert(syncstore->initialized);
786 assert(syncdata != NULL);
787 assert(boundstore != NULL);
788
789 SCIP_CALL( SCIPboundstoreMerge(syncstore->mainscip, syncdata->boundstore, boundstore) );
790
791 return SCIP_OKAY;
792}
793
794/** is synchronization store initialized */
796 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
797 )
798{
799 assert(syncstore != NULL);
800
801 return syncstore->initialized;
802}
803
804/** returns the mode of the synchronization store */
806 SCIP_SYNCSTORE* syncstore /**< the synchronization store */
807 )
808{
809 assert(syncstore != NULL);
810
811 return syncstore->mode;
812}
SCIP_RETCODE SCIPboundstoreMerge(SCIP *scip, SCIP_BOUNDSTORE *target, SCIP_BOUNDSTORE *source)
Definition: boundstore.c:124
void SCIPboundstoreFree(SCIP *scip, SCIP_BOUNDSTORE **boundstore)
Definition: boundstore.c:60
SCIP_RETCODE SCIPboundstoreCreate(SCIP *scip, SCIP_BOUNDSTORE **boundstore, int nvars)
Definition: boundstore.c:39
void SCIPboundstoreClear(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:146
int SCIPboundstoreGetNChgs(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:197
the interface of the boundstore structure
datastructures for concurrent solvers
SCIP_Real SCIPgetConcurrentDualbound(SCIP *scip)
Definition: concurrent.c:306
SCIP_Real SCIPgetConcurrentPrimalbound(SCIP *scip)
Definition: concurrent.c:321
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:117
SCIP_Real SCIPgetConcurrentGap(SCIP *scip)
Definition: concurrent.c:336
helper functions for concurrent scip solvers
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:266
#define SCIP_Longint
Definition: def.h:157
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_CALL(x)
Definition: def.h:373
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:307
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
SCIP_RETCODE SCIPautoselectDisps(SCIP *scip)
Definition: scip_disp.c:132
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
SCIP_Longint SCIPgetMemTotal(SCIP *scip)
Definition: scip_mem.c:113
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
SCIP_Longint SCIPgetNNZs(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
memory allocation routines
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSallocMemory(ptr)
Definition: memory.h:118
internal methods for storing and manipulating the main problem
public methods for message output
#define SCIPdebugMessage
Definition: pub_message.h:96
SCIP callable library.
SCIP_Real limit_gap
SCIP_Bool initialized
SCIP_SYNCDATA * syncdata
SCIP_Real limit_absgap
SCIP_Real syncfreqmax
SCIP_Real syncfreqinit
SCIP_PARALLELMODE mode
SCIP_LOCK * lock
SCIP_SYNCDATA * lastsync
SCIP_Real minsyncdelay
datastructures for concurrent solvers
the struct definitions for the synchronization store
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:241
SCIP_Real SCIPsyncdataGetSyncFreq(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:576
SCIP_Longint SCIPsyncdataGetMemTotal(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:566
SCIP_BOUNDSTORE * SCIPsyncdataGetBoundChgs(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:624
SCIP_Real SCIPsyncstoreGetLastUpperbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:272
SCIP_RETCODE SCIPsyncstoreFinishSync(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:481
SCIP_Real SCIPsyncstoreGetLastLowerbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:283
SCIP_Real SCIPsyncdataGetUpperbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:586
void SCIPsyncdataSetUpperbound(SCIP_SYNCDATA *syncdata, SCIP_Real upperbound)
Definition: syncstore.c:695
SCIP_RETCODE SCIPsyncdataAddBoundChanges(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_BOUNDSTORE *boundstore)
Definition: syncstore.c:778
int SCIPsyncstoreGetWinner(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:531
SCIP_RETCODE SCIPsyncstoreEnsureAllSynced(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:409
void SCIPsyncdataSetSyncFreq(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq)
Definition: syncstore.c:634
SCIP_Real SCIPsyncstoreGetLastSyncfreq(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:327
void SCIPsyncdataGetSolutions(SCIP_SYNCDATA *syncdata, SCIP_Real ***solvalues, int **solowner, int *nsols)
Definition: syncstore.c:606
void SCIPsyncdataSetStatus(SCIP_SYNCDATA *syncdata, SCIP_STATUS status, int solverid)
Definition: syncstore.c:648
void SCIPsyncstoreSetSolveIsStopped(SCIP_SYNCSTORE *syncstore, SCIP_Bool stopped)
Definition: syncstore.c:259
SCIP_RETCODE SCIPsyncstoreRelease(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:89
SCIP_Longint SCIPsyncstoreGetLastMemTotal(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:316
SCIP_RETCODE SCIPsyncstoreExit(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:204
void SCIPsyncdataSetLowerbound(SCIP_SYNCDATA *syncdata, SCIP_Real lowerbound)
Definition: syncstore.c:706
SCIP_RETCODE SCIPsyncstoreCapture(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:124
int SCIPsyncstoreGetLastNBounds(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:305
static int getNSyncdata(SCIP *scip)
Definition: syncstore.c:55
int SCIPsyncstoreGetLastNSols(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:294
SCIP_RETCODE SCIPsyncstoreStartSync(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:438
void SCIPsyncdataGetSolutionBuffer(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real solobj, int ownerid, SCIP_Real **buffer)
Definition: syncstore.c:719
SCIP_Real SCIPsyncdataGetLowerbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:596
SCIP_PARALLELMODE SCIPsyncstoreGetMode(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:805
SCIP_RETCODE SCIPsyncstoreCreate(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:67
int SCIPsyncdataGetNSynced(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:545
SCIP_SYNCDATA * SCIPsyncstoreGetSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum)
Definition: syncstore.c:340
SCIP_Bool SCIPsyncstoreIsInitialized(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:795
SCIP_SYNCDATA * SCIPsyncstoreGetNextSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq, SCIP_Longint writenum, SCIP_Real *delay)
Definition: syncstore.c:361
void SCIPsyncdataAddMemTotal(SCIP_SYNCDATA *syncdata, SCIP_Longint memtotal)
Definition: syncstore.c:684
int SCIPsyncstoreGetNSolvers(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:555
SCIP_STATUS SCIPsyncdataGetStatus(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:521
SCIP_RETCODE SCIPsyncstoreInit(SCIP *scip)
Definition: syncstore.c:138
the function declarations for the synchronization store
the type definitions for the SCIP parallel interface
SCIP_RETCODE SCIPtpiWaitCondition(SCIP_CONDITION *condition, SCIP_LOCK *lock)
Definition: tpi_none.c:125
SCIP_RETCODE SCIPtpiAcquireLock(SCIP_LOCK *lock)
Definition: tpi_none.c:65
SCIP_RETCODE SCIPtpiExit(void)
Definition: tpi_none.c:217
SCIP_RETCODE SCIPtpiBroadcastCondition(SCIP_CONDITION *condition)
Definition: tpi_none.c:115
void SCIPtpiDestroyLock(SCIP_LOCK **lock)
Definition: tpi_none.c:56
void SCIPtpiDestroyCondition(SCIP_CONDITION **condition)
Definition: tpi_none.c:98
SCIP_RETCODE SCIPtpiInitLock(SCIP_LOCK **lock)
Definition: tpi_none.c:45
SCIP_RETCODE SCIPtpiReleaseLock(SCIP_LOCK *lock)
Definition: tpi_none.c:73
SCIP_RETCODE SCIPtpiInitCondition(SCIP_CONDITION **condition)
Definition: tpi_none.c:87
SCIP_RETCODE SCIPtpiInit(int nthreads, int queuesize, SCIP_Bool blockwhenfull)
Definition: tpi_none.c:203
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:61
@ SCIP_STATUS_UNKNOWN
Definition: type_stat.h:42
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:67
enum SCIP_Parallelmode SCIP_PARALLELMODE
@ SCIP_PARA_DETERMINISTIC
struct SCIP_SyncData SCIP_SYNCDATA