SCIP

    Solving Constraint Integer Programs

    heur_padm.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-2026 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 heur_padm.c
    26 * @brief PADM primal heuristic
    27 * @author Dieter Weninger
    28 * @author Katrin Halbig
    29 *
    30 * Primal heuristic based on ideas published in the papers
    31 * "A Decomposition Heuristic for Mixed-Integer Supply Chain Problems" by Martin Schmidt, Lars Schewe, and Dieter Weninger,
    32 * and "Exploiting user-supplied Decompositions inside Heuristics" by Katrin Halbig, Adrian Göß and Dieter Weninger.
    33 *
    34 * The penalty alternating direction method (PADM) heuristic is a construction heuristic which additionally needs a
    35 * user decomposition with linking variables only.
    36 *
    37 * PADM splits the problem into several sub-SCIPs according to the decomposition, whereby the linking variables get
    38 * copied and the difference is penalized. Then the sub-SCIPs are solved on an alternating basis until they arrive at
    39 * the same values of the linking variables (ADM-loop). If they don't reconcile after a couple of iterations,
    40 * the penalty parameters are increased (penalty-loop) and the sub-SCIPs are solved again on an alternating basis.
    41 */
    42
    43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    44
    46#include "scip/cons_linear.h"
    47#include "scip/debug.h"
    48#include "scip/heur_padm.h"
    49#include "scip/heuristics.h"
    50#include "scip/pub_cons.h"
    51#include "scip/pub_tree.h"
    52#include "scip/pub_heur.h"
    53#include "scip/pub_message.h"
    54#include "scip/pub_misc.h"
    56#include "scip/pub_sol.h"
    57#include "scip/pub_var.h"
    58#include "scip/scipdefplugins.h"
    59#include "scip/scip_branch.h"
    60#include "scip/scip_cons.h"
    61#include "scip/scip_copy.h"
    62#include "scip/scip_dcmp.h"
    63#include "scip/scip_general.h"
    64#include "scip/scip_heur.h"
    65#include "scip/scip_lp.h"
    66#include "scip/scip_mem.h"
    67#include "scip/scip_message.h"
    68#include "scip/scip_nodesel.h"
    69#include "scip/scip_numerics.h"
    70#include "scip/scip_param.h"
    71#include "scip/scip_prob.h"
    73#include "scip/scip_sol.h"
    74#include "scip/scip_solve.h"
    76#include "scip/scip_table.h"
    77#include "scip/scip_timing.h"
    78#include "scip/scip_tree.h"
    79#include "scip/scip_var.h"
    80
    81#define HEUR_NAME "padm"
    82#define HEUR_DESC "penalty alternating direction method primal heuristic"
    83#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    84#define HEUR_PRIORITY 70000
    85#define HEUR_FREQ 0
    86#define HEUR_FREQOFS 0
    87#define HEUR_MAXDEPTH -1
    88#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE | SCIP_HEURTIMING_AFTERNODE
    89#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    90
    91#define COUPLINGSIZE 3
    92#define DEFAULT_MINNODES 50LL
    93#define DEFAULT_MAXNODES 5000LL
    94#define DEFAULT_NODEFAC 0.8
    95#define DEFAULT_ADMIT 4
    96#define DEFAULT_PENALTYIT 100
    97#define DEFAULT_GAP 2.0
    98
    99/*
    100 * Data structures
    101 */
    102
    103/** data related to one problem (see below) */
    104typedef struct Problem PROBLEM;
    105
    106/** data related to one block */
    107typedef struct Block
    108{
    109 PROBLEM* problem; /**< the problem this block belongs to */
    110 SCIP* subscip; /**< sub-SCIP representing this block */
    111 int number; /**< component number */
    112 SCIP_VAR** subvars; /**< variables belonging to this block (without slack variables) */
    113 int nsubvars; /**< number of variables belonging to this block (without slack variables) */
    114 SCIP_VAR** slackspos; /**< positive slack variables */
    115 SCIP_VAR** slacksneg; /**< negative slack variables */
    116 SCIP_CONS** couplingcons; /**< coupling contraints */
    117 int ncoupling; /**< number of coupling contraints (equal to positive/negative slack variables) */
    118 SCIP_Real size; /**< share of total problem */
    120
    121/** data related to one problem */
    122struct Problem
    123{
    124 SCIP* scip; /**< the SCIP instance this problem belongs to */
    125 char* name; /**< name of the problem */
    126 BLOCK* blocks; /**< blocks into which the problem will be divided */
    127 int nblocks; /**< number of blocks */
    128};
    129
    130/** set data structure */
    131typedef struct set
    132{
    133 int size; /**< size of the set */
    134 int* indexes; /**< set of indexes */
    136
    137/** data of one linking variable related to one block */
    138typedef struct blockinfo
    139{
    140 int block; /**< index of this block */
    141 int otherblock; /**< index of the other connected block */
    142 int linkvaridx; /**< linking variable index */
    143 SCIP_Real linkvarval; /**< value of linking variable */
    144 SCIP_VAR* linkvar; /**< linking variable */
    145 SCIP_Real slackposobjcoeff; /**< penalty coefficient of positive slack variable */
    146 SCIP_VAR* slackposvar; /**< positive slack variable */
    147 SCIP_Real slacknegobjcoeff; /**< penalty coefficient of negative slack variable */
    148 SCIP_VAR* slacknegvar; /**< negative slack variable */
    149 SCIP_CONS* couplingCons; /**< coupling contraint (equation) */
    151
    152/** returns TRUE iff both keys are equal */
    153static
    155{ /*lint --e{715}*/
    156 BLOCKINFO* binfo1;
    157 BLOCKINFO* binfo2;
    158
    159 binfo1 = (BLOCKINFO*) key1;
    160 binfo2 = (BLOCKINFO*) key2;
    161
    162 if( binfo1->block != binfo2->block || binfo1->otherblock != binfo2->otherblock ||
    163 binfo1->linkvaridx != binfo2->linkvaridx )
    164 return FALSE;
    165
    166 return TRUE;
    167}
    168
    169/** returns the hash value of the key */
    170static
    171SCIP_DECL_HASHKEYVAL(indexesHashval)
    172{ /*lint --e{715}*/
    173 BLOCKINFO* binfo;
    174 binfo = (BLOCKINFO*) key;
    175
    176 return SCIPhashFour(SCIPrealHashCode((double)binfo->block), SCIPrealHashCode((double)binfo->otherblock),
    177 SCIPrealHashCode((double)binfo->linkvaridx), SCIPrealHashCode((double)binfo->linkvaridx));
    178}
    179
    180/** primal heuristic data */
    181struct SCIP_HeurData
    182{
    183 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in all subproblems */
    184 SCIP_Longint minnodes; /**< minimum number of nodes to regard in one subproblem */
    185 int admiterations; /**< maximal number of ADM iterations in each penalty loop */
    186 int penaltyiterations; /**< maximal number of penalty iterations */
    187 int timing; /**< should the heuristic run before or after the processing of the node?
    188 (0: before, 1: after, 2: both) */
    189 SCIP_Real nodefac; /**< factor to control nodelimits of subproblems */
    190 SCIP_Real gap; /**< mipgap at start */
    191 SCIP_Bool reoptimize; /**< should the problem get reoptimized with the original objective function? */
    192 SCIP_Bool scaling; /**< enable sigmoid rescaling of penalty parameters */
    193 SCIP_Bool assignlinking; /**< should linking constraints be assigned? */
    194 SCIP_Bool original; /**< should the original problem be used? */
    195};
    196
    197/*
    198 * Local methods
    199 */
    200
    201/** initializes one block */
    202static
    204 PROBLEM* problem /**< problem structure */
    205 )
    206{
    207 BLOCK* block;
    208
    209 assert(problem != NULL);
    210 assert(problem->scip != NULL);
    211
    212 block = &problem->blocks[problem->nblocks];
    213
    214 block->problem = problem;
    215 block->subscip = NULL;
    216 block->subvars = NULL;
    217 block->nsubvars = 0;
    218 block->number = problem->nblocks;
    219 block->slackspos = NULL;
    220 block->slacksneg = NULL;
    221 block->couplingcons = NULL;
    222 block->ncoupling = 0;
    223 block->size = 0;
    224
    225 ++problem->nblocks;
    226
    227 return SCIP_OKAY;
    228}
    229
    230/** frees component structure */
    231static
    233 BLOCK* block /**< block structure */
    234 )
    235{
    236 assert(block != NULL);
    237
    238 block->ncoupling = 0;
    239
    240 if( block->subvars != NULL )
    241 {
    242 SCIPfreeBufferArray(block->problem->scip, &(block->subvars));
    243 }
    244
    245 if( block->subscip != NULL )
    246 {
    247 SCIP_CALL( SCIPfree(&block->subscip) );
    248 }
    249
    250 return SCIP_OKAY;
    251}
    252
    253/** initializes subproblem structure */
    254static
    256 SCIP* scip, /**< SCIP data structure */
    257 PROBLEM** problem, /**< pointer to problem structure */
    258 int nblocks /**< number of blocks */
    259 )
    260{
    261 char name[SCIP_MAXSTRLEN];
    262
    263 assert(scip != NULL);
    264 assert(problem != NULL);
    265
    267 assert(*problem != NULL);
    268
    269 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPgetProbName(scip));
    270
    271 SCIP_CALL( SCIPduplicateMemoryArray(scip, &(*problem)->name, name, strlen(name) + 1) );
    272
    273 SCIPdebugMessage("initialized problem <%s>\n", (*problem)->name);
    274
    275 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*problem)->blocks, nblocks) );
    276
    277 (*problem)->scip = scip;
    278 (*problem)->nblocks = 0;
    279
    280 return SCIP_OKAY;
    281}
    282
    283/** frees subproblem structure */
    284static
    286 PROBLEM** problem, /**< pointer to problem to free */
    287 int nblocks /**< number of blocks in decomposition */
    288 )
    289{
    290 SCIP* scip;
    291 int c;
    292
    293 assert(problem != NULL);
    294 assert(*problem != NULL);
    295
    296 scip = (*problem)->scip;
    297 assert(scip != NULL);
    298
    299 /* free all blocks */
    300 for( c = nblocks - 1; c >= 0; --c )
    301 {
    302 SCIP_CALL( freeBlock(&(*problem)->blocks[c]) );
    303 }
    304 if( (*problem)->blocks != NULL )
    305 {
    306 SCIPfreeBlockMemoryArray(scip, &(*problem)->blocks, nblocks);
    307 }
    308
    309 /* free problem name */
    310 SCIPfreeMemoryArray(scip, &(*problem)->name);
    311
    312 /* free PROBLEM struct and set the pointer to NULL */
    313 SCIPfreeBlockMemory(scip, problem);
    314 *problem = NULL;
    315
    316 return SCIP_OKAY;
    317}
    318
    319/** creates a sub-SCIP for the given variables and constraints */
    320static
    322 SCIP* scip, /**< main SCIP data structure */
    323 SCIP** subscip /**< pointer to store created sub-SCIP */
    324 )
    325{
    326 SCIP_Real infvalue;
    327
    328 /* create a new SCIP instance */
    329 SCIP_CALL( SCIPcreate(subscip) );
    330
    332
    333 /* copy value for infinity */
    334 SCIP_CALL( SCIPgetRealParam(scip, "numerics/infinity", &infvalue) );
    335 SCIP_CALL( SCIPsetRealParam(*subscip, "numerics/infinity", infvalue) );
    336
    337 SCIP_CALL( SCIPcopyLimits(scip, *subscip) );
    338
    339 /* avoid recursive calls */
    340 SCIP_CALL( SCIPsetSubscipsOff(*subscip, TRUE) );
    341
    342 /* disable cutting plane separation */
    344
    345 /* disable expensive presolving */
    347
    348 /* disable expensive techniques */
    349 SCIP_CALL( SCIPsetIntParam(*subscip, "misc/usesymmetry", 0) );
    350
    351 /* do not abort subproblem on CTRL-C */
    352 SCIP_CALL( SCIPsetBoolParam(*subscip, "misc/catchctrlc", FALSE) );
    353
    354#ifdef SCIP_DEBUG
    355 /* for debugging, enable full output */
    356 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 5) );
    357 SCIP_CALL( SCIPsetIntParam(*subscip, "display/freq", 100000000) );
    358#else
    359 /* disable statistic timing inside sub SCIP and output to console */
    360 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 0) );
    361 SCIP_CALL( SCIPsetBoolParam(*subscip, "timing/statistictiming", FALSE) );
    362#endif
    363
    364 return SCIP_OKAY;
    365}
    366
    367/** copies the given constraints and the corresponding variables to the given sub-SCIP */
    368static
    370 SCIP* scip, /**< source SCIP */
    371 SCIP* subscip, /**< target SCIP */
    372 const char* name, /**< name for copied problem */
    373 SCIP_CONS** conss, /**< constraints to copy */
    374 SCIP_HASHMAP* varmap, /**< hashmap used for the copy process of variables */
    375 SCIP_HASHMAP* consmap, /**< hashmap used for the copy process of constraints */
    376 int nconss, /**< number of constraints to copy */
    377 SCIP_Bool useorigprob, /**< do we use the original problem? */
    378 SCIP_Bool* success /**< pointer to store whether copying was successful */
    379 )
    380{
    381 SCIP_CONS* newcons;
    382 int i;
    383
    384 assert(scip != NULL);
    385 assert(subscip != NULL);
    386 assert(conss != NULL);
    387 assert(consmap != NULL);
    388 assert(success != NULL);
    389
    390 *success = TRUE;
    391 newcons = NULL;
    392
    393 /* create problem in sub-SCIP */
    394 SCIP_CALL( SCIPcopyProb(scip, subscip, varmap, consmap, FALSE, name) );
    395
    396 /* copy constraints */
    397 for( i = 0; i < nconss; ++i )
    398 {
    399 assert(conss[i] != NULL);
    400
    401 /* do not check this if we use the original problem
    402 * Since constraints can be deleted etc. during presolving, these assertions would fail.
    403 */
    404 if( !useorigprob )
    405 {
    406 assert(!SCIPconsIsModifiable(conss[i]));
    407 assert(SCIPconsIsActive(conss[i]));
    408 assert(!SCIPconsIsDeleted(conss[i]));
    409 }
    410
    411 /* copy the constraint */
    412 SCIP_CALL( SCIPgetConsCopy(scip, subscip, conss[i], &newcons, SCIPconsGetHdlr(conss[i]), varmap, consmap, NULL,
    413 SCIPconsIsInitial(conss[i]), SCIPconsIsSeparated(conss[i]), SCIPconsIsEnforced(conss[i]),
    414 SCIPconsIsChecked(conss[i]), SCIPconsIsPropagated(conss[i]), FALSE, FALSE,
    415 SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]), FALSE, FALSE, success) );
    416
    417 /* abort if constraint was not successfully copied */
    418 if( !(*success) || newcons == NULL)
    419 return SCIP_OKAY;
    420
    421 SCIP_CALL( SCIPaddCons(subscip, newcons) );
    422 SCIP_CALL( SCIPreleaseCons(subscip, &newcons) );
    423 }
    424
    425 return SCIP_OKAY;
    426}
    427
    428/** creates the subscip for a given block */
    429static
    431 BLOCK* block, /**< block structure */
    432 SCIP_HASHMAP* varmap, /**< variable hashmap used to improve performance */
    433 SCIP_HASHMAP* consmap, /**< constraint hashmap used to improve performance */
    434 SCIP_CONS** conss, /**< constraints contained in this block */
    435 int nconss, /**< number of constraints contained in this block */
    436 SCIP_Bool useorigprob, /**< do we use the original problem? */
    437 SCIP_Bool* success /**< pointer to store whether the copying process was successful */
    438 )
    439{
    440 char name[SCIP_MAXSTRLEN];
    441 PROBLEM* problem;
    442 SCIP* scip;
    443 SCIP_VAR** subscipvars;
    444 int nsubscipvars;
    445 int i;
    446
    447 assert(block != NULL);
    448 assert(varmap != NULL);
    449 assert(consmap != NULL);
    450 assert(conss != NULL);
    451 assert(success != NULL);
    452
    453 problem = block->problem;
    454 assert(problem != NULL);
    455
    456 scip = problem->scip;
    457 assert(scip != NULL);
    458
    459 (*success) = TRUE;
    460
    461 SCIP_CALL( createSubscip(scip, &block->subscip) );
    462
    463 if( block->subscip != NULL )
    464 {
    465 /* get name of the original problem and add "comp_nr" */
    466 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", problem->name, block->number);
    467
    468 SCIP_CALL( copyToSubscip(scip, block->subscip, name, conss, varmap, consmap, nconss, useorigprob, success) );
    469
    470 if( !(*success) )
    471 {
    472 SCIP_CALL( SCIPfree(&block->subscip) );
    473 block->subscip = NULL;
    474 }
    475 else
    476 {
    477 /* save variables of subscip (without slack variables) */
    478 nsubscipvars = SCIPgetNOrigVars(block->subscip);
    479 subscipvars = SCIPgetOrigVars(block->subscip);
    480 SCIP_CALL( SCIPallocBufferArray(scip, &(block->subvars), nsubscipvars) );
    481 block->nsubvars = nsubscipvars;
    482 for( i = 0; i < nsubscipvars; i++ )
    483 block->subvars[i] = subscipvars[i];
    484
    485 /* calculate size of sub-SCIP with focus on the number of integer variables
    486 * we use this value to determine the nodelimit
    487 */
    490 }
    491 }
    492 else
    493 (*success) = FALSE;
    494
    495 SCIPdebugMsg(scip, "created subscip of block %d\n", block->number);
    496
    497 return SCIP_OKAY;
    498}
    499
    500/** creates problem structure and split it into blocks */
    501static
    503 SCIP* scip, /**< SCIP data structure */
    504 SCIP_CONS** sortedconss, /**< array of (checked) constraints sorted by blocks */
    505 int nconss, /**< number of constraints */
    506 int* consssize, /**< number of constraints per block (and border at index 0) */
    507 int nblocks, /**< number of blocks */
    508 PROBLEM** problem, /**< pointer to store problem structure */
    509 SCIP_Bool useorigprob, /**< do we use the original problem? */
    510 SCIP_Bool* success /**< pointer to store whether the process was successful */
    511 )
    512{
    513 BLOCK* block;
    514 SCIP_HASHMAP* varmap;
    515 SCIP_HASHMAP* consmap;
    516 SCIP_CONS** blockconss;
    517 int nhandledconss;
    518 int nblockconss;
    519 int b;
    520
    521 (*success) = TRUE;
    522
    523 /* init subproblem data structure */
    524 SCIP_CALL( initProblem(scip, problem, nblocks) );
    525 assert((*problem)->blocks != NULL);
    526
    527 /* hashmap mapping from original constraints to constraints in the sub-SCIPs (for performance reasons) */
    528 SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), nconss) );
    529
    530 for( b = 0; b < nblocks; b++ )
    531 {
    532 SCIP_CALL( initBlock(*problem) );
    533 }
    534
    535 /* loop over all blocks and create subscips */
    536 nhandledconss = 0;
    537 for( b = 0; b < nblocks; b++ )
    538 {
    539 block = &(*problem)->blocks[b];
    540
    542
    543 /* get block constraints */
    544 blockconss = &(sortedconss[nhandledconss]);
    545 nblockconss = consssize[b + 1];
    546
    547 /* build subscip for block */
    548 SCIP_CALL( blockCreateSubscip(block, varmap, consmap, blockconss, nblockconss, useorigprob, success) );
    549
    550 SCIPhashmapFree(&varmap);
    551 nhandledconss += nblockconss;
    552
    553 if( !(*success) )
    554 break;
    555 }
    556
    557 SCIPhashmapFree(&consmap);
    558
    559 if( !(*success) )
    560 {
    561 /* free subproblem data structure since not all blocks could be copied */
    562 SCIP_CALL( freeProblem(problem, nblocks) );
    563 }
    564
    565 return SCIP_OKAY;
    566}
    567
    568/** copies labels to newdecomp and assigns linking constraints if possible*/
    569static
    571 SCIP* scip, /**< SCIP data structure */
    572 SCIP_DECOMP* newdecomp, /**< decomposition with (partially) assigned linking constraints */
    573 SCIP_VAR** vars, /**< array of variables */
    574 SCIP_CONS** sortedconss, /**< sorted array of constraints */
    575 int* varlabels, /**< array of variable labels */
    576 int* conslabels, /**< sorted array of constraint labels */
    577 int nvars, /**< number of variables */
    578 int nconss, /**< number of constraints */
    579 int nlinkconss /**< number of linking constraints */
    580 )
    581{
    582 assert(scip != NULL);
    583 assert(vars != NULL);
    584 assert(sortedconss != NULL);
    585 assert(varlabels != NULL);
    586 assert(conslabels != NULL);
    587
    588 /* copy the labels */
    589 SCIP_CALL( SCIPdecompSetVarsLabels(newdecomp, vars, varlabels, nvars) );
    590 SCIP_CALL( SCIPdecompSetConsLabels(newdecomp, sortedconss, conslabels, nconss) );
    591
    592 SCIPdebugMsg(scip, "try to assign %d linking constraints\n", nlinkconss);
    593
    594 /* reassign linking constraints */
    595 SCIP_CALL( SCIPassignDecompLinkConss(scip, newdecomp, &sortedconss[0], nlinkconss, NULL) );
    596
    597 SCIP_CALL( SCIPcomputeDecompVarsLabels(scip, newdecomp, sortedconss, nconss) );
    598
    600
    601 SCIPdecompGetConsLabels(newdecomp, sortedconss, conslabels, nconss);
    602 SCIPdecompGetVarsLabels(newdecomp, vars, varlabels, nvars);
    603
    604 SCIPsortIntPtr(conslabels, (void**)sortedconss, nconss);
    605
    606 return SCIP_OKAY;
    607}
    608
    609/** computes feasible solution from last stored solution of the block*/
    610static
    612 SCIP* subscip, /**< SCIP data structure */
    613 BLOCK* block /**< block structure*/
    614 )
    615{
    616 SCIP_SOL** sols;
    617 SCIP_SOL* sol; /* solution of block that will be repaired */
    618 SCIP_SOL* newsol;
    619 SCIP_VAR** blockvars;
    620 SCIP_VAR** consvars;
    621 SCIP_Real* blockvals;
    622 int nsols;
    623 int nvars;
    624 int c;
    625 SCIP_Bool success;
    626
    627 assert(subscip != NULL);
    628 assert(block != NULL);
    629
    630 nsols = SCIPgetNSols(subscip);
    631
    632 /* no solution in solution candidate storage found */
    633 if( nsols == 0 )
    634 return SCIP_OKAY;
    635
    636 SCIP_CALL( SCIPallocBufferArray(subscip, &consvars, COUPLINGSIZE) );
    637
    638 sols = SCIPgetSols(subscip);
    639 sol = sols[nsols - 1];
    640
    641 /* copy the solution */
    642 nvars = SCIPgetNVars(subscip);
    643 blockvars = SCIPgetVars(subscip);
    644 SCIP_CALL( SCIPallocBufferArray(subscip, &blockvals, nvars) );
    645 SCIP_CALL( SCIPgetSolVals(subscip, sol, nvars, blockvars, blockvals) );
    646 SCIP_CALL( SCIPcreateOrigSol(subscip, &newsol, NULL) );
    647 SCIP_CALL( SCIPsetSolVals(subscip, newsol, nvars, blockvars, blockvals) );
    648
    649 /* correct each coupling constraint;
    650 * orig_var + slackpos - slackneg == side
    651 * adapt slack variables so that constraint is feasible */
    652 for( c = 0; c < block->ncoupling; c++ )
    653 {
    654 SCIP_Real solval; /* old solution values of variables; [0] original variable, [1] slackpos, [2] slackneg */
    655 SCIP_Real side; /* current right hand side */
    656 SCIP_Real diff;
    657
    658 SCIP_CALL( SCIPgetConsVars(subscip, block->couplingcons[c], consvars, COUPLINGSIZE, &success) );
    659 solval = SCIPgetSolVal(subscip, sol, consvars[0]);
    660
    661 side = SCIPgetRhsLinear(subscip, block->couplingcons[c]);
    662 assert(SCIPisEQ(subscip, SCIPgetRhsLinear(subscip, block->couplingcons[c]), SCIPgetLhsLinear(subscip, block->couplingcons[c])));
    663
    664 diff = side - solval;
    665
    666 /* slackpos is strict positiv */
    667 if( diff > 0 )
    668 {
    669 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], diff) );
    670 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], 0.0) );
    671 }
    672 /* slackneg is strict positiv */
    673 else if( diff < 0 )
    674 {
    675 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], -diff) );
    676 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], 0.0) );
    677 }
    678 /* no slack variable necessary */
    679 else
    680 {
    681 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slackspos[c], 0.0) );
    682 SCIP_CALL( SCIPsetSolVal(subscip, newsol, block->slacksneg[c], 0.0) );
    683 }
    684 }
    685
    686 SCIPdebugMsg(subscip, "Try adding solution with objective value %.2f\n", SCIPgetSolOrigObj(subscip, newsol));
    687 SCIP_CALL( SCIPaddSolFree(subscip, &newsol, &success) );
    688
    689 if( !success )
    690 SCIPdebugMsg(subscip, "Correcting solution failed\n"); /* maybe not better than old solutions */
    691 else
    692 {
    693 SCIPdebugMsg(subscip, "Correcting solution successful\n");
    694 }
    695
    696 SCIPfreeBufferArray(subscip, &blockvals);
    697 SCIPfreeBufferArray(subscip, &consvars);
    698
    699 return SCIP_OKAY;
    700}
    701
    702/** reoptimizes the heuristic solution with original objective function
    703 *
    704 * Since the main algorithm of padm ignores the objective function, this method can be called to obtain better solutions.
    705 * It copies the main scip, fixes the linking variables at the values of the already found solution
    706 * and solves the new problem with small limits.
    707 */
    708static
    710 SCIP* scip, /**< SCIP data structure */
    711 SCIP_HEUR* heur, /**< pointer to heuristic*/
    712 SCIP_SOL* sol, /**< heuristic solution */
    713 SCIP_VAR** vars, /**< pointer to variables */
    714 int nvars, /**< number of variables */
    715 SCIP_VAR** linkvars, /**< pointer to linking variables */
    716 int nlinkvars, /**< number of linking variables */
    717 SCIP_SOL** newsol, /**< pointer to store improved solution */
    718 SCIP_Bool* success /**< pointer to store whether reoptimization was successful */
    719 )
    720{
    721 SCIP* scipcopy;
    722 SCIP_SOL* startsol;
    723 SCIP_HASHMAP* varmap;
    724 SCIP_VAR** subvars;
    725 SCIP_STATUS status;
    726 SCIP_Real* linkvals;
    727 SCIP_Real time;
    728 int v;
    729
    730 assert(scip != NULL);
    731 assert(heur != NULL);
    732 assert(sol != NULL);
    733 assert(vars != NULL);
    734 assert(linkvars != NULL);
    735
    736 SCIP_CALL( SCIPallocBufferArray(scip, &linkvals, nlinkvars) );
    737 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    738
    739 SCIP_CALL( SCIPgetSolVals(scip, sol, nlinkvars, linkvars, linkvals) );
    740
    741 /* initializing the problem copy*/
    742 SCIP_CALL( SCIPcreate(&scipcopy) );
    743
    744 /* - create the variable mapping hash map
    745 * - create a problem copy of main SCIP
    746 */
    747 if( SCIPheurGetData(heur)->original )
    748 {
    750 SCIP_CALL( SCIPcopyOrigConsCompression(scip, scipcopy, varmap, NULL, "reopt_padm", linkvars, linkvals, nlinkvars,
    751 FALSE, FALSE, TRUE, success) );
    752 }
    753 else
    754 {
    755 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scipcopy), SCIPgetNVars(scip)) );
    756 SCIP_CALL( SCIPcopyConsCompression(scip, scipcopy, varmap, NULL, "reopt_padm", linkvars, linkvals, nlinkvars,
    757 TRUE, FALSE, FALSE, TRUE, success) );
    758 }
    759 for( v = 0; v < nvars; v++ )
    760 {
    761 subvars[v] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
    762 }
    763
    764 /* do not abort subproblem on CTRL-C */
    765 SCIP_CALL( SCIPsetBoolParam(scipcopy, "misc/catchctrlc", FALSE) );
    766
    767 /* forbid recursive call of heuristics and separators solving sub-SCIPs */
    768 SCIP_CALL( SCIPsetSubscipsOff(scipcopy, TRUE) );
    769
    770#ifdef SCIP_DEBUG
    771 /* for debugging, enable full output */
    772 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/verblevel", 5) );
    773 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/freq", 100000000) );
    774#else
    775 /* disable statistic timing inside sub SCIP and output to console */
    776 SCIP_CALL( SCIPsetIntParam(scipcopy, "display/verblevel", 0) );
    777 SCIP_CALL( SCIPsetBoolParam(scipcopy, "timing/statistictiming", FALSE) );
    778#endif
    779
    780 /* disable cutting plane separation */
    782
    783 /* disable expensive presolving but enable components presolver */
    785 SCIP_CALL( SCIPsetIntParam(scipcopy, "constraints/components/maxprerounds", 1) );
    786 SCIP_CALL( SCIPsetLongintParam(scipcopy, "constraints/components/nodelimit", 0LL) );
    787
    788 /* disable expensive techniques */
    789 SCIP_CALL( SCIPsetIntParam(scipcopy, "misc/usesymmetry", 0) );
    790
    791 /* speed up sub-SCIP by not checking dual LP feasibility */
    792 SCIP_CALL( SCIPsetBoolParam(scipcopy, "lp/checkdualfeas", FALSE) );
    793
    794 /* add heuristic solution as start solution */
    795 SCIP_CALL( SCIPtransformProb(scipcopy) );
    796 *success = FALSE;
    798 {
    799 SCIP_CALL( SCIPcreateSol(scipcopy, &startsol, heur) );
    800 for( v = 0; v < nvars; v++ )
    801 {
    802 SCIP_VAR* subvar;
    803 subvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
    804 if( subvar != NULL )
    805 {
    806 SCIP_CALL( SCIPsetSolVal(scipcopy, startsol, subvar, SCIPgetSolVal(scip, sol, vars[v])) );
    807 }
    808 }
    809
    810 SCIP_CALL( SCIPtrySolFree(scipcopy, &startsol, FALSE, FALSE, FALSE, FALSE, FALSE, success) );
    811 if( *success )
    812 SCIPdebugMsg(scip, "set start solution\n");
    813 else
    814 SCIPdebugMsg(scip, "start solution for reoptimizing is not feasible\n");
    815 }
    816
    817 /* set limits; do not use more time than the heuristic has already used */
    818 SCIP_CALL( SCIPcopyLimits(scip, scipcopy) );
    819 SCIP_CALL( SCIPsetLongintParam(scipcopy, "limits/nodes", 1LL) );
    820 SCIP_CALL( SCIPgetRealParam(scipcopy, "limits/time", &time) );
    821 if( SCIPheurGetTime(heur) < time - 1.0 )
    822 {
    823 SCIP_CALL( SCIPsetRealParam(scipcopy, "limits/time", SCIPheurGetTime(heur) + 1.0) );
    824 }
    825 if( *success )
    826 {
    827 SCIP_CALL( SCIPsetIntParam(scipcopy, "limits/bestsol", 2) ); /* first solution is start solution */
    828 }
    829 else
    830 {
    831 SCIP_CALL( SCIPsetIntParam(scipcopy, "limits/bestsol", 1) );
    832 }
    833
    834 /* reoptimize problem */
    835 SCIP_CALL_ABORT( SCIPsolve(scipcopy) );
    836 status = SCIPgetStatus(scipcopy);
    837
    838 /* copy solution to main scip */
    839 if( status == SCIP_STATUS_BESTSOLLIMIT || status == SCIP_STATUS_OPTIMAL )
    840 {
    841 SCIP_SOL* solcopy;
    842
    843 solcopy = SCIPgetBestSol(scipcopy);
    844 SCIP_CALL( SCIPtranslateSubSol(scip, scipcopy, solcopy, heur, subvars, newsol) );
    845
    846 SCIPdebugMsg(scip, "Objective value of reoptimized solution %.2f\n", SCIPgetSolOrigObj(scip, *newsol));
    847 *success = TRUE;
    848 }
    849 else
    850 {
    851 *success = FALSE;
    852 }
    853
    854 /* free data */
    855 SCIPhashmapFree(&varmap);
    856 SCIP_CALL( SCIPfree(&scipcopy) );
    857 SCIPfreeBufferArray(scip, &subvars);
    858 SCIPfreeBufferArray(scip, &linkvals);
    859
    860 return SCIP_OKAY;
    861}
    862
    863/** rescales the penalty parameters
    864 *
    865 * A sigmoid function is a function with an "S"-shaped graph, e.g. S(x) = x/(1+|x|).
    866 * In order to avoid numerical instabilities due to large penalty parameters we rescale them
    867 * using the sigmoid function
    868 * S(x) = (x - shift)/(flatness + |x - shift|) * (range/2) + offset.
    869 * The parameters are mapped into the more controllable interval [lowestslack, range + lowestslack].
    870 */
    871static
    873 PROBLEM* problem, /**< block structure */
    874 SET* linkvartoblocks, /**< linking variable to blocks set */
    875 SET* blocktolinkvars, /**< block to linking variable set */
    876 SCIP_HASHTABLE* htable, /**< hashtable containing blockinfo*/
    877 SCIP_Real maxpenalty /**< maximum penalty parameter */
    878 )
    879{
    880 SCIP_Real shift;
    881 SCIP_Real lowestslack;
    882 SCIP_Real range;
    883 SCIP_Real offset;
    884 SCIP_Real flatness;
    885 int b;
    886 int i;
    887 int k;
    888
    889 shift = maxpenalty / 2.0;
    890 lowestslack = 0.1;
    891 range = 10.0;
    892 offset = range / 2.0 + lowestslack;
    893 flatness = maxpenalty / 10.0;
    894
    895 for( b = 0; b < problem->nblocks; b++ )
    896 {
    897 for( i = 0; i < blocktolinkvars[b].size; i++ )
    898 {
    899 int linkvaridx;
    900 linkvaridx = blocktolinkvars[b].indexes[i];
    901
    902 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    903 {
    904 int b2;
    905 b2 = linkvartoblocks[linkvaridx].indexes[k];
    906
    907 if( b2 != b )
    908 {
    909 BLOCKINFO binfo;
    910 BLOCKINFO* binfoout;
    911 SCIP_Real oldcoeff;
    912
    913 binfo.block = b;
    914 binfo.otherblock = b2;
    915 binfo.linkvaridx = linkvaridx;
    916 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
    917 assert(binfoout != NULL);
    918
    919 /* scale coefficient of positive slack variable */
    920 oldcoeff = binfoout->slackposobjcoeff;
    921 binfoout->slackposobjcoeff = ((oldcoeff - shift) / (flatness + REALABS(oldcoeff - shift))) * range / 2.0 + offset;
    922
    923 /* scale coefficient of negative slack variable */
    924 oldcoeff = binfoout->slacknegobjcoeff;
    925 binfoout->slacknegobjcoeff = ((oldcoeff - shift) / (flatness + REALABS(oldcoeff - shift))) * range / 2.0 + offset;
    926 }
    927 }
    928 }
    929 }
    930 return SCIP_OKAY;
    931}
    932
    933/** returns the available time limit that is left */
    934static
    936 SCIP* scip, /**< SCIP data structure */
    937 SCIP_Real* time /**< pointer to store remaining time */
    938 )
    939{
    940 SCIP_Real timelim;
    941 SCIP_Real solvingtime;
    942
    943 assert(scip != NULL);
    944
    945 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelim) );
    946 solvingtime = SCIPgetSolvingTime(scip);
    947
    948 if( !SCIPisInfinity(scip, timelim) )
    949 *time = MAX(0.0, (timelim - solvingtime));
    950 else
    951 *time = SCIPinfinity(scip);
    952
    953 return SCIP_OKAY;
    954}
    955
    956/*
    957 * Callback methods of primal heuristic
    958 */
    959
    960/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    961static
    963{ /*lint --e{715}*/
    964 assert(scip != NULL);
    965 assert(heur != NULL);
    966
    968
    969 /* call inclusion method of primal heuristic */
    971
    972 return SCIP_OKAY;
    973}
    974
    975
    976/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    977static
    979{ /*lint --e{715}*/
    980 SCIP_HEURDATA* heurdata;
    981
    982 heurdata = SCIPheurGetData(heur);
    983 SCIPheurSetData(heur, NULL);
    984
    985 assert(heurdata != NULL);
    986
    987 SCIPfreeBlockMemory(scip, &heurdata);
    988
    989 return SCIP_OKAY;
    990}
    991
    992
    993/** execution method of primal heuristic */
    994static SCIP_DECL_HEUREXEC(heurExecPADM)
    995{ /*lint --e{715}*/
    996 char name[SCIP_MAXSTRLEN];
    997 char info[SCIP_MAXSTRLEN];
    998 SCIP_HEURDATA* heurdata;
    999 PROBLEM* problem;
    1000 SCIP_DECOMP** alldecomps;
    1001 SCIP_DECOMP* decomp;
    1002 SCIP_DECOMP* assigneddecomp;
    1003 SCIP_VAR** vars;
    1004 SCIP_VAR** linkvars;
    1005 SCIP_VAR** tmpcouplingvars;
    1006 SCIP_CONS** conss;
    1007 SCIP_CONS** sortedconss;
    1008 SET* linkvartoblocks;
    1009 SET* blocktolinkvars;
    1010 BLOCKINFO* blockinfolist;
    1011 SCIP_HASHTABLE* htable;
    1012 int* varlabels;
    1013 int* conslabels;
    1014 int* consssize;
    1015 int* alllinkvartoblocks; /* for efficient memory allocation */
    1016 SCIP_Bool* varonlyobj;
    1017 SCIP_Real* tmpcouplingcoef;
    1018 SCIP_Real gap;
    1019 SCIP_Real maxpenalty;
    1020 SCIP_Real slackthreshold;
    1021 SCIP_Real memory; /* in MB */
    1022 SCIP_Real timeleft;
    1023 SCIP_STATUS status;
    1024 SCIP_Bool solutionsdiffer;
    1025 SCIP_Bool solved;
    1026 SCIP_Bool doscaling;
    1027 SCIP_Bool istimeleft;
    1028 SCIP_Bool success;
    1029 SCIP_Bool avoidmemout;
    1030 SCIP_Bool disablemeasures;
    1031 int maxgraphedge;
    1032 int ndecomps;
    1033 int nconss;
    1034 int nvars;
    1035 int nblocks;
    1036 int numlinkvars;
    1037 int nentries;
    1038 int aiter;
    1039 int piter;
    1040 int increasedslacks;
    1041 int blockinfolistfill;
    1042 SCIP_Longint nodesleft;
    1043 int i;
    1044 int b;
    1045 int k;
    1046 int j;
    1047
    1048 assert(scip != NULL);
    1049 assert(heur != NULL);
    1050 assert(result != NULL);
    1051
    1052 heurdata = SCIPheurGetData(heur);
    1053 assert(heurdata != NULL);
    1054
    1055 *result = SCIP_DIDNOTRUN;
    1056
    1057 problem = NULL;
    1058 assigneddecomp = NULL;
    1059 sortedconss = NULL;
    1060 varlabels = NULL;
    1061 conslabels = NULL;
    1062 consssize = NULL;
    1063 alllinkvartoblocks = NULL;
    1064 linkvars = NULL;
    1065 linkvartoblocks = NULL;
    1066 blocktolinkvars = NULL;
    1067 tmpcouplingvars = NULL;
    1068 tmpcouplingcoef = NULL;
    1069 varonlyobj = NULL;
    1070 blockinfolist = NULL;
    1071 htable = NULL;
    1072
    1073 nodesleft = heurdata->maxnodes;
    1074 gap = heurdata->gap;
    1075
    1076 if( (heurtiming & SCIP_HEURTIMING_BEFORENODE) && heurdata->timing !=1 )
    1077 {
    1078 SCIPdebugMsg(scip, "Initialize padm heuristic before node\n");
    1079 }
    1080 else if( (heurtiming & SCIP_HEURTIMING_AFTERNODE) && heurdata->timing >=1 )
    1081 {
    1082 SCIPdebugMsg(scip, "Initialize padm heuristic after node\n");
    1083 }
    1084 else
    1085 {
    1086 return SCIP_OKAY;
    1087 }
    1088
    1089#ifdef PADM_WRITE_PROBLEMS
    1090 SCIP_CALL( SCIPwriteOrigProblem(scip, "orig_problem", NULL, FALSE) );
    1091 SCIP_CALL( SCIPwriteTransProblem(scip, "trans_problem", NULL, FALSE) );
    1092#endif
    1093
    1094 /* take original problem (This is only for testing and not recommended!) */
    1095 if( heurdata->original )
    1096 {
    1097 /* multiaggregation of variables has to be switched off */
    1098 if( !SCIPdoNotMultaggr(scip) )
    1099 {
    1100 SCIPwarningMessage(scip, "Heuristic %s does not support multiaggregation when the original problem is used.\nPlease turn multiaggregation off to use this feature.\n", HEUR_NAME);
    1101 return SCIP_OKAY;
    1102 }
    1103
    1104 SCIPgetDecomps(scip, &alldecomps, &ndecomps, TRUE);
    1105 if( ndecomps == 0)
    1106 return SCIP_OKAY;
    1107
    1108 /* it takes the first decomposition */
    1109 decomp = alldecomps[0];
    1110 SCIPdebugMsg(scip, "First original decomposition is selected\n");
    1111 assert(decomp != NULL);
    1112
    1113 nconss = SCIPgetNOrigConss(scip);
    1114 conss = SCIPgetOrigConss(scip);
    1115 nvars = SCIPgetNOrigVars(scip);
    1116 vars = SCIPgetOrigVars(scip);
    1117 }
    1118 /* take transformed problem */
    1119 else
    1120 {
    1121 SCIPgetDecomps(scip, &alldecomps, &ndecomps, FALSE);
    1122 if( ndecomps == 0)
    1123 return SCIP_OKAY;
    1124
    1125 /* it takes the first decomposition */
    1126 decomp = alldecomps[0];
    1127 SCIPdebugMsg(scip, "First transformed decomposition is selected\n");
    1128 assert(decomp != NULL);
    1129
    1130 nconss = SCIPgetNConss(scip);
    1131 conss = SCIPgetConss(scip);
    1132 nvars = SCIPgetNVars(scip);
    1133 vars = SCIPgetVars(scip);
    1134 }
    1135
    1136 nblocks = SCIPdecompGetNBlocks(decomp);
    1137
    1138 /* if problem has no constraints, no variables or less than two blocks, return */
    1139 if( nconss == 0 || nvars == 0 || nblocks <= 1 )
    1140 {
    1141 SCIPdebugMsg(scip, "problem has no constraints, no variables or less than two blocks\n");
    1142 goto TERMINATE;
    1143 }
    1144
    1145 /* estimate required memory for all blocks and terminate if not enough memory is available */
    1146 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memory) );
    1147 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    1148 if( avoidmemout && (((SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip))/1048576.0) * nblocks >= memory) )
    1149 {
    1150 SCIPdebugMsg(scip, "The estimated memory usage for %d blocks is too large.\n", nblocks);
    1151 goto TERMINATE;
    1152 }
    1153
    1154 /* we do not need the block decomposition graph and expensive measures of the decomposition statistics */
    1155 SCIP_CALL( SCIPgetIntParam(scip, "decomposition/maxgraphedge", &maxgraphedge) );
    1156 if( !SCIPisParamFixed(scip, "decomposition/maxgraphedge") )
    1157 {
    1158 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", 0) );
    1159 }
    1160 SCIP_CALL( SCIPgetBoolParam(scip, "decomposition/disablemeasures", &disablemeasures) );
    1161 if( !SCIPisParamFixed(scip, "decomposition/disablemeasures") )
    1162 {
    1163 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", TRUE) );
    1164 }
    1165
    1166 /* don't change problem by sorting constraints */
    1167 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
    1168
    1169 SCIP_CALL( SCIPallocBufferArray(scip, &varlabels, nvars) );
    1170 SCIP_CALL( SCIPallocBufferArray(scip, &conslabels, nconss) );
    1171 SCIP_CALL( SCIPallocBufferArray(scip, &consssize, nblocks + 1) );
    1172
    1173 SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
    1174 SCIPdecompGetVarsLabels(decomp, vars, varlabels, nvars);
    1175
    1176 /* sort constraints by blocks */
    1177 SCIPsortIntPtr(conslabels, (void**)sortedconss, nconss);
    1178
    1179 /* try to assign linking constraints */
    1180 if( heurdata->assignlinking && conslabels[0] == SCIP_DECOMP_LINKCONS )
    1181 {
    1182 /* create new decomposition; don't change the decompositions in the decompstore */
    1183 SCIP_CALL( SCIPcreateDecomp(scip, &assigneddecomp, nblocks, heurdata->original, SCIPdecompUseBendersLabels(decomp)) );
    1184
    1185 SCIP_CALL( assignLinking(scip, assigneddecomp, vars, sortedconss, varlabels, conslabels, nvars, nconss, SCIPdecompGetNBorderConss(decomp)) );
    1186 assert(SCIPdecompGetNBlocks(decomp) >= SCIPdecompGetNBlocks(assigneddecomp));
    1187 decomp = assigneddecomp;
    1188
    1189 /* number of blocks can get smaller (since assigning constraints can lead to empty blocks) */
    1190 nblocks = SCIPdecompGetNBlocks(decomp);
    1191 }
    1192 else
    1193 {
    1194 /* The decomposition statistics were computed during transformation of the decomposition store.
    1195 * Since propagators can have changed the number of constraints/variables,
    1196 * the statistics are no longer up-to-date and have to be recomputed.
    1197 */
    1199 nblocks = SCIPdecompGetNBlocks(decomp);
    1200 }
    1201
    1202 /* reset parameters */
    1203 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", maxgraphedge) );
    1204 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", disablemeasures) );
    1205
    1206 /* @note the terms 'linking' and 'border' (constraints/variables) are used interchangeably */
    1207
    1208 if( SCIPdecompGetNBorderConss(decomp) != 0 )
    1209 {
    1210 SCIPdebugMsg(scip, "No support for linking contraints\n");
    1211 goto TERMINATE;
    1212 }
    1213
    1214 /* get number of linking variables */
    1215 numlinkvars = SCIPdecompGetNBorderVars(decomp);
    1216 SCIPdebugMsg(scip, "%d linking variables\n", numlinkvars);
    1217
    1218 if( numlinkvars == 0 )
    1219 {
    1220 SCIPdebugMsg(scip, "No linking variables\n");
    1221 goto TERMINATE;
    1222 }
    1223
    1224 *result = SCIP_DIDNOTFIND;
    1225
    1226 /* get for every block the number of constraints (first entry belongs to border) */
    1227 SCIP_CALL( SCIPdecompGetConssSize(decomp, consssize, nblocks + 1) );
    1228
    1229 /* create blockproblems */
    1230 SCIP_CALL( createAndSplitProblem(scip, sortedconss, nconss, consssize, nblocks, &problem, heurdata->original, &success) );
    1231
    1232 if( !success )
    1233 {
    1234 SCIPdebugMsg(scip, "Some subscips could not be created successfully.\n");
    1235 goto TERMINATE;
    1236 }
    1237
    1238 SCIP_CALL( SCIPallocBufferArray(scip, &linkvartoblocks, numlinkvars) );
    1239 SCIP_CALL( SCIPallocBufferArray(scip, &blocktolinkvars, problem->nblocks) );
    1240
    1241 /* set pointer to NULL for safe memory release */
    1242 for( i = 0; i < numlinkvars; i++ )
    1243 linkvartoblocks[i].indexes = NULL;
    1244 for( i = 0; i < problem->nblocks; i++ )
    1245 blocktolinkvars[i].indexes = NULL;
    1246
    1247 /* extract linking variables and init linking variable to blocks set */
    1248 SCIP_CALL( SCIPallocBufferArray(scip, &alllinkvartoblocks, problem->nblocks * numlinkvars) );
    1249 SCIP_CALL( SCIPallocBufferArray(scip, &linkvars, numlinkvars) );
    1250
    1251 b = 0;
    1252 for( i = 0; i < nvars; i++ )
    1253 {
    1254 if( varlabels[i] == SCIP_DECOMP_LINKVAR )
    1255 {
    1256 linkvars[b] = vars[i];
    1257 linkvartoblocks[b].indexes = &alllinkvartoblocks[b * problem->nblocks];
    1258 linkvartoblocks[b].size = 0;
    1259 b++;
    1260 }
    1261 }
    1262
    1263 /* fill linking variable to blocks set */
    1264 for( i = 0; i < numlinkvars; i++ )
    1265 {
    1266 SCIP_VAR* var;
    1267 const char* vname;
    1268
    1269 assert(linkvartoblocks[i].indexes != NULL);
    1270
    1271 vname = SCIPvarGetName(linkvars[i]);
    1272 k = 0;
    1273 for( b = 0; b < problem->nblocks; b++ )
    1274 {
    1275 var = SCIPfindVar((problem->blocks[b]).subscip, vname);
    1276 if( var != NULL )
    1277 {
    1278 linkvartoblocks[i].indexes[k] = b;
    1279 linkvartoblocks[i].size = k + 1;
    1280 k++;
    1281 }
    1282 }
    1283 }
    1284
    1285 /* check whether there is enough time left */
    1286 SCIP_CALL( getTimeLeft(scip, &timeleft) );
    1287 if( timeleft <= 0 )
    1288 {
    1289 SCIPdebugMsg(scip, "no time left\n");
    1290 goto TERMINATE;
    1291 }
    1292
    1293 /* init varonlyobj; true if variable is only part of the objective function */
    1294 SCIP_CALL( SCIPallocBufferArray(scip, &varonlyobj, numlinkvars) );
    1295 for( i = 0; i < numlinkvars; ++i)
    1296 varonlyobj[i] = TRUE;
    1297
    1298 /* init and fill block to linking variables set */
    1299 for( b = 0; b < problem->nblocks; b++ )
    1300 {
    1301 SCIP_CALL( SCIPallocBufferArray(scip, &(blocktolinkvars[b].indexes), numlinkvars) );
    1302 blocktolinkvars[b].size = 0;
    1303
    1304 k = 0;
    1305 for( i = 0; i < numlinkvars; i++ )
    1306 {
    1307 SCIP_VAR* var;
    1308 const char* vname;
    1309
    1310 vname = SCIPvarGetName(linkvars[i]);
    1311 var = SCIPfindVar((problem->blocks[b]).subscip, vname);
    1312 if( var != NULL )
    1313 {
    1314 varonlyobj[i] = FALSE;
    1315 blocktolinkvars[b].indexes[k] = i;
    1316 blocktolinkvars[b].size = k + 1;
    1317 k++;
    1318 }
    1319 }
    1320 }
    1321
    1322 /* init arrays for slack variables and coupling constraints */
    1323 for( b = 0; b < problem->nblocks; b++ )
    1324 {
    1325 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).slackspos), blocktolinkvars[b].size * (nblocks - 1)) );
    1326 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).slacksneg), blocktolinkvars[b].size * (nblocks - 1)) );
    1327 SCIP_CALL( SCIPallocBufferArray(scip, &((problem->blocks[b]).couplingcons), blocktolinkvars[b].size * (nblocks - 1)) );
    1328 }
    1329
    1330 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcouplingvars, COUPLINGSIZE) );
    1331 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcouplingcoef, COUPLINGSIZE) );
    1332 tmpcouplingcoef[0] = 1.0;
    1333 tmpcouplingcoef[1] = 1.0;
    1334 tmpcouplingcoef[2] = -1.0;
    1335
    1336 /* count hashtable entries */
    1337 nentries = 0;
    1338 for( b = 0; b < problem->nblocks; b++ )
    1339 {
    1340 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1341 {
    1342 int linkvaridx = blocktolinkvars[b].indexes[i];
    1343 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1344 {
    1345 if( linkvartoblocks[linkvaridx].indexes[k] != b )
    1346 nentries++;
    1347 }
    1348 }
    1349 }
    1350
    1351 SCIP_CALL( SCIPallocBufferArray(scip, &blockinfolist, nentries) );
    1352 SCIP_CALL( SCIPhashtableCreate(&htable, SCIPblkmem(scip), 1, SCIPhashGetKeyStandard, indexesEqual, indexesHashval, (void*) scip) );
    1353 blockinfolistfill = 0;
    1354
    1355 /* extend submips */
    1356 SCIPdebugMsg(scip, "Extending %d block models\n", problem->nblocks);
    1357 for( b = 0; b < problem->nblocks; b++ )
    1358 {
    1359 SCIP_VAR** blockvars;
    1360 int nblockvars;
    1361
    1362 blockvars = SCIPgetVars((problem->blocks[b]).subscip);
    1363 nblockvars = SCIPgetNVars((problem->blocks[b]).subscip);
    1364
    1365 /* set objective function of each block to zero */
    1366 for( i = 0; i < nblockvars; i++ )
    1367 {
    1368 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, blockvars[i], 0.0) );
    1369 }
    1370
    1371 /* add two slack variables for each linking variable in block */
    1372 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1373 {
    1374 int linkvaridx;
    1375 linkvaridx = blocktolinkvars[b].indexes[i];
    1376
    1377 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1378 {
    1379 int b2;
    1380 b2 = linkvartoblocks[linkvaridx].indexes[k];
    1381
    1382 /* handle different blocks with common linking variable */
    1383 if( b2 != b )
    1384 {
    1385 BLOCKINFO* binfo;
    1386 binfo = &blockinfolist[blockinfolistfill];
    1387 blockinfolistfill++;
    1388 binfo->block = b;
    1389 binfo->otherblock = b2;
    1390 binfo->linkvaridx = linkvaridx;
    1391 binfo->linkvar = SCIPfindVar((problem->blocks[b]).subscip, SCIPvarGetName(linkvars[linkvaridx]));
    1392 j = (problem->blocks[b]).ncoupling;
    1393
    1394 /* create positive slack variable */
    1395 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_slackpos_block_%d", SCIPvarGetName(linkvars[linkvaridx]), b2);
    1396 (problem->blocks[b]).slackspos[j] = NULL;
    1397 SCIP_CALL( SCIPcreateVarBasic((problem->blocks[b]).subscip,
    1398 &((problem->blocks[b]).slackspos[j]), name,
    1400 SCIP_CALL( SCIPaddVar((problem->blocks[b]).subscip, (problem->blocks[b]).slackspos[j]) );
    1401 assert((problem->blocks[b]).slackspos[j] != NULL);
    1402 binfo->slackposobjcoeff = 1.0;
    1403 binfo->slackposvar = (problem->blocks[b]).slackspos[j];
    1404
    1405 /* create negative slack variable */
    1406 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_slackneg_block_%d", SCIPvarGetName(linkvars[linkvaridx]), b2);
    1407 (problem->blocks[b]).slacksneg[j] = NULL;
    1408 SCIP_CALL( SCIPcreateVarBasic((problem->blocks[b]).subscip,
    1409 &((problem->blocks[b]).slacksneg[j]), name,
    1411 SCIP_CALL( SCIPaddVar((problem->blocks[b]).subscip, (problem->blocks[b]).slacksneg[j]) );
    1412 assert((problem->blocks[b]).slacksneg[j] != NULL);
    1413 binfo->slacknegobjcoeff = 1.0;
    1414 binfo->slacknegvar = (problem->blocks[b]).slacksneg[j];
    1415
    1416 /* fill variables for linking constraint */
    1417 tmpcouplingvars[0] = binfo->linkvar;
    1418 tmpcouplingvars[1] = binfo->slackposvar;
    1419 tmpcouplingvars[2] = binfo->slacknegvar;
    1420
    1421 /* create linking constraint */
    1422 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_coupling_block_%d",
    1423 SCIPvarGetName(linkvars[linkvaridx]), b2);
    1424 (problem->blocks[b]).couplingcons[j] = NULL;
    1425
    1426 /* create linking constraint with initial side equal to zero (or lower bound of linking variable) */
    1427 if( heurtiming & SCIP_HEURTIMING_BEFORENODE )
    1428 {
    1429 SCIP_Real initval;
    1430 SCIP_Real lb;
    1431
    1432 lb = SCIPvarGetLbOriginal(binfo->linkvar);
    1433 initval = MAX(lb, 0.0);
    1434
    1435 SCIP_CALL( SCIPcreateConsBasicLinear((problem->blocks[b]).subscip, &((problem->blocks[b]).couplingcons[j]),
    1436 name, COUPLINGSIZE, tmpcouplingvars, tmpcouplingcoef, initval, initval) );
    1437
    1438 /* set initial value of linking variable */
    1439 binfo->linkvarval = initval;
    1440 }
    1441
    1442 /* create linking constraint with initial side equal to LP solution (rounded if variable is integer) */
    1443 if( heurtiming & SCIP_HEURTIMING_AFTERNODE )
    1444 {
    1445 SCIP_Real initval;
    1446
    1447 initval = SCIPvarGetLPSol(linkvars[linkvaridx]);
    1448 if( SCIPvarIsIntegral(binfo->linkvar) )
    1449 initval = SCIPround(scip, initval);
    1450
    1451 SCIP_CALL( SCIPcreateConsBasicLinear((problem->blocks[b]).subscip, &((problem->blocks[b]).couplingcons[j]),
    1452 name, COUPLINGSIZE, tmpcouplingvars, tmpcouplingcoef, initval, initval) );
    1453
    1454 /* set initial value of linking variable */
    1455 binfo->linkvarval = initval;
    1456 }
    1457
    1458 SCIP_CALL( SCIPaddCons((problem->blocks[b]).subscip, (problem->blocks[b]).couplingcons[j]) );
    1459 assert((problem->blocks[b]).couplingcons[j] != NULL);
    1460 binfo->couplingCons = (problem->blocks[b]).couplingcons[j];
    1461
    1462 (problem->blocks[b]).ncoupling++;
    1463
    1464 /* feed hashtable */
    1465 SCIP_CALL( SCIPhashtableSafeInsert(htable, (void*) binfo) );
    1466 }
    1467 }
    1468 }
    1469 }
    1470 assert(nentries == SCIPhashtableGetNElements(htable));
    1471
    1472#ifdef PADM_WRITE_PROBLEMS
    1473 /* write extended submips */
    1474 for( b = 0; b < problem->nblocks; b++ )
    1475 {
    1476 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "extended_block_%d.lp", b);
    1477 SCIP_CALL( SCIPwriteOrigProblem((problem->blocks[b]).subscip, name, NULL, FALSE) );
    1478 }
    1479#endif
    1480
    1481 /* determine threshold for penalty coefficients via maximum norm */
    1482 slackthreshold = SCIP_REAL_MIN;
    1483 for( i = 0; i < nvars; i++ )
    1484 {
    1485 SCIP_Real obj;
    1486
    1487 obj = REALABS(SCIPvarGetObj(vars[i]));
    1488 if( obj > slackthreshold )
    1489 slackthreshold = obj;
    1490 }
    1491
    1492 /* ------------------------------------------------------------------------------------------------- */
    1493
    1494 /* check whether there is enough time left */
    1495 SCIP_CALL( getTimeLeft(scip, &timeleft) );
    1496 if( timeleft <= 0 )
    1497 {
    1498 SCIPdebugMsg(scip, "no time left\n");
    1499 goto TERMINATE;
    1500 }
    1501
    1502 SCIPdebugMsg(scip, "Starting iterations\n");
    1503 SCIPdebugMsg(scip, "PIt\tADMIt\tSlacks\tInfo\n");
    1504
    1505 piter = 0;
    1506 increasedslacks = 0;
    1507 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "-");
    1508 solved = FALSE;
    1509 istimeleft = TRUE;
    1510
    1511 /* Penalty loop */
    1512 while( !solved && piter < heurdata->penaltyiterations && istimeleft )
    1513 {
    1514 piter++;
    1515 solutionsdiffer = TRUE;
    1516 aiter = 0;
    1517
    1518 /* Alternating direction method loop */
    1519 while( solutionsdiffer && aiter < heurdata->admiterations && istimeleft )
    1520 {
    1521 aiter++;
    1522 solutionsdiffer = FALSE;
    1523 SCIPdebugMsg(scip, "%d\t%d\t%d\t%s\n", piter, aiter, increasedslacks, info);
    1524
    1525 /* Loop through the blocks and solve each sub-SCIP, potentially multiple times */
    1526 for( b = 0; b < problem->nblocks; b++ )
    1527 {
    1528 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1529 {
    1530 int linkvaridx;
    1531 linkvaridx = blocktolinkvars[b].indexes[i];
    1532
    1533 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1534 {
    1535 int b2;
    1536 b2 = linkvartoblocks[linkvaridx].indexes[k];
    1537
    1538 if( b2 != b )
    1539 {
    1540 BLOCKINFO binfo;
    1541 BLOCKINFO* binfoout;
    1542 BLOCKINFO binfo2;
    1543 BLOCKINFO* binfo2out;
    1544
    1545 SCIP_CONS* couplingcons;
    1546 SCIP_Real newrhs;
    1547
    1548 binfo.block = b;
    1549 binfo.otherblock = b2;
    1550 binfo.linkvaridx = linkvaridx;
    1551
    1552 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void *)&binfo);
    1553 assert(binfoout != NULL);
    1554 couplingcons = binfoout->couplingCons;
    1555
    1556 /* interchange blocks b and b2 for getting new right hand side */
    1557 binfo2.block = b2;
    1558 binfo2.otherblock = b;
    1559 binfo2.linkvaridx = linkvaridx;
    1560 binfo2out = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo2);
    1561 assert(binfo2out != NULL);
    1562 newrhs = binfo2out->linkvarval;
    1563
    1564 /* change side of coupling constraint equation with linking variable value of the other block */
    1565 SCIP_CALL( SCIPchgLhsLinear((problem->blocks[b]).subscip, couplingcons, newrhs) );
    1566 SCIP_CALL( SCIPchgRhsLinear((problem->blocks[b]).subscip, couplingcons, newrhs) );
    1567
    1568 /* change penalty coefficients of slack variables */
    1569 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slackposvar, binfoout->slackposobjcoeff) );
    1570 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slacknegvar, binfoout->slacknegobjcoeff) );
    1571 }
    1572 }
    1573 }
    1574
    1575 /* increase slack penalty coeffs until each subproblem can be solved to optimality */
    1576 do
    1577 {
    1579 int iteration;
    1580
    1581#ifdef PADM_WRITE_PROBLEMS
    1582 SCIPdebugMsg(scip, "write subscip of block %d in piter=%d and aiter=%d\n", b, piter, aiter);
    1583 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "blockproblem_%d_%d_%d.lp", b, piter, aiter);
    1584 SCIP_CALL( SCIPwriteOrigProblem((problem->blocks[b]).subscip, name, NULL, FALSE) );
    1585#endif
    1586
    1587 SCIP_CALL( SCIPsetRealParam((problem->blocks[b]).subscip, "limits/gap", gap) );
    1588
    1589 /* reuse old solution if available */
    1590 SCIP_CALL( reuseSolution((problem->blocks[b]).subscip, &problem->blocks[b]) );
    1591
    1592 /* update time and memory limit of subproblem */
    1593 SCIP_CALL( SCIPcopyLimits(scip, (problem->blocks[b]).subscip) );
    1594
    1595 /* stop if there are not enough nodes left */
    1596 if( nodesleft < heurdata->minnodes )
    1597 {
    1598 SCIPdebugMsg(scip, "Node limit reached.\n");
    1599 goto TERMINATE;
    1600 }
    1601
    1602 /* update node limit of subproblem
    1603 * in the first iterations we have a smaller node limit
    1604 */
    1605 iteration = ((piter - 1) * heurdata->admiterations) + aiter;
    1606 nnodes = (SCIP_Longint)SCIPceil(scip, (problem->blocks[b]).size * nodesleft * ( 1 - pow(heurdata->nodefac, (double)iteration) ));
    1607 nnodes = MAX( heurdata->minnodes, nnodes );
    1608 SCIP_CALL( SCIPsetLongintParam((problem->blocks[b]).subscip, "limits/nodes", nnodes) );
    1609
    1610 /* solve block
    1611 *
    1612 * errors in solving the subproblem should not kill the overall solving process;
    1613 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    1614 */
    1615 SCIP_CALL_ABORT( SCIPsolve((problem->blocks[b]).subscip) );
    1616 status = SCIPgetStatus((problem->blocks[b]).subscip);
    1617
    1618 /* subtract used nodes from the total nodelimit */
    1619 nodesleft -= (SCIP_Longint)SCIPceil(scip, SCIPgetNNodes((problem->blocks[b]).subscip) * (problem->blocks[b]).size);
    1620
    1621 /* check solution if one of the four cases occurs
    1622 * - solution is optimal
    1623 * - solution reached gaplimit
    1624 * - node limit reached with at least one feasible solution
    1625 * - time limit is reached but best solution needs no slack variables (no dual solution available)
    1626 */
    1627 if( status == SCIP_STATUS_OPTIMAL || status == SCIP_STATUS_GAPLIMIT ||
    1628 (status == SCIP_STATUS_NODELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0) ||
    1629 (status == SCIP_STATUS_TIMELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0 &&
    1630 SCIPisEQ(scip, SCIPgetSolOrigObj((problem->blocks[b]).subscip, SCIPgetBestSol((problem->blocks[b]).subscip)), 0.0) ) )
    1631 {
    1632 SCIPdebugMsg(scip, "Block is optimal or reached gaplimit or nodelimit.\n");
    1633
    1634 if( status == SCIP_STATUS_TIMELIMIT )
    1635 {
    1636 SCIPdebugMsg(scip, "Block reached time limit with at least one feasible solution.\n");
    1637 istimeleft = FALSE;
    1638 }
    1639
    1640 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1641 {
    1642 int linkvaridx;
    1643 linkvaridx = blocktolinkvars[b].indexes[i];
    1644
    1645 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1646 {
    1647 int b2;
    1648 b2 = linkvartoblocks[linkvaridx].indexes[k];
    1649
    1650 if( b2 != b )
    1651 {
    1652 SCIP_SOL* sol;
    1653 BLOCKINFO binfo;
    1654 BLOCKINFO* binfoout;
    1655 SCIP_VAR* var;
    1656 SCIP_Real val;
    1657
    1658 binfo.block = b;
    1659 binfo.otherblock = b2;
    1660 binfo.linkvaridx = linkvaridx;
    1661 binfoout = (BLOCKINFO *)SCIPhashtableRetrieve(htable, (void *)&binfo);
    1662 assert(binfoout != NULL);
    1663
    1664 sol = SCIPgetBestSol((problem->blocks[b]).subscip);
    1665 assert(sol != NULL);
    1666 var = binfoout->linkvar;
    1667 val = SCIPgetSolVal((problem->blocks[b]).subscip, sol, var);
    1668
    1669 if( !EPSEQ(binfoout->linkvarval, val, SCIP_DEFAULT_EPSILON) )
    1670 solutionsdiffer = TRUE;
    1671
    1672 binfoout->linkvarval = val;
    1673 }
    1674 }
    1675 }
    1676 }
    1677 else if( status == SCIP_STATUS_UNBOUNDED )
    1678 {
    1679 SCIPdebugMsg(scip, "Block is unbounded.\n");
    1680 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1681 {
    1682 int linkvaridx;
    1683 linkvaridx = blocktolinkvars[b].indexes[i];
    1684
    1685 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1686 {
    1687 int b2;
    1688 b2 = linkvartoblocks[linkvaridx].indexes[k];
    1689
    1690 if( b2 != b )
    1691 {
    1692 BLOCKINFO binfo;
    1693 BLOCKINFO* binfoout;
    1694
    1695 binfo.block = b;
    1696 binfo.otherblock = b2;
    1697 binfo.linkvaridx = linkvaridx;
    1698 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
    1699 assert(binfoout != NULL);
    1700
    1701 /* increase penalty coefficients to obtain a bounded subproblem */
    1702 binfoout->slackposobjcoeff *= 10.0;
    1703 binfoout->slacknegobjcoeff *= 10.0;
    1704 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slackposvar, binfoout->slackposobjcoeff) );
    1705 SCIP_CALL( SCIPchgVarObj((problem->blocks[b]).subscip, binfoout->slacknegvar, binfoout->slacknegobjcoeff) );
    1706 }
    1707 }
    1708 }
    1709 }
    1710 else if( status == SCIP_STATUS_TIMELIMIT )
    1711 {
    1712 SCIPdebugMsg(scip, "Block reached time limit. No optimal solution available.\n");
    1713 goto TERMINATE;
    1714 }
    1715 else
    1716 {
    1717 SCIPdebugMsg(scip, "Block solving status %d not supported\n", status);
    1718 goto TERMINATE;
    1719 }
    1720
    1721 /* free solving data in order to change problem */
    1722 SCIP_CALL( SCIPfreeTransform((problem->blocks[b]).subscip) );
    1723 }
    1724 while( status != SCIP_STATUS_OPTIMAL && status != SCIP_STATUS_GAPLIMIT &&
    1725 !(status == SCIP_STATUS_NODELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0) &&
    1726 !(status == SCIP_STATUS_TIMELIMIT && SCIPgetNSols((problem->blocks[b]).subscip) > 0 &&
    1727 SCIPisEQ(scip, SCIPgetSolOrigObj((problem->blocks[b]).subscip, SCIPgetBestSol((problem->blocks[b]).subscip)), 0.0) ) );
    1728 }
    1729 }
    1730
    1731 /* check wether problem has been solved and if not update penalty coeffs */
    1732 doscaling = FALSE;
    1733 solved = TRUE;
    1734 increasedslacks = 0;
    1735 maxpenalty = SCIP_REAL_MIN;
    1736 for( b = 0; b < problem->nblocks; b++ )
    1737 {
    1738 for( i = 0; i < blocktolinkvars[b].size; i++ )
    1739 {
    1740 int linkvaridx;
    1741 linkvaridx = blocktolinkvars[b].indexes[i];
    1742
    1743 for( k = 0; k < linkvartoblocks[linkvaridx].size; k++ )
    1744 {
    1745 int b2;
    1746 b2 = linkvartoblocks[linkvaridx].indexes[k];
    1747
    1748 if( b2 != b )
    1749 {
    1750 SCIP_SOL* sol;
    1751 BLOCKINFO binfo;
    1752 BLOCKINFO* binfoout;
    1753 SCIP_Real slackposval;
    1754 SCIP_Real slacknegval;
    1755
    1756 binfo.block = b;
    1757 binfo.otherblock = b2;
    1758 binfo.linkvaridx = linkvaridx;
    1759 binfoout = (BLOCKINFO*) SCIPhashtableRetrieve(htable, (void*) &binfo);
    1760 assert(binfoout != NULL);
    1761
    1762 sol = SCIPgetBestSol((problem->blocks[b]).subscip);
    1763 slackposval = SCIPgetSolVal((problem->blocks[b]).subscip, sol, binfoout->slackposvar);
    1764 slacknegval = SCIPgetSolVal((problem->blocks[b]).subscip, sol, binfoout->slacknegvar);
    1765
    1766 /* increase penalty coefficient of positive slack variable */
    1767 if( SCIPisGT(scip, slackposval, 0.0) )
    1768 {
    1769 binfoout->slackposobjcoeff *= 10.0;
    1770
    1771 if( binfoout->slackposobjcoeff > slackthreshold )
    1772 doscaling = TRUE;
    1773
    1774 if( binfoout->slackposobjcoeff > maxpenalty )
    1775 maxpenalty = binfoout->slackposobjcoeff;
    1776
    1777 solved = FALSE;
    1778 increasedslacks++;
    1779 }
    1780
    1781 /* increase penalty coefficient of negative slack variable */
    1782 if( SCIPisGT(scip, slacknegval, 0.0) )
    1783 {
    1784 binfoout->slacknegobjcoeff *= 10.0;
    1785
    1786 if( binfoout->slacknegobjcoeff > slackthreshold )
    1787 doscaling = TRUE;
    1788
    1789 if( binfoout->slacknegobjcoeff > maxpenalty )
    1790 maxpenalty = binfoout->slacknegobjcoeff;
    1791
    1792 solved = FALSE;
    1793 increasedslacks++;
    1794 }
    1795 }
    1796 }
    1797 }
    1798 }
    1799
    1800 /* should sigmoid scaling be applied to the penalty parameters? */
    1801 if( doscaling && heurdata->scaling )
    1802 {
    1803 SCIPdebugMsg(scip, "rescale penalty parameters\n");
    1804
    1805 /* reset counter */
    1806 increasedslacks = 0;
    1807
    1808 /* rescale penalty parameters */
    1809 SCIP_CALL( scalePenalties(problem, linkvartoblocks, blocktolinkvars, htable, maxpenalty) );
    1810 }
    1811
    1812 /* adapt in some cases the gap parameter */
    1813 if( (aiter == 1 && solutionsdiffer == FALSE) || (doscaling && heurdata->scaling) )
    1814 {
    1815 SCIP_Real mingap = 0.001; //todo
    1816 SCIP_Real newgap = MAX(gap * 0.5, mingap);
    1817
    1818 if( newgap >= mingap )
    1819 {
    1820 if( doscaling && heurdata->scaling )
    1821 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "scale, %f", newgap);
    1822 else
    1823 (void) SCIPsnprintf(info, SCIP_MAXSTRLEN, "%f", newgap);
    1824
    1825 gap = newgap;
    1826 }
    1827 }
    1828
    1829 /* free solution process data */
    1830 if( !solved )
    1831 for( b = 0; b < problem->nblocks; b++ )
    1832 {
    1833 SCIP_CALL( SCIPfreeTransform((problem->blocks[b]).subscip) );
    1834 }
    1835 }
    1836
    1837 /* copy solution if present */
    1838 if( solved )
    1839 {
    1840 SCIP_SOL* newsol;
    1841 SCIP_Real* blocksolvals;
    1842
    1843 assert(increasedslacks == 0);
    1844
    1845 SCIP_CALL( SCIPallocBufferArray(scip, &blocksolvals, nvars) );
    1846 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
    1847
    1848 for( b = 0; b < problem->nblocks; b++ )
    1849 {
    1850 SCIP_SOL* blocksol;
    1851 SCIP_VAR** blockvars;
    1852 int nblockvars;
    1853
    1854 /* get solution of block variables (without slack variables) */
    1855 blocksol = SCIPgetBestSol((problem->blocks[b]).subscip);
    1856 assert(blocksol != NULL);
    1857 blockvars = (problem->blocks[b]).subvars;
    1858 nblockvars = (problem->blocks[b]).nsubvars;
    1859 SCIP_CALL( SCIPgetSolVals((problem->blocks[b]).subscip, blocksol, nblockvars, blockvars, blocksolvals) );
    1860
    1861 for( i = 0; i < nblockvars; i++ )
    1862 {
    1863 SCIP_VAR* origvar;
    1864 SCIP_Real solval;
    1865
    1866 origvar = SCIPfindVar(scip, SCIPvarGetName(blockvars[i]));
    1867 solval = blocksolvals[i];
    1868 SCIP_CALL_ABORT( SCIPsetSolVal(scip, newsol, origvar, solval) );
    1869 }
    1870 }
    1871
    1872 /* treat variables with no constraints; set value of variable to bound */
    1873 for( i = 0; i < numlinkvars; i++ )
    1874 {
    1875 if( varonlyobj[i] )
    1876 {
    1877 SCIP_Real fixedvalue;
    1878 if( SCIPvarGetObj(linkvars[i]) < 0 )
    1879 {
    1880 fixedvalue = SCIPvarGetUbLocal(linkvars[i]);
    1881 if( SCIPisInfinity(scip, fixedvalue) )
    1882 break; // todo: maybe we should return the status UNBOUNDED instead
    1883 }
    1884 else
    1885 {
    1886 fixedvalue = SCIPvarGetLbLocal(linkvars[i]);
    1887 if( SCIPisInfinity(scip, fixedvalue) )
    1888 break; // todo: maybe we should return the status UNBOUNDED instead
    1889 }
    1890 SCIP_CALL_ABORT( SCIPsetSolVal(scip, newsol, linkvars[i], fixedvalue) );
    1891 }
    1892 }
    1893
    1894 SCIPdebugMsg(scip, "Objective value %.2f\n", SCIPgetSolOrigObj(scip, newsol));
    1895
    1896 /* fix linking variables and reoptimize with original objective function */
    1897 if( heurdata->reoptimize )
    1898 {
    1899 SCIP_SOL* improvedsol = NULL;
    1900 SCIP_CALL( reoptimize(scip, heur, newsol, vars, nvars, linkvars, numlinkvars, &improvedsol, &success) );
    1901 assert(improvedsol != NULL || success == FALSE);
    1902
    1903 if( success )
    1904 {
    1905 SCIP_CALL( SCIPtrySolFree(scip, &improvedsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1906 if( !success )
    1907 {
    1908 SCIPdebugMsg(scip, "Reoptimizing solution failed\n");
    1909 }
    1910 else
    1911 {
    1912 SCIPdebugMsg(scip, "Reoptimizing solution successful\n");
    1913 *result = SCIP_FOUNDSOL;
    1914 }
    1915 }
    1916 }
    1917
    1918 /* if reoptimization is turned off or reoptimization found no solution, try initial solution */
    1919 if( *result != SCIP_FOUNDSOL )
    1920 {
    1921 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1922 if( !success )
    1923 {
    1924 SCIPdebugMsg(scip, "Solution copy failed\n");
    1925 }
    1926 else
    1927 {
    1928 SCIPdebugMsg(scip, "Solution copy successful\n");
    1929 *result = SCIP_FOUNDSOL;
    1930 }
    1931 }
    1932 else
    1933 {
    1934 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
    1935 }
    1936
    1937 SCIPfreeBufferArray(scip, &blocksolvals);
    1938 }
    1939 else
    1940 {
    1941 SCIPdebugMsg(scip, "maximum number of penalty loops reached\n");
    1942 *result = SCIP_DIDNOTFIND;
    1943 }
    1944
    1945TERMINATE:
    1946 /* release variables, constraints and free memory */
    1947 if( problem != NULL )
    1948 {
    1949 for( b = 0; b < problem->nblocks; b++ )
    1950 {
    1951 BLOCK curr_block = problem->blocks[b];
    1952 for( i = 0; i < (problem->blocks[b]).ncoupling; i++ )
    1953 {
    1954 SCIP_CALL( SCIPreleaseCons(curr_block.subscip, &curr_block.couplingcons[i]) );
    1955 SCIP_CALL( SCIPreleaseVar(curr_block.subscip, &curr_block.slackspos[i]) );
    1956 SCIP_CALL( SCIPreleaseVar(curr_block.subscip, &curr_block.slacksneg[i]) );
    1957 }
    1958 }
    1959 }
    1960
    1961 if( htable != NULL )
    1962 SCIPhashtableFree(&htable);
    1963
    1964 if( blockinfolist != NULL )
    1965 SCIPfreeBufferArray(scip, &blockinfolist);
    1966
    1967 if( tmpcouplingcoef != NULL )
    1968 SCIPfreeBufferArray(scip, &tmpcouplingcoef);
    1969
    1970 if( tmpcouplingvars != NULL )
    1971 SCIPfreeBufferArray(scip, &tmpcouplingvars);
    1972
    1973 if( problem != NULL )
    1974 {
    1975 for( b = problem->nblocks - 1; b >= 0; b-- )
    1976 {
    1977 if( problem->blocks[b].couplingcons != NULL )
    1978 {
    1979 SCIPfreeBufferArray(scip, &problem->blocks[b].couplingcons);
    1980 SCIPfreeBufferArray(scip, &problem->blocks[b].slacksneg);
    1981 SCIPfreeBufferArray(scip, &problem->blocks[b].slackspos);
    1982 }
    1983 }
    1984 }
    1985
    1986 if( varonlyobj != NULL )
    1987 SCIPfreeBufferArray(scip, &varonlyobj);
    1988
    1989 if( problem != NULL && blocktolinkvars != NULL )
    1990 {
    1991 for( b = problem->nblocks -1; b >= 0; b-- )
    1992 {
    1993 if( blocktolinkvars[b].indexes != NULL )
    1994 SCIPfreeBufferArray(scip, &(blocktolinkvars[b].indexes));
    1995 }
    1996 }
    1997
    1998 if( linkvars != NULL )
    1999 SCIPfreeBufferArray(scip, &linkvars);
    2000
    2001 if( alllinkvartoblocks != NULL )
    2002 SCIPfreeBufferArray(scip, &alllinkvartoblocks);
    2003
    2004 if( blocktolinkvars != NULL )
    2005 SCIPfreeBufferArray(scip, &blocktolinkvars);
    2006
    2007 if( linkvartoblocks != NULL )
    2008 SCIPfreeBufferArray(scip, &linkvartoblocks);
    2009
    2010 if( assigneddecomp != NULL )
    2011 SCIPfreeDecomp(scip, &assigneddecomp);
    2012
    2013 if( consssize != NULL )
    2014 SCIPfreeBufferArray(scip, &consssize);
    2015
    2016 if( conslabels != NULL )
    2017 SCIPfreeBufferArray(scip, &conslabels);
    2018
    2019 if( varlabels != NULL )
    2020 SCIPfreeBufferArray(scip, &varlabels);
    2021
    2022 if( sortedconss != NULL )
    2023 SCIPfreeBufferArray(scip, &sortedconss);
    2024
    2025 if( problem != NULL )
    2026 {
    2027 SCIP_CALL( freeProblem(&problem, nblocks) );
    2028 }
    2029
    2030 SCIPdebugMsg(scip, "Leave padm heuristic\n");
    2031 return SCIP_OKAY;
    2032}
    2033
    2034/*
    2035 * primal heuristic specific interface methods
    2036 */
    2037
    2038/** creates the PADM primal heuristic and includes it in SCIP */
    2040 SCIP* scip /**< SCIP data structure */
    2041 )
    2042{
    2043 SCIP_HEURDATA* heurdata;
    2044 SCIP_HEUR* heur = NULL;
    2045
    2046 /* create PADM primal heuristic data */
    2047 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    2048
    2049 /* include primal heuristic */
    2052 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecPADM, heurdata) );
    2053
    2054 assert(heur != NULL);
    2055
    2056 /* primal heuristic is safe to use in exact solving mode */
    2057 SCIPheurMarkExact(heur);
    2058
    2059 /* set non fundamental callbacks via setter functions */
    2060 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyPADM) );
    2061 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreePADM) );
    2062
    2063 /* add padm primal heuristic parameters */
    2064 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    2065 "maximum number of nodes to regard in all subproblems",
    2066 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    2067
    2068 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    2069 "minimum number of nodes to regard in one subproblem",
    2070 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    2071
    2072 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodefac",
    2073 "factor to control nodelimits of subproblems", &heurdata->nodefac, TRUE, DEFAULT_NODEFAC, 0.0, 0.99, NULL, NULL) );
    2074
    2075 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/admiterations",
    2076 "maximal number of ADM iterations in each penalty loop", &heurdata->admiterations, TRUE, DEFAULT_ADMIT, 1, 100, NULL, NULL) );
    2077
    2078 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/penaltyiterations",
    2079 "maximal number of penalty iterations", &heurdata->penaltyiterations, TRUE, DEFAULT_PENALTYIT, 1, 100000, NULL, NULL) );
    2080
    2081 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gap",
    2082 "mipgap at start", &heurdata->gap, TRUE, DEFAULT_GAP, 0.0, 16.0, NULL, NULL) );
    2083
    2084 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reoptimize",
    2085 "should the problem get reoptimized with the original objective function?", &heurdata->reoptimize, FALSE, TRUE, NULL, NULL) );
    2086
    2087 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/scaling",
    2088 "enable sigmoid rescaling of penalty parameters", &heurdata->scaling, TRUE, TRUE, NULL, NULL) );
    2089
    2090 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/assignlinking",
    2091 "should linking constraints be assigned?", &heurdata->assignlinking, FALSE, TRUE, NULL, NULL) );
    2092
    2093 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/original",
    2094 "should the original problem be used? This is only for testing and not recommended!", &heurdata->original, TRUE, FALSE, NULL, NULL) );
    2095
    2096 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/timing",
    2097 "should the heuristic run before or after the processing of the node? (0: before, 1: after, 2: both)",
    2098 &heurdata->timing, FALSE, 0, 0, 2, NULL, NULL) );
    2099
    2100 return SCIP_OKAY;
    2101}
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    struct Problem PROBLEM
    Constraint handler for linear constraints in their most general form, .
    methods for debugging
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_DEFAULT_EPSILON
    Definition: def.h:173
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define EPSEQ(x, y, eps)
    Definition: def.h:192
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIP_REAL_MIN
    Definition: def.h:168
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define nnodes
    Definition: gastrans.c:74
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    SCIP_RETCODE SCIPcopyOrigConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:3134
    SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:2962
    SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
    Definition: scip_copy.c:1581
    SCIP_RETCODE SCIPcopyProb(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, const char *name)
    Definition: scip_copy.c:529
    SCIP_RETCODE SCIPtranslateSubSol(SCIP *scip, SCIP *subscip, SCIP_SOL *subsol, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_SOL **newsol)
    Definition: scip_copy.c:1398
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3293
    void SCIPgetDecomps(SCIP *scip, SCIP_DECOMP ***decomps, int *ndecomps, SCIP_Bool original)
    Definition: scip_dcmp.c:263
    SCIP_RETCODE SCIPdecompSetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
    Definition: dcmp.c:124
    int SCIPdecompGetNBlocks(SCIP_DECOMP *decomp)
    Definition: dcmp.c:279
    SCIP_RETCODE SCIPcomputeDecompVarsLabels(SCIP *scip, SCIP_DECOMP *decomp, SCIP_CONS **conss, int nconss)
    Definition: scip_dcmp.c:455
    SCIP_RETCODE SCIPdecompSetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
    Definition: dcmp.c:173
    SCIP_RETCODE SCIPassignDecompLinkConss(SCIP *scip, SCIP_DECOMP *decomp, SCIP_CONS **conss, int nconss, int *nskipconss)
    Definition: scip_dcmp.c:550
    void SCIPfreeDecomp(SCIP *scip, SCIP_DECOMP **decomp)
    Definition: scip_dcmp.c:234
    SCIP_RETCODE SCIPcomputeDecompStats(SCIP *scip, SCIP_DECOMP *decomp, SCIP_Bool uselimits)
    Definition: scip_dcmp.c:1136
    void SCIPdecompGetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
    Definition: dcmp.c:198
    SCIP_RETCODE SCIPdecompGetConssSize(SCIP_DECOMP *decomp, int *consssize, int nlabels)
    Definition: dcmp.c:349
    SCIP_RETCODE SCIPcreateDecomp(SCIP *scip, SCIP_DECOMP **decomp, int nblocks, SCIP_Bool original, SCIP_Bool benderslabels)
    Definition: scip_dcmp.c:218
    int SCIPdecompGetNBorderVars(SCIP_DECOMP *decomp)
    Definition: dcmp.c:379
    void SCIPdecompGetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
    Definition: dcmp.c:149
    SCIP_Bool SCIPdecompUseBendersLabels(SCIP_DECOMP *decomp)
    Definition: dcmp.c:269
    int SCIPdecompGetNBorderConss(SCIP_DECOMP *decomp)
    Definition: dcmp.c:394
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:742
    int SCIPgetNOrigBinVars(SCIP *scip)
    Definition: scip_prob.c:2867
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
    Definition: scip_prob.c:2811
    int SCIPgetNOrigIntVars(SCIP *scip)
    Definition: scip_prob.c:2896
    SCIP_CONS ** SCIPgetConss(SCIP *scip)
    Definition: scip_prob.c:3666
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
    Definition: scip_prob.c:3739
    SCIP_RETCODE SCIPwriteTransProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:789
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
    Definition: scip_prob.c:3189
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    #define SCIPhashFour(a, b, c, d)
    Definition: pub_misc.h:573
    SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2567
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    static INLINE uint32_t SCIPrealHashCode(double x)
    Definition: pub_misc.h:593
    SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2755
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
    Definition: scip_param.c:269
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    SCIP_RETCODE SCIPincludeHeurPADM(SCIP *scip)
    Definition: heur_padm.c:2039
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
    Definition: scip_cons.c:2577
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8454
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_Real SCIPheurGetTime(SCIP_HEUR *heur)
    Definition: heur.c:1655
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:76
    #define SCIPfreeMemoryArray(scip, ptr)
    Definition: scip_mem.h:80
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPaddSolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool *stored)
    Definition: scip_sol.c:3914
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:829
    SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1844
    SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1660
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2936
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4114
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3475
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
    Definition: var.c:24052
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPdoNotMultaggr(SCIP *scip)
    Definition: scip_var.c:10919
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24696
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
    Definition: scip_var.c:184
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE getTimeLeft(SCIP *scip, SCIP_Real *time)
    Definition: heur_padm.c:935
    static SCIP_RETCODE initProblem(SCIP *scip, PROBLEM **problem, int nblocks)
    Definition: heur_padm.c:255
    static SCIP_DECL_HEURFREE(heurFreePADM)
    Definition: heur_padm.c:978
    static SCIP_RETCODE blockCreateSubscip(BLOCK *block, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_CONS **conss, int nconss, SCIP_Bool useorigprob, SCIP_Bool *success)
    Definition: heur_padm.c:430
    #define DEFAULT_MAXNODES
    Definition: heur_padm.c:93
    static SCIP_DECL_HASHKEYEQ(indexesEqual)
    Definition: heur_padm.c:154
    static SCIP_RETCODE initBlock(PROBLEM *problem)
    Definition: heur_padm.c:203
    #define HEUR_TIMING
    Definition: heur_padm.c:88
    #define DEFAULT_MINNODES
    Definition: heur_padm.c:92
    #define DEFAULT_NODEFAC
    Definition: heur_padm.c:94
    #define HEUR_FREQOFS
    Definition: heur_padm.c:86
    static SCIP_DECL_HEUREXEC(heurExecPADM)
    Definition: heur_padm.c:994
    #define HEUR_DESC
    Definition: heur_padm.c:82
    #define COUPLINGSIZE
    Definition: heur_padm.c:91
    static SCIP_RETCODE createSubscip(SCIP *scip, SCIP **subscip)
    Definition: heur_padm.c:321
    #define HEUR_DISPCHAR
    Definition: heur_padm.c:83
    static SCIP_DECL_HASHKEYVAL(indexesHashval)
    Definition: heur_padm.c:171
    #define HEUR_MAXDEPTH
    Definition: heur_padm.c:87
    #define HEUR_PRIORITY
    Definition: heur_padm.c:84
    struct set SET
    #define HEUR_NAME
    Definition: heur_padm.c:81
    #define DEFAULT_ADMIT
    Definition: heur_padm.c:95
    static SCIP_RETCODE assignLinking(SCIP *scip, SCIP_DECOMP *newdecomp, SCIP_VAR **vars, SCIP_CONS **sortedconss, int *varlabels, int *conslabels, int nvars, int nconss, int nlinkconss)
    Definition: heur_padm.c:570
    struct Block BLOCK
    static SCIP_RETCODE copyToSubscip(SCIP *scip, SCIP *subscip, const char *name, SCIP_CONS **conss, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, int nconss, SCIP_Bool useorigprob, SCIP_Bool *success)
    Definition: heur_padm.c:369
    static SCIP_RETCODE reuseSolution(SCIP *subscip, BLOCK *block)
    Definition: heur_padm.c:611
    static SCIP_RETCODE createAndSplitProblem(SCIP *scip, SCIP_CONS **sortedconss, int nconss, int *consssize, int nblocks, PROBLEM **problem, SCIP_Bool useorigprob, SCIP_Bool *success)
    Definition: heur_padm.c:502
    static SCIP_RETCODE scalePenalties(PROBLEM *problem, SET *linkvartoblocks, SET *blocktolinkvars, SCIP_HASHTABLE *htable, SCIP_Real maxpenalty)
    Definition: heur_padm.c:872
    static SCIP_DECL_HEURCOPY(heurCopyPADM)
    Definition: heur_padm.c:962
    #define DEFAULT_PENALTYIT
    Definition: heur_padm.c:96
    static SCIP_RETCODE freeBlock(BLOCK *block)
    Definition: heur_padm.c:232
    #define HEUR_FREQ
    Definition: heur_padm.c:85
    struct blockinfo BLOCKINFO
    #define HEUR_USESSUBSCIP
    Definition: heur_padm.c:89
    static SCIP_RETCODE reoptimize(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol, SCIP_VAR **vars, int nvars, SCIP_VAR **linkvars, int nlinkvars, SCIP_SOL **newsol, SCIP_Bool *success)
    Definition: heur_padm.c:709
    static SCIP_RETCODE freeProblem(PROBLEM **problem, int nblocks)
    Definition: heur_padm.c:285
    #define DEFAULT_GAP
    Definition: heur_padm.c:97
    PADM primal heuristic.
    methods commonly used by primal heuristics
    memory allocation routines
    public methods for managing constraints
    public methods for primal heuristics
    public methods for message output
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    public data structures and miscellaneous methods
    methods for selecting k-medians
    public methods for primal CIP solutions
    public methods for branch and bound tree
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for decompositions
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for node selector plugins
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for statistics table plugins
    public methods for timing
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
    default SCIP plugins
    PROBLEM * problem
    Definition: heur_padm.c:109
    SCIP_VAR ** subvars
    Definition: heur_padm.c:112
    int ncoupling
    Definition: heur_padm.c:117
    SCIP_VAR ** slacksneg
    Definition: heur_padm.c:115
    SCIP_VAR ** slackspos
    Definition: heur_padm.c:114
    SCIP_Real size
    Definition: heur_padm.c:118
    SCIP_CONS ** couplingcons
    Definition: heur_padm.c:116
    int nsubvars
    Definition: heur_padm.c:113
    int number
    Definition: heur_padm.c:111
    SCIP * subscip
    Definition: heur_padm.c:110
    unsigned int original
    Definition: struct_cons.h:83
    SCIP_Bool original
    Definition: struct_dcmp.h:62
    SCIP_Real slackposobjcoeff
    Definition: heur_padm.c:145
    SCIP_VAR * slackposvar
    Definition: heur_padm.c:146
    int otherblock
    Definition: heur_padm.c:141
    int linkvaridx
    Definition: heur_padm.c:142
    SCIP_CONS * couplingCons
    Definition: heur_padm.c:149
    SCIP_VAR * slacknegvar
    Definition: heur_padm.c:148
    SCIP_VAR * linkvar
    Definition: heur_padm.c:144
    SCIP_Real slacknegobjcoeff
    Definition: heur_padm.c:147
    SCIP_Real linkvarval
    Definition: heur_padm.c:143
    int block
    Definition: heur_padm.c:140
    Definition: heur_padm.c:132
    int size
    Definition: heur_padm.c:133
    int * indexes
    Definition: heur_padm.c:134
    #define SCIP_DECOMP_LINKVAR
    Definition: type_dcmp.h:44
    #define SCIP_DECOMP_LINKCONS
    Definition: type_dcmp.h:45
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_UNBOUNDED
    Definition: type_stat.h:45
    @ SCIP_STATUS_GAPLIMIT
    Definition: type_stat.h:56
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    #define SCIP_HEURTIMING_AFTERNODE
    Definition: type_timing.h:98
    #define SCIP_HEURTIMING_BEFORENODE
    Definition: type_timing.h:80
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71