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-2025 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) ||
    499 (SCIPgetNLimSolsFound(syncstore->mainscip) > 0 && SCIPgetConcurrentPrimalbound(syncstore->mainscip) - SCIPgetConcurrentDualbound(syncstore->mainscip) <= syncstore->limit_absgap) )
    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 the 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 assumed to be followed by
    657 * SCIP_STATUS_INFEASIBLE and SCIP_STATUS_UNBOUNDED) and break ties by the solverid; remember the solver with the
    658 * best status so that the winner will be selected deterministically
    659 */
    660 if( syncdata->winner < 0 )
    661 {
    662 syncdata->status = status;
    663 syncdata->winner = solverid;
    664 }
    665 else if( syncdata->status < SCIP_STATUS_OPTIMAL )
    666 {
    667 if( status > syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
    668 {
    669 syncdata->status = status;
    670 syncdata->winner = solverid;
    671 }
    672 }
    673 else if( syncdata->status > SCIP_STATUS_OPTIMAL && status >= SCIP_STATUS_OPTIMAL )
    674 {
    675 if( status < syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
    676 {
    677 syncdata->status = status;
    678 syncdata->winner = solverid;
    679 }
    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:317
    SCIP_Real SCIPgetConcurrentPrimalbound(SCIP *scip)
    Definition: concurrent.c:332
    int SCIPgetNConcurrentSolvers(SCIP *scip)
    Definition: concurrent.c:126
    SCIP_Real SCIPgetConcurrentGap(SCIP *scip)
    Definition: concurrent.c:347
    helper functions for concurrent scip solvers
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_CALL(x)
    Definition: def.h:355
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    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:10511
    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_Longint SCIPgetNLimSolsFound(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:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_UNKNOWN
    Definition: type_stat.h:42
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    enum SCIP_Parallelmode SCIP_PARALLELMODE
    @ SCIP_PARA_DETERMINISTIC
    struct SCIP_SyncData SCIP_SYNCDATA