Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_dks.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_dks.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief dks primal heuristic
    28 * @author Adrian Göß
    29 * @author Dieter Weninger
    30 *
    31 * Primal heuristic based on ideas published in the paper
    32 * "Exploiting user-supplied Decompositions inside Heuristics" by Katrin Halbig, Adrian Göß and Dieter Weninger.
    33 */
    34
    35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+--*/
    36
    37#include "scip/pub_lp.h"
    39#include "scip/cons_linear.h"
    40#include "scip/debug.h"
    41#include "scip/heuristics.h"
    42#include "scip/pub_cons.h"
    43#include "scip/pub_event.h"
    44#include "scip/pub_fileio.h"
    45#include "scip/pub_tree.h"
    46#include "scip/pub_heur.h"
    47#include "scip/pub_message.h"
    48#include "scip/pub_misc.h"
    50#include "scip/pub_sol.h"
    51#include "scip/pub_var.h"
    52#include "scip/scipdefplugins.h"
    53#include "scip/scip_branch.h"
    54#include "scip/scip_cons.h"
    55#include "scip/scip_copy.h"
    56#include "scip/scip_dcmp.h"
    57#include "scip/scip_event.h"
    58#include "scip/scip_general.h"
    59#include "scip/scip_heur.h"
    60#include "scip/scip_lp.h"
    61#include "scip/scip_mem.h"
    62#include "scip/scip_message.h"
    63#include "scip/scip_nodesel.h"
    64#include "scip/scip_numerics.h"
    65#include "scip/scip_param.h"
    66#include "scip/scip_prob.h"
    68#include "scip/scip_sol.h"
    69#include "scip/scip_solve.h"
    71#include "scip/scip_table.h"
    72#include "scip/scip_timing.h"
    73#include "scip/scip_tree.h"
    74#include "scip/scip_var.h"
    75#include "scip/sol.h"
    76#include "scip/heur_dks.h"
    77
    78
    79#define HEUR_NAME "dks"
    80#define HEUR_DESC "decomposition kernel search"
    81#define HEUR_DISPCHAR 'D'
    82#define HEUR_PRIORITY -1102500
    83#define HEUR_FREQ -1
    84#define HEUR_FREQOFS 0
    85#define HEUR_MAXDEPTH 0
    86#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
    87#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    88
    89#define DEFAULT_MAXBUCKS 20 /**< default value for the number of buckets to investigate */
    90#define DEFAULT_KERNELSIZEFACTOR 2.0 /**< default value for the maximal growing of the kernel size */
    91#define DEFAULT_ADDUSECONSS TRUE /**< default value to add a use constraint */
    92#define DEFAULT_LINKBUCKSIZE TRUE /**< default value to respect kernel linking vars for the bucket size */
    93#define DEFAULT_TRANSLBKERNEL TRUE /**< default value to respect the diff of var lb in trans and orig prob */
    94#define DEFAULT_LESSLOCKSKERNEL FALSE /**< default value to respect <= 1 up- & downlock in kernel construction */
    95#define DEFAULT_USETRANSPROB TRUE /**< default value to use the original or transformed problem **/
    96#define DEFAULT_BUCKMAXGAP 0.01 /**< default value for the maximal mip gap of a bucket */
    97#define DEFAULT_MAXLINKSCORE 1.0 /**< default value for the maximal linking score of an instance */
    98#define DEFAULT_MAXBUCKFRAC 0.10 /**< default value to respect buckets with <= this share of bin/int vars */
    99#define DEFAULT_MAXNODES 5000LL /**< default node limit of the heuristic */
    100#define DEFAULT_USETWOLEVEL TRUE /**< default value to use a two level structure for the buckets */
    101#define DEFAULT_USEDECOMP TRUE /**< default value to use the decomp if given */
    102#define DEFAULT_USEBESTSOL TRUE /**< default value to use the best existing solution or the lp solution */
    103#define DEFAULT_REDCOSTSORT TRUE /**< default value to sort the non kernel vars before bucket split */
    104#define DEFAULT_PRIMALONLY FALSE /**< default value to kill dks after the first primal solution is found */
    105#define DEFAULT_REDCOSTLOGSORT TRUE /**< default value to sort non kernel vars logarithmically by redcost */
    106#define DEFAULT_OBJCUTOFF TRUE /**< default value to add an objective cutoff */
    107#define DEFAULT_RUNBINPROBSONLY FALSE /**< default value to run only for bin or bin + int only problems */
    108
    109/*
    110 * Data structures
    111 */
    112
    113/** data related to one bucket list, details see below **/
    114typedef struct Bucketlist BUCKETLIST;
    115
    116/** data related to one bucket **/
    117typedef struct Bucket
    118{
    119 BUCKETLIST* bucketlist; /**< the bucketlist the bucket belongs to */
    120 SCIP* subscip; /**< scip structure to solve smaller MIPs later */
    121 int number; /**< component number */
    122 SCIP_VAR** contbucketvars; /**< continuous variables for this bucket */
    123 SCIP_VAR** bucketvars; /**< variables of this bucket, just binary if 2-level bucket */
    124 SCIP_VAR** intbucketvars; /**< just integer variables if 2-level bucket */
    125 int ncontbucketvars; /**< amount of continuous variables in this bucket */
    126 int nbucketvars; /**< amount of variables in this bucket */
    127 int nintbucketvars; /**< amount of integer variables in a 2-level bucket */
    128 SCIP_Bool twolevel; /**< is the current bucket a 2-level one */
    129 SCIP_VAR** sub2scip; /**< mapping the variables to the original ones */
    130 SCIP_VAR** scip2sub; /**< mapping original variables to subscip ones */
    132
    133/** data related to one whole list of buckets **/
    135{
    136 SCIP* scip; /**< scip instance this bucketlist belongs to */
    137 BUCKET* buckets; /**< buckets in this bucketlist */
    138 int nbuckets; /**< amount of buckets in this bucketlist */
    139};
    140
    141/** primal heuristic data */
    142struct SCIP_HeurData
    143{
    144 int maxbucks; /**< maximum amount of buckets that are investigated */
    145 SCIP_Real kernelsizefactor; /**< factor with which initial kernel can grow max */
    146 SCIP_Bool addUseConss; /**< add a constraint that ensures a use of the bucket variables or not */
    147 SCIP_Bool linkbucksize; /**< respect the kernel linking variables for the initial bucket size */
    148 SCIP_Bool translbkernel; /**< respect the variable's lb in transprob at kernel construction */
    149 SCIP_Bool lesslockskernel; /**< respect variables with <= 1 up & downlock at kernel construction */
    150 SCIP_Bool usetransprob; /**< use the transformed problem instead of the original one */
    151 SCIP_Real buckmaxgap; /**< set an upper bound for the maximum mip gap of each bucket */
    152 SCIP_Real maxlinkscore; /**< set an upper bound for the linking score to get solved by dks */
    153 SCIP_Real maxbuckfrac; /**< maximal share of int/bin variables for a bucket to be computed */
    154 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in all subproblems */
    155 SCIP_Bool usetwolevel; /**< use two level structure for the buckets if possible */
    156 SCIP_Bool usedecomp; /**< use decomp if given */
    157 SCIP_Bool usebestsol; /**< use best solution or alt. LP sol */
    158 SCIP_Bool redcostsort; /**< sort the non kernel variables by reduced costs */
    159 SCIP_Bool primalonly; /**< terminate after the first found primal solution */
    160 SCIP_Bool redcostlogsort; /**< flag indicating logarithmically sorted reduced costs at bucket init */
    161 SCIP_Bool objcutoff; /**< add an objective cutoff for the current best sol */
    162 int ncalls; /**< amount of calls of the heuristic */
    163 SCIP_Bool runbinprobsonly; /**< flag indicating if executing only on bin/int problems */
    164 SCIP_Bool uselesscall; /**< flag indicating if DKS has been called once & not found a solution */
    165};
    166
    167
    168/*
    169 * Local methods
    170 */
    171
    172/** calculate the linking score of a given decomposition */
    173static
    175 int* blocklabels, /**< int array to store the different block labels */
    176 int* varlabels, /**< array of variable labels */
    177 int* conslabels, /**< array of constraint labels */
    178 SCIP_Real* linkscore, /**< linking score to return */
    179 int* nblocklabels, /**< number of block labels to return */
    180 int nblocks, /**< number of blocks */
    181 int nvars, /**< number of variables */
    182 int nconss /**< number of constraints */
    183 )
    184{
    185 int v;
    186 int b;
    187
    188 int nlinkscoreconss = 0; /* number of linking conss for calculation */
    189 int nlinkscorevars = 0; /* number of linking vars for calculation */
    190
    191 assert(nblocklabels != NULL);
    192
    193 *nblocklabels = 0; /* number of distinct block labels */
    194
    195 for( v = 0; v < nvars; v++ )
    196 {
    197 assert(varlabels != NULL);
    198
    199 /* counting of linking variables */
    200 if( varlabels[v] == SCIP_DECOMP_LINKVAR )
    201 nlinkscorevars++;
    202 /* fill an array for the existing distinct block labels that are not linking variables */
    203 else if( *nblocklabels < nblocks && blocklabels != NULL )
    204 {
    205 SCIP_Bool newlabel = TRUE; /* indication of finding a new label */
    206
    207 /* check the current label for novelty */
    208 for( b = 0; b < *nblocklabels; b++ )
    209 {
    210 if( blocklabels[b] == varlabels[v] )
    211 {
    212 newlabel = FALSE;
    213 break;
    214 }
    215 }
    216
    217 /* add unseen labels */
    218 if( newlabel )
    219 blocklabels[(*nblocklabels)++] = varlabels[v];
    220 }
    221 }
    222
    223 /* counting of linking constraints */
    224 for( v = 0; v < nconss; v++ )
    225 {
    226 assert(conslabels != NULL);
    227 if( conslabels[v] == SCIP_DECOMP_LINKCONS )
    228 nlinkscoreconss++;
    229 }
    230
    231 /* linking score calculation */
    232 *linkscore = ( (SCIP_Real)nlinkscorevars*(SCIP_Real)nconss + (SCIP_Real)nlinkscoreconss*(SCIP_Real)nvars -
    233 (SCIP_Real)nlinkscorevars*(SCIP_Real)nlinkscoreconss ) / ((SCIP_Real)nconss*(SCIP_Real)nvars);
    234
    235 return SCIP_OKAY;
    236}
    237
    238/** count of potential kernel variables for one level or two level structure */
    239static
    241 SCIP* scip, /**< main SCIP data structure */
    242 SCIP_VAR** vars, /**< array of variables */
    243 SCIP_SOL* bestcurrsol, /**< best current solution */
    244 SCIP_HASHMAP* lbvarmap, /**< original lower bound of transformed variables */
    245 SCIP_Bool twolevel, /**< usage of one or two level structure */
    246 SCIP_Bool usebestsol, /**< usage of best or lp solution */
    247 SCIP_Bool usetransprob, /**< usage of transformed or original problem */
    248 SCIP_Bool usetranslb, /**< usage of transformed lb in comparison to original lb */
    249 int* bw_ncontkernelvars, /**< blockwise number of continuous kernel variables */
    250 int* bw_ncontnonkernelvars, /**< blockwise number of continuous non-kernel variables */
    251 int* bw_nkernelvars, /**< blockwise number of (binary) kernel variables */
    252 int* bw_nnonkernelvars, /**< blockwise number of (binary) non-kernel variables */
    253 int* bw_nintkernelvars, /**< blockwise number of integer kernel variables */
    254 int* bw_nintnonkernelvars, /**< blockwise number of integer non-kernel variables */
    255 int* ncontkernelvars, /**< number of continuous kernel variables */
    256 int* ncontnonkernelvars, /**< number of continuous non-kernel variables */
    257 int* nkernelvars, /**< number of (binary) kernel variables */
    258 int* nnonkernelvars, /**< number of (binary) non-kernel variables */
    259 int* nintkernelvars, /**< number of integer kernel variables */
    260 int* nintnonkernelvars, /**< number of integer non-kernel variables */
    261 int* block2index, /**< mapping of block labels to block index */
    262 int* varlabels, /**< array of variable labels */
    263 int blklbl_offset, /**< optional offset for the blocklabels, if it exists a block 0 */
    264 int nvars /**< number of variables */
    265 )
    266{
    267 SCIP_Real lpval; /* variable value in LP solution */
    268 SCIP_Real lb;
    269 SCIP_Real lborig;
    270 int i;
    271 int block;
    272
    273 assert(bw_ncontkernelvars != NULL);
    274 assert(bw_ncontnonkernelvars != NULL);
    275 assert(bw_nkernelvars != NULL);
    276 assert(bw_nnonkernelvars != NULL);
    277
    278 assert(ncontkernelvars != NULL);
    279 assert(ncontnonkernelvars != NULL);
    280 assert(nkernelvars != NULL);
    281 assert(nnonkernelvars != NULL);
    282
    283 /* count all possible kernel variables dependent on their type blockwise and overall */
    284 for( i = 0; i < nvars; i++ )
    285 {
    286 /* calculate the variable's LP solution value, the lower bound in the transformed and original problem */
    287 lpval = usebestsol ? SCIPgetSolVal(scip, bestcurrsol, vars[i]) : SCIPvarGetLPSol(vars[i]);
    288 lb = SCIPvarGetLbLocal(vars[i]);
    289 lborig = usetransprob ? SCIPhashmapGetImageReal(lbvarmap, vars[i]) : SCIPvarGetLbOriginal(vars[i]);
    290
    291 /* definition of the variable's block (SCIP_DECOMP_LINKVAR = -1, but is stored as 0) */
    292 block = block2index[MAX(varlabels[i] + blklbl_offset, 0)];
    293
    294 switch( SCIPvarGetType(vars[i]) )
    295 {
    296 /* compare binaries only to the lower bound of 0.0 and count as kernel or non-kernel variable */
    298 if( !SCIPisEQ(scip, lpval, 0.0) )
    299 {
    300 (*nkernelvars)++;
    301 bw_nkernelvars[block]++;
    302 }
    303 else
    304 {
    305 (*nnonkernelvars)++;
    306 bw_nnonkernelvars[block]++;
    307 }
    308 break;
    309
    310 /* LP value > lb -> count integer as kernel variable else not */
    311 /* count separatly if binaries and integers are present */
    313 if( (!SCIPisEQ(scip, lpval, 0.0) && !SCIPisEQ(scip, lpval, lb))
    314 || (usetranslb && SCIPisGT(scip, lb, lborig)) )
    315 {
    316 if( twolevel )
    317 {
    318 if( nintkernelvars != NULL )
    319 (*nintkernelvars)++;
    320 if( bw_nintkernelvars != NULL )
    321 bw_nintkernelvars[block]++;
    322 }
    323 else
    324 {
    325 (*nkernelvars)++;
    326 bw_nkernelvars[block]++;
    327 }
    328 }
    329 else
    330 {
    331 if( twolevel )
    332 {
    333 if( nintnonkernelvars != NULL )
    334 (*nintnonkernelvars)++;
    335 if( bw_nintnonkernelvars != NULL )
    336 bw_nintnonkernelvars[block]++;
    337 }
    338 else
    339 {
    340 (*nnonkernelvars)++;
    341 bw_nnonkernelvars[block]++;
    342 }
    343 }
    344 break;
    345
    346 /* LP value > lower bound -> potential kernel variable else not for continuous vars */
    348 default:
    349 if( (!SCIPisEQ(scip, lpval, 0.0) && !SCIPisEQ(scip, lpval, lb) )
    350 || (usetranslb && SCIPisGT(scip, lb, lborig)) )
    351 {
    352 (*ncontkernelvars)++;
    353 bw_ncontkernelvars[block]++;
    354 }
    355 else
    356 {
    357 (*ncontnonkernelvars)++;
    358 bw_ncontnonkernelvars[block]++;
    359 }
    360 break;
    361 } /*lint !e788*/
    362 }
    363
    364 return SCIP_OKAY;
    365}
    366
    367/** fill the blockwise kernels with the respective variables */
    368static
    370 SCIP* scip, /**< main SCIP data structure */
    371 SCIP_VAR** vars, /**< array of variables */
    372 SCIP_VAR** binintvars, /**< array of binary and integer variables */
    373 SCIP_VAR*** bw_contkernelvars, /**< blockwise array of continuous kernel variables */
    374 SCIP_VAR*** bw_contnonkernelvars, /**< blockwise array of continuous non-kernel variables */
    375 SCIP_VAR*** bw_kernelvars, /**< blockwise array of (binary) kernel variables */
    376 SCIP_VAR*** bw_nonkernelvars, /**< blockwise array of (binary) non-kernel variables */
    377 SCIP_VAR*** bw_intkernelvars, /**< blockwise array of integer kernel variables */
    378 SCIP_VAR*** bw_intnonkernelvars, /**< blockwise array of integer non-kernel variables */
    379 SCIP_SOL* bestcurrsol, /**< best current solution */
    380 SCIP_HASHMAP* lbvarmap, /**< original lower bound of transformed variables */
    381 SCIP_Bool twolevel, /**< usage of one or two level structure */
    382 SCIP_Bool usebestsol, /**< usage of best or lp solution */
    383 SCIP_Bool usetransprob, /**< usage of transformed or original problem */
    384 SCIP_Bool usetranslb, /**< usage of transformed lb in comparison to original lb */
    385 int* bw_contkernelcount, /**< blockwise counter of continuous kernel variables */
    386 int* bw_contnonkernelcount, /**< blockwise counter of continuous non-kernel variables */
    387 int* bw_kernelcount, /**< blockwise counter of (binary) kernel variables */
    388 int* bw_nonkernelcount, /**< blockwise counter of (binary) non-kernel variables */
    389 int* bw_intkernelcount, /**< blockwise counter of integer kernel variables */
    390 int* bw_intnonkernelcount, /**< blockwise counter of integer non-kernel variables */
    391 int* bw_ncontkernelvars, /**< blockwise number of continuous kernel variables */
    392 int* bw_ncontnonkernelvars, /**< blockwise number of continuous non-kernel variables */
    393 int* bw_nkernelvars, /**< blockwise number of (binary) kernel variables */
    394 int* bw_nnonkernelvars, /**< blockwise number of (binary) non-kernel variables */
    395 int* bw_nintkernelvars, /**< blockwise number of integer kernel variables */
    396 int* bw_nintnonkernelvars, /**< blockwise number of integer non-kernel variables */
    397 int* block2index, /**< mapping of block labels to block index */
    398 int* varlabels, /**< array of variable labels */
    399 int blklbl_offset, /**< optional offset for the blocklabels, if it exists a block 0 */
    400 int nvars /**< number of variables */
    401 )
    402{
    403 SCIP_Real lpval; /* variable value in LP solution */
    404 SCIP_Real lb;
    405 SCIP_Real lborig;
    406 int i; /* variable counter */
    407 int j = 0; /* integer and binary variable counter */
    408 int m; /* temporary integer variable index */
    409 int n; /* temporary (binary) variable index */
    410 int l; /* temporary continuous variable index */
    411 int block_index;
    412
    413 assert(bw_contkernelvars != NULL);
    414 assert(bw_contnonkernelvars != NULL);
    415 assert(bw_kernelvars != NULL);
    416 assert(bw_nonkernelvars != NULL);
    417 assert(bw_contkernelcount != NULL);
    418 assert(bw_contnonkernelcount != NULL);
    419 assert(bw_kernelcount != NULL);
    420 assert(bw_nonkernelcount != NULL);
    421
    422 /* assign all variables dependent on their type blockwise to a kernel or a non-kernel */
    423 for( i = 0; i < nvars; i++ )
    424 {
    425 /* calculate the variable's LP solution value, the lower bound in the transformed and original problem */
    426 lpval = usebestsol ? SCIPgetSolVal(scip, bestcurrsol, vars[i]) : SCIPvarGetLPSol(vars[i]);
    427 lb = SCIPvarGetLbLocal(vars[i]);
    428 lborig = usetransprob ? SCIPhashmapGetImageReal(lbvarmap, vars[i]) : SCIPvarGetLbOriginal(vars[i]);
    429
    430 /* definition of the variable's block index (SCIP_DECOMP_LINKVAR = -1, but is stored as 0 in block2index) */
    431 block_index = block2index[MAX(varlabels[i] + blklbl_offset, 0)];
    432
    433 switch( SCIPvarGetType(vars[i]) )
    434 {
    435 /* compare binaries only to the lower bound of 0.0 and add to kernel or non-kernel variables */
    437 /* adding the variable to the binary and integer variable array */
    438 binintvars[j++] = vars[i];
    439
    440 if( !SCIPisEQ(scip, lpval, 0.0) )
    441 {
    442 n = bw_kernelcount[block_index];
    443 assert(bw_nnonkernelvars != NULL);
    444 assert(n < bw_nkernelvars[block_index] + bw_nnonkernelvars[block_index]);
    445 bw_kernelvars[block_index][n] = vars[i];
    446 bw_kernelcount[block_index]++;
    447 }
    448 else
    449 {
    450 n = bw_nonkernelcount[block_index];
    451 assert(bw_nnonkernelvars != NULL);
    452 assert(n < bw_nkernelvars[block_index] + bw_nnonkernelvars[block_index]);
    453 bw_nonkernelvars[block_index][n] = vars[i];
    454 bw_nonkernelcount[block_index]++;
    455 }
    456 break;
    457
    458 /* LP value > lb -> integer kernel variable else non-kernel variable */
    459 /* count separatly if binaries and integers are present */
    461 /* adding the variable to the binary and integer variable array */
    462 binintvars[j++] = vars[i];
    463
    464 if( (!SCIPisEQ(scip, lpval, 0.0) && !SCIPisEQ(scip, lpval, lb))
    465 || (usetranslb && SCIPisGT(scip, lb, lborig)) )
    466 {
    467 if( twolevel )
    468 {
    469 if( bw_intkernelcount != NULL )
    470 {
    471 m = bw_intkernelcount[block_index];
    472 assert(bw_nintnonkernelvars != NULL);
    473 assert(bw_nintkernelvars != NULL);
    474 assert(m < bw_nintkernelvars[block_index] + bw_nintnonkernelvars[block_index]);
    475 if( bw_intkernelvars != NULL )
    476 bw_intkernelvars[block_index][m] = vars[i];
    477 bw_intkernelcount[block_index]++;
    478 }
    479 }
    480 else
    481 {
    482 m = bw_kernelcount[block_index];
    483 assert(bw_nnonkernelvars != NULL);
    484 assert(m < bw_nkernelvars[block_index] + bw_nnonkernelvars[block_index]);
    485 bw_kernelvars[block_index][m] = vars[i];
    486 bw_kernelcount[block_index]++;
    487 }
    488 }
    489 else
    490 {
    491 if( twolevel )
    492 {
    493 if( bw_intnonkernelcount != NULL )
    494 {
    495 m = bw_intnonkernelcount[block_index];
    496 assert(bw_nintnonkernelvars != NULL);
    497 assert(bw_nintkernelvars != NULL);
    498 assert(m < bw_nintkernelvars[block_index] + bw_nintnonkernelvars[block_index]);
    499 if( bw_intnonkernelvars != NULL )
    500 bw_intnonkernelvars[block_index][m] = vars[i];
    501 bw_intnonkernelcount[block_index]++;
    502 }
    503 }
    504 else
    505 {
    506 m = bw_nonkernelcount[block_index];
    507 assert(bw_nnonkernelvars != NULL);
    508 assert(m < bw_nkernelvars[block_index] + bw_nnonkernelvars[block_index]);
    509 bw_nonkernelvars[block_index][m] = vars[i];
    510 bw_nonkernelcount[block_index]++;
    511 }
    512 }
    513 break;
    514
    515 /* LP value > lower bound -> continuous kernel variable else non-kernel variable */
    517 default:
    518 if( (!SCIPisEQ(scip, lpval, 0.0) && !SCIPisEQ(scip, lpval, lb) )
    519 || (usetranslb && SCIPisGT(scip, lb, lborig)) )
    520 {
    521 l = bw_contkernelcount[block_index];
    522 assert(bw_ncontnonkernelvars != NULL);
    523 assert(l < bw_ncontkernelvars[block_index] + bw_ncontnonkernelvars[block_index]);
    524 bw_contkernelvars[block_index][l] = vars[i];
    525 bw_contkernelcount[block_index]++;
    526 }
    527 else
    528 {
    529 l = bw_contnonkernelcount[block_index];
    530 assert(bw_ncontnonkernelvars != NULL);
    531 assert(l < bw_ncontkernelvars[block_index] + bw_ncontnonkernelvars[block_index]);
    532 bw_contnonkernelvars[block_index][l] = vars[i];
    533 bw_contnonkernelcount[block_index]++;
    534 }
    535 break;
    536 } /*lint !e788*/
    537 }
    538
    539 return SCIP_OKAY;
    540}
    541
    542/** calculation of reduced costs and non-decreasing sorting **/
    543static
    545 SCIP* scip, /**< main SCIP data structure */
    546 SCIP_VAR*** bw_contnonkernelvars, /**< array pointer of continuous, non-kernel variables */
    547 SCIP_VAR*** bw_nonkernelvars, /**< array pointer of (binary,) non-kernel variables */
    548 SCIP_VAR*** bw_intnonkernelvars, /**< array pointer of integer, non-kernel variables */
    549 SCIP_Real*** bw_cont_redcost, /**< array pointer with reduced costs for continuous variables */
    550 SCIP_Real*** bw_redcost, /**< array pointer with reduced costs for (binary) variables */
    551 SCIP_Real*** bw_int_redcost, /**< array pointer with reduced costs for integer variables */
    552 int* bw_ncontnonkernelvars, /**< blockwise number of continuous, non-kernel variables */
    553 int* bw_nnonkernelvars, /**< blockwise number of (binary,) non-kernel variables */
    554 int* bw_nintnonkernelvars, /**< blockwise number of integer, non-kernel variables */
    555 SCIP_Bool twolevel, /**< usage of one or two level structure */
    556 int nblocks /**< number of blocks */
    557 )
    558{
    559 int b; /* block counter */
    560 int i; /* variable counter */
    561
    562 SCIP_CALL( SCIPallocBufferArray(scip, bw_cont_redcost, nblocks + 1) );
    563 SCIP_CALL( SCIPallocBufferArray(scip, bw_redcost, nblocks + 1) );
    564 if( twolevel )
    565 SCIP_CALL( SCIPallocBufferArray(scip, bw_int_redcost, nblocks + 1) );
    566
    567 /* blockwise and type-wise extraction of reduced costs and sorting in non-decreasing order */
    568 for( b = 0; b < nblocks + 1; b++ )
    569 {
    570 SCIP_CALL( SCIPallocBufferArray(scip, &((*bw_cont_redcost)[b]), bw_ncontnonkernelvars[b]) );
    571 SCIP_CALL( SCIPallocBufferArray(scip, &((*bw_redcost)[b]), bw_nnonkernelvars[b]) );
    572
    573 for( i = 0; i < bw_ncontnonkernelvars[b]; i++ )
    574 {
    575 (*bw_cont_redcost)[b][i] = SCIPgetVarRedcost(scip, bw_contnonkernelvars[b][i]);
    576 /* if a var is not in LP (SCIP_INVALID), we assign a reduced cost of zero & thus the var to an early bucket */
    577 if( (*bw_cont_redcost)[b][i] == SCIP_INVALID ) /*lint !e777*/
    578 (*bw_cont_redcost)[b][i] = 0.0;
    579 }
    580
    581 for( i = 0; i < bw_nnonkernelvars[b]; i++ )
    582 {
    583 (*bw_redcost)[b][i] = SCIPgetVarRedcost(scip, bw_nonkernelvars[b][i]);
    584 /* if a var is not in LP (SCIP_INVALID), we assign a reduced cost of zero & thus the var to an early bucket */
    585 if( (*bw_redcost)[b][i] == SCIP_INVALID ) /*lint !e777*/
    586 (*bw_redcost)[b][i] = 0.0;
    587 }
    588
    589 SCIPsortRealPtr((*bw_cont_redcost)[b], (void**)bw_contnonkernelvars[b], bw_ncontnonkernelvars[b]);
    590 SCIPsortRealPtr((*bw_redcost)[b], (void**)bw_nonkernelvars[b], bw_nnonkernelvars[b]);
    591
    592 if( twolevel )
    593 {
    594 SCIP_CALL( SCIPallocBufferArray(scip, &((*bw_int_redcost)[b]), bw_nintnonkernelvars[b]) );
    595
    596 for( i = 0; i < bw_nintnonkernelvars[b]; i++ )
    597 {
    598 (*bw_int_redcost)[b][i] = SCIPgetVarRedcost(scip, bw_intnonkernelvars[b][i]);
    599 /* if a var is not in LP (SCIP_INVALID), we assign a red cost of zero & thus the var to an early bucket */
    600 if( (*bw_int_redcost)[b][i] == SCIP_INVALID ) /*lint !e777*/
    601 (*bw_int_redcost)[b][i] = 0.0;
    602 }
    603
    604 SCIPsortRealPtr((*bw_int_redcost)[b], (void**)bw_intnonkernelvars[b], bw_nintnonkernelvars[b]);
    605 }
    606 }
    607
    608 return SCIP_OKAY;
    609}
    610
    611/** free memory of reduced cost arrays */
    612static
    614 SCIP* scip, /**< main SCIP data structure */
    615 SCIP_Real*** bw_cont_redcost, /**< array pointer with reduced costs for continuous variables */
    616 SCIP_Real*** bw_redcost, /**< array pointer with reduced costs for (binary) variables */
    617 SCIP_Real*** bw_int_redcost, /**< array pointer with reduced costs for integer variables */
    618 int nblocks /**< number of blocks */
    619 )
    620{
    621 int b;
    622
    623 /* type-wise and blockwise freeing of reduced cost arrays */
    624 if( *bw_cont_redcost != NULL )
    625 {
    626 for( b = 0; b < nblocks + 1; b++ )
    627 {
    628 if( (*bw_cont_redcost)[b] != NULL )
    629 SCIPfreeBufferArray(scip, &((*bw_cont_redcost)[b]));
    630 }
    631
    632 SCIPfreeBufferArray(scip, bw_cont_redcost);
    633 }
    634
    635 if( *bw_redcost != NULL )
    636 {
    637 for( b = 0; b < nblocks + 1; b++ )
    638 {
    639 if( (*bw_redcost)[b] != NULL )
    640 SCIPfreeBufferArray(scip, &((*bw_redcost)[b]));
    641 }
    642
    643 SCIPfreeBufferArray(scip, bw_redcost);
    644 }
    645
    646 if( *bw_int_redcost != NULL )
    647 {
    648 for( b = 0; b < nblocks + 1; b++ )
    649 {
    650 if( (*bw_int_redcost)[b] != NULL )
    651 SCIPfreeBufferArray(scip, &((*bw_int_redcost)[b]));
    652 }
    653
    654 SCIPfreeBufferArray(scip, bw_int_redcost);
    655 }
    656
    657 return SCIP_OKAY;
    658}
    659
    660/** determines affiliation to a redcost (logsorted) bucket, avoiding inf to inf comparison */
    661static
    663 SCIP* scip, /**< SCIP data structure */
    664 SCIP_Real base, /**< the nbuckets-th-root of the shifted max red costs in current bucket */
    665 SCIP_Real redcost, /**< the reduced cost of the current variable */
    666 SCIP_Real redcostmin, /**< the minimal reduced cost of the current block for shifting */
    667 int currentindex, /**< current iteration index */
    668 int nbuckets /**< number of buckets */
    669 )
    670{
    671 /* compute the reduced cost bounds for the current interval for logarithmic sorting */
    672 SCIP_Real redcostlb = pow(base, (double)(currentindex - 1));
    673 SCIP_Real redcostub = pow(base, (double)currentindex);
    674
    675 /* shift the current reduced cost for determining the membership to the current interval */
    676 SCIP_Real shifted_redcost = redcost - redcostmin + 1.0;
    677
    678 /* check whether the current reduced cost is in (min, max] */
    679 SCIP_Bool greatermincost = SCIPisGT(scip, shifted_redcost, redcostlb);
    680 SCIP_Bool lessequalmaxcost = SCIPisLE(scip, shifted_redcost, redcostub);
    681
    682 assert(base >= 1);
    683 assert(!SCIPisInfinity(scip, base));
    684
    685 /* respecting the edge cases, return the result */
    686 if( currentindex == 1 )
    687 /* there is no minimal reduced cost to respect */
    688 return lessequalmaxcost;
    689 else if ( currentindex == nbuckets )
    690 /* there is no maximal reduced cost to respect */
    691 return greatermincost;
    692 else
    693 /* both interval bounds must be respected */
    694 return greatermincost && lessequalmaxcost;
    695}
    696
    697/** fill bucket with its variables */
    698static
    700 SCIP* scip, /**< main SCIP data structure */
    701 BUCKETLIST** bucketlist, /**< array pointer of buckets to fill */
    702 SCIP_VAR*** bw_contnonkernelvars, /**< array of continuous, non-kernel variables */
    703 SCIP_VAR*** bw_nonkernelvars, /**< array of (binary,) non-kernel variables */
    704 SCIP_VAR*** bw_intnonkernelvars, /**< array of integer, non-kernel variables */
    705 int* bw_ncontnonkernelvars, /**< blockwise number of continuous, non-kernel variables */
    706 int* bw_nnonkernelvars, /**< blockwise number of (binary,) non-kernel variables */
    707 int* bw_nintnonkernelvars, /**< blockwise number of integer, non-kernel variables */
    708 SCIP_Real** bw_cont_redcost, /**< blockwise reduced costs of continuous, non-kernel variables */
    709 SCIP_Real** bw_redcost, /**< blockwise reduced costs of (binary,) non-kernel variables */
    710 SCIP_Real** bw_int_redcost, /**< blockwise reduced costs of integer, non-kernel variables */
    711 SCIP_Bool twolevel, /**< usage of one or two level structure */
    712 SCIP_Bool redcostlogsort, /**< filling the buckets by logarithmically reduced cost sort */
    713 int nbuckets, /**< number of buckets */
    714 int nblocks /**< number of blocks */
    715 )
    716{
    717 BUCKET* bucket; /* temporary bucket */
    718 int contbucklength; /* temporary length of the continuous bucket */
    719 int bucklength; /* temporary length of the (binary) bucket */
    720 int intbucklength; /* temporary length of the integer bucket */
    721 int fromcontvars; /* temporary start index for the variables of a continuous bucket */
    722 int tocontvars; /* temporary end index for the variables of a continuous bucket */
    723 int fromvars; /* temporary start index for the variables of a (binary) bucket */
    724 int tovars; /* temporary end index for the variables of a (binary) bucket */
    725 int fromintvars; /* temporary start index for the variables of a integer bucket */
    726 int tointvars; /* temporary end index for the variables of a integer bucket */
    727 int k; /* bucket counter */
    728 int b; /* block counter */
    729 int l; /* variable counter */
    730 int j; /* temporary continuous variable counter */
    731 int n; /* temporary (binary) variable counter */
    732 int m; /* temporary integer variable counter */
    733 SCIP_Real* contbases = NULL; /* blockwise the nbuckets-th-root of the max reduced costs of cont vars */
    734 SCIP_Real* bases = NULL; /* blockwise the nbuckets-th-root of the max reduced costs of (bin) vars */
    735 SCIP_Real* intbases = NULL; /* blockwise the nbuckets-th-root of the max reduced costs of int vars */
    736
    737 assert(nbuckets > 0);
    738
    739 /* when sorting logarithmically by reduced costs, get maximum per block and its shifted nbuckets-th-root */
    740 if( redcostlogsort )
    741 {
    742 SCIP_Real tmp_max;
    743 SCIP_Real tmp_min;
    744
    745 SCIP_CALL( SCIPallocBufferArray(scip, &contbases, nblocks + 1) );
    746 SCIP_CALL( SCIPallocBufferArray(scip, &bases, nblocks + 1) );
    747 if( twolevel )
    748 SCIP_CALL( SCIPallocBufferArray(scip, &intbases, nblocks + 1) );
    749
    750 for( b = 0; b < nblocks + 1; b++ )
    751 {
    752 if( bw_ncontnonkernelvars[b] > 0 )
    753 {
    754 /* reduced costs are not supposed to be +inf or -inf */
    755 tmp_max = bw_cont_redcost[b][bw_ncontnonkernelvars[b] - 1];
    756 tmp_min = bw_cont_redcost[b][0];
    757 assert(!(SCIPisInfinity(scip, tmp_max) || SCIPisInfinity(scip, -tmp_max)));
    758 assert(!(SCIPisInfinity(scip, tmp_min) || SCIPisInfinity(scip, -tmp_min)));
    759
    760 /* compute the nbuckets-th root of (redcostmax - redcostmin + 1.0) from the sorted(!) bw_cont_redcost[b] */
    761 contbases[b] = (SCIP_Real) pow(tmp_max - tmp_min + 1.0, 1.0/nbuckets);
    762 }
    763 else
    764 /* save -1.0 as placeholder */
    765 contbases[b] = -1.0;
    766
    767 if( bw_nnonkernelvars[b] > 0 )
    768 {
    769 /* reduced costs are not supposed to be +inf or -inf */
    770 tmp_max = bw_redcost[b][bw_nnonkernelvars[b] - 1];
    771 tmp_min = bw_redcost[b][0];
    772 assert(!(SCIPisInfinity(scip, tmp_max) || SCIPisInfinity(scip, -tmp_max)));
    773 assert(!(SCIPisInfinity(scip, tmp_min) || SCIPisInfinity(scip, -tmp_min)));
    774
    775 /* compute the nbuckets-th root of (redcostmax - redcostmin + 1.0) from the sorted(!) bw_cont_redcost[b] */
    776 bases[b] = (SCIP_Real) pow(tmp_max - tmp_min + 1.0, 1.0/nbuckets);
    777 }
    778 else
    779 /* save -1.0 as placeholder */
    780 bases[b] = -1.0;
    781
    782 if( twolevel )
    783 {
    784 if( bw_nintnonkernelvars[b] > 0 )
    785 {
    786 /* reduced costs are not supposed to be +inf or -inf */
    787 tmp_max = bw_int_redcost[b][bw_nintnonkernelvars[b] - 1];
    788 tmp_min = bw_int_redcost[b][0];
    789 assert(!(SCIPisInfinity(scip, tmp_max) || SCIPisInfinity(scip, -tmp_max)));
    790 assert(!(SCIPisInfinity(scip, tmp_min) || SCIPisInfinity(scip, -tmp_min)));
    791
    792 intbases[b] = (SCIP_Real) pow(tmp_max - tmp_min + 1.0, 1.0/nbuckets);
    793 }
    794 else
    795 /* save -1.0 as placeholder */
    796 intbases[b] = -1.0;
    797 }
    798 }
    799 }
    800
    801 /* iteration over all buckets to fill, k = 0 is empty bucket by definition */
    802 for( k = 1; k < nbuckets + 1; k++ )
    803 {
    804 bucket = &(*bucketlist)->buckets[k];
    805
    806 contbucklength = 0;
    807 bucklength = 0;
    808 intbucklength = 0;
    809
    810 /* calculate the length of the variable arrays for the current bucket typewise */
    811 for( b = 0; b < nblocks + 1; b++ )
    812 {
    813 if( redcostlogsort )
    814 {
    815 /* calculation of the variable array length for each type */
    816 for( l = 0; l < bw_ncontnonkernelvars[b]; l++ )
    817 {
    818 if( isInCurrentLogBucket(scip, contbases[b], bw_cont_redcost[b][l], bw_cont_redcost[b][0], k, nbuckets) )
    819 contbucklength++;
    820 }
    821
    822 for( l = 0; l < bw_nnonkernelvars[b]; l++ )
    823 {
    824 if( isInCurrentLogBucket(scip, bases[b], bw_redcost[b][l], bw_redcost[b][0], k, nbuckets) )
    825 bucklength++;
    826 }
    827
    828 if( twolevel )
    829 {
    830 for( l = 0; l < bw_nintnonkernelvars[b]; l++ )
    831 {
    832 if( isInCurrentLogBucket(scip, intbases[b], bw_int_redcost[b][l], bw_int_redcost[b][0], k, nbuckets) )
    833 intbucklength++;
    834 }
    835 }
    836 }
    837 else
    838 {
    839 /* initialize the start/end indices to split the non-kernel vars typewise and compute the bucket length */
    840 fromcontvars = (int)SCIPceil(scip, (bw_ncontnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    841 tocontvars = (int)SCIPceil(scip, (bw_ncontnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    842 fromvars = (int)SCIPceil(scip, (bw_nnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    843 tovars = (int)SCIPceil(scip, (bw_nnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    844
    845 contbucklength += tocontvars - fromcontvars;
    846 bucklength += tovars - fromvars;
    847
    848 if( twolevel )
    849 {
    850 fromintvars = (int)SCIPceil(scip, (bw_nintnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    851 tointvars = (int)SCIPceil(scip, (bw_nintnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    852
    853 intbucklength += tointvars - fromintvars;
    854 }
    855 }
    856 }
    857
    858 /* initialize all buffer arrays for the continuous, binary/integer and (if necessary) integer bucket variables */
    859 SCIP_CALL( SCIPallocBufferArray(scip, &(bucket->contbucketvars), contbucklength) );
    860 bucket->ncontbucketvars = contbucklength;
    861 SCIP_CALL( SCIPallocBufferArray(scip, &(bucket->bucketvars), bucklength) );
    862 bucket->nbucketvars = bucklength;
    863 if( twolevel )
    864 {
    865 SCIP_CALL( SCIPallocBufferArray(scip, &(bucket->intbucketvars), intbucklength) );
    866 bucket->nintbucketvars = intbucklength;
    867 }
    868
    869 /* fill the initialized arrays with the respective variables */
    870 j = 0;
    871 n = 0;
    872 m = 0;
    873 for( b = 0; b < nblocks + 1; b++ )
    874 {
    875 if( redcostlogsort )
    876 {
    877 /* assignment of the variables to the respective bucket variable arrays for each type */
    878 for( l = 0; l < bw_ncontnonkernelvars[b]; l++ )
    879 {
    880 if( isInCurrentLogBucket(scip, contbases[b], bw_cont_redcost[b][l], bw_cont_redcost[b][0], k, nbuckets) )
    881 bucket->contbucketvars[j++] = bw_contnonkernelvars[b][l];
    882 }
    883
    884 for( l = 0; l < bw_nnonkernelvars[b]; l++ )
    885 {
    886 if( isInCurrentLogBucket(scip, bases[b], bw_redcost[b][l], bw_redcost[b][0], k, nbuckets) )
    887 bucket->bucketvars[n++] = bw_nonkernelvars[b][l];
    888 }
    889
    890 if( twolevel )
    891 {
    892 for( l = 0; l < bw_nintnonkernelvars[b]; l++ )
    893 {
    894 if( isInCurrentLogBucket(scip, intbases[b], bw_int_redcost[b][l], bw_int_redcost[b][0], k, nbuckets) )
    895 bucket->intbucketvars[m++] = bw_intnonkernelvars[b][l];
    896 }
    897 }
    898 }
    899 else
    900 {
    901 /* calculate again the necessary start and end indices to split the non-kernel variables typewise */
    902 fromcontvars = (int)SCIPceil(scip, (bw_ncontnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    903 tocontvars = (int)SCIPceil(scip, (bw_ncontnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    904 fromvars = (int)SCIPceil(scip, (bw_nnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    905 tovars = (int)SCIPceil(scip, (bw_nnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    906
    907 /* fill the variable arrays */
    908 for( l = 0; l < tocontvars - fromcontvars; l++ )
    909 bucket->contbucketvars[j++] = bw_contnonkernelvars[b][fromcontvars + l];
    910 for( l = 0; l < tovars - fromvars; l++ )
    911 bucket->bucketvars[n++] = bw_nonkernelvars[b][fromvars + l];
    912
    913 /* apply the procedure above for the integer variables if necessary */
    914 if( twolevel )
    915 {
    916 fromintvars = (int)SCIPceil(scip, (bw_nintnonkernelvars[b] / (SCIP_Real)nbuckets) * (k - 1) );
    917 tointvars = (int)SCIPceil(scip, (bw_nintnonkernelvars[b] / (SCIP_Real)nbuckets) * k );
    918
    919 for( l = 0; l < tointvars - fromintvars; l++ )
    920 bucket->intbucketvars[m++] = bw_intnonkernelvars[b][fromintvars + l];
    921 }
    922 }
    923 }
    924
    925 assert(j == contbucklength);
    926 assert(n == bucklength);
    927 if( twolevel )
    928 assert(m == intbucklength);
    929 }
    930
    931 if( redcostlogsort )
    932 {
    933 SCIPfreeBufferArray(scip, &contbases);
    934 SCIPfreeBufferArray(scip, &bases);
    935 if( twolevel )
    936 SCIPfreeBufferArray(scip, &intbases);
    937 }
    938
    939 return SCIP_OKAY;
    940}
    941
    942/** release memory of bucket arrays */
    943static
    945 SCIP* scip, /**< main SCIP data structure */
    946 BUCKET* bucket, /**< bucket to free the arrays from */
    947 SCIP_Bool twolevel /**< usage of one or two level structure */
    948 )
    949{
    950 if( bucket->contbucketvars != NULL )
    952 if( bucket->bucketvars != NULL )
    954 if( twolevel && bucket->intbucketvars != NULL )
    956
    957 return SCIP_OKAY;
    958}
    959
    960/** initialize a bucket */
    961static
    963 BUCKETLIST* bucketlist /**< bucketlist structure where the bucket belongs to */
    964 )
    965{
    966 BUCKET* bucket;
    967
    968 assert(bucketlist != NULL);
    969 assert(bucketlist->scip != NULL);
    970
    971 bucket = &bucketlist->buckets[bucketlist->nbuckets];
    972
    973 bucket->bucketlist = bucketlist;
    974 bucket->subscip = NULL;
    975 bucket->contbucketvars = NULL;
    976 bucket->bucketvars = NULL;
    977 bucket->intbucketvars = NULL;
    978 bucket->ncontbucketvars = 0;
    979 bucket->nbucketvars = 0;
    980 bucket->nintbucketvars = 0;
    981 bucket->number = bucketlist->nbuckets;
    982 bucket->twolevel = FALSE;
    983 bucket->scip2sub = NULL;
    984 bucket->sub2scip = NULL;
    985
    986 ++bucketlist->nbuckets;
    987
    988 return SCIP_OKAY;
    989}
    990
    991/** free bucket structure */
    992static
    994 SCIP* scip, /**< SCIP data structure */
    995 BUCKET* bucket /**< bucket structure to free */
    996 )
    997{
    998 assert(scip != NULL);
    999 assert(bucket != NULL);
    1000
    1001 assert(bucket->subscip != NULL);
    1002
    1003 /* free variable mappings subscip -> scip and scip -> subscip */
    1006
    1007 SCIP_CALL( SCIPfree(&bucket->subscip) );
    1008 bucket->subscip = NULL;
    1009
    1010 return SCIP_OKAY;
    1011}
    1012
    1013/** initialize the bucketlist */
    1014static
    1016 SCIP* scip, /**< SCIP data structure */
    1017 BUCKETLIST** bucketlist, /**< pointer to bucketlist */
    1018 int nbuckets /**< number of buckets */
    1019 )
    1020{
    1021 char name[SCIP_MAXSTRLEN];
    1022
    1023 assert(scip != NULL);
    1024 assert(bucketlist != NULL);
    1025
    1026 SCIP_CALL( SCIPallocBlockMemory(scip, bucketlist) );
    1027 assert(*bucketlist != NULL);
    1028
    1029 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPgetProbName(scip));
    1030
    1031 SCIPdebugMessage("initialized problem %s\n", name);
    1032
    1033 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*bucketlist)->buckets, nbuckets) );
    1034
    1035 (*bucketlist)->scip = scip;
    1036 (*bucketlist)->nbuckets = 0;
    1037
    1038 return SCIP_OKAY;
    1039}
    1040
    1041/** free bucketlist structure */
    1042static
    1044 BUCKETLIST** bucketlist, /**< pointer to bucketlist to free */
    1045 int nbuckets /**< number of buckets to free */
    1046 )
    1047{
    1048 SCIP* scip;
    1049
    1050 assert(bucketlist != NULL);
    1051 assert(*bucketlist != NULL);
    1052
    1053 scip = (*bucketlist)->scip;
    1054 assert(scip != NULL);
    1055
    1056 if( (*bucketlist)->buckets != NULL )
    1057 SCIPfreeBlockMemoryArray(scip, &(*bucketlist)->buckets, nbuckets);
    1058
    1059 SCIPfreeBlockMemory(scip, bucketlist);
    1060 *bucketlist = NULL;
    1061
    1062 return SCIP_OKAY;
    1063}
    1064
    1065/** creates the subscip for each bucket */
    1066static
    1068 BUCKET* bucket, /**< the bucket to create the subscip for */
    1069 SCIP_Bool usetransprob, /**< indicating whether the transformed or the original problem is used */
    1070 SCIP_Bool* success /**< pointer to store if the creation process was successfull */
    1071 )
    1072{
    1073 BUCKETLIST* bucketlist;
    1074 SCIP* scip;
    1075 SCIP_VAR** vars;
    1076 SCIP_VAR** subvars;
    1077 SCIP_VAR* var;
    1078 SCIP_VAR* subvar;
    1079 SCIP_HASHMAP* varsmap;
    1080 SCIP_HASHMAP* consmap;
    1081 char probname[SCIP_MAXSTRLEN];
    1082 int i;
    1083 int nvars;
    1084 int nsubvars;
    1085
    1086 SCIP_CONS** conss;
    1087 SCIP_CONS* newcons;
    1088
    1089 assert(bucket != NULL);
    1090 assert(success != NULL);
    1091
    1092 bucketlist = bucket->bucketlist;
    1093 assert(bucketlist != NULL);
    1094
    1095 scip = bucketlist->scip;
    1096 assert(scip != NULL);
    1097
    1098 /* start new creation process */
    1099 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    1100
    1101 /* initializing the subproblem */
    1102 SCIP_CALL( SCIPcreate(&bucket->subscip) );
    1103
    1104 /* create variable hash mapping scip -> subscip */
    1105 SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
    1106
    1107 (*success) = TRUE;
    1108
    1109#ifdef SCIP_DEBUG /* we print statistics later, so we need to copy statistics tables */
    1111 TRUE, FALSE, TRUE, TRUE, TRUE,
    1112 TRUE, TRUE, TRUE, TRUE, TRUE,
    1113 TRUE, TRUE, TRUE, FALSE, TRUE,
    1114 TRUE, TRUE, TRUE, TRUE, TRUE, success) );
    1115#else
    1117 TRUE, FALSE, TRUE, TRUE, TRUE,
    1118 TRUE, TRUE, TRUE, TRUE, TRUE,
    1119 TRUE, TRUE, TRUE, FALSE, FALSE,
    1120 TRUE, FALSE, FALSE, TRUE, TRUE, success) );
    1121#endif
    1122
    1123 /* copy parameter settings */
    1125
    1126 /* adapt limit settings */
    1127 SCIP_CALL( SCIPcopyLimits(scip, bucket->subscip) );
    1128
    1129 /* create problem in subscip */
    1130 /* get name of the original problem and add "dksbucket" + [bucketnumber] */
    1131 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_dksbucket%d", SCIPgetProbName(scip), bucket->number);
    1132
    1133 /* from before: avoid recursive calls */
    1135
    1136 /* copy all variables */
    1137 SCIP_CALL( SCIPcopyProb(scip, bucket->subscip, varsmap, NULL, FALSE, probname) );
    1138 SCIP_CALL( SCIPcopyVars(scip, bucket->subscip, varsmap, NULL, NULL, NULL, 0, TRUE) );
    1139
    1140 /* copy as many constraints as possible */
    1142
    1143 conss = SCIPgetConss(scip);
    1144
    1145 for( i = 0; i < SCIPgetNConss(scip); ++i )
    1146 {
    1147 /* do not check this if we use the transformed problem */
    1148 if( !usetransprob )
    1149 assert(!SCIPconsIsModifiable(conss[i]));
    1150 /* copy the constraint */
    1151 SCIP_CALL( SCIPgetConsCopy(scip, bucket->subscip, conss[i], &newcons, SCIPconsGetHdlr(conss[i]), varsmap, consmap,
    1152 NULL, SCIPconsIsInitial(conss[i]), SCIPconsIsSeparated(conss[i]), SCIPconsIsEnforced(conss[i]),
    1153 SCIPconsIsChecked(conss[i]), SCIPconsIsPropagated(conss[i]), FALSE, FALSE, SCIPconsIsDynamic(conss[i]),
    1154 SCIPconsIsRemovable(conss[i]), FALSE, FALSE, success) );
    1155
    1156 /* abort if constraint was not successfully copied */
    1157 if( !(*success) )
    1158 {
    1159 *success = FALSE;
    1160 if( newcons != NULL )
    1161 {
    1162 SCIP_CALL( SCIPreleaseCons(bucket->subscip, &newcons) );
    1163 }
    1164 SCIPhashmapFree(&varsmap);
    1165 SCIPhashmapFree(&consmap);
    1166 return SCIP_OKAY;
    1167 }
    1168
    1169 if( newcons != NULL )
    1170 {
    1171 SCIP_CALL( SCIPaddCons(bucket->subscip, newcons) );
    1172 SCIP_CALL( SCIPreleaseCons(bucket->subscip, &newcons) );
    1173 }
    1174 }
    1175
    1176 SCIPhashmapFree(&consmap);
    1177 if( !(*success) )
    1178 {
    1179 SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "In heur_dks: failed to copy some constraints, continuing\n");
    1180 SCIPdebugMsg(scip, "In heur_dks: failed to copy some constraints to subscip, continue anyway\n");
    1181 }
    1182
    1183 /* create arrays translating scip transformed vars to subscip original vars, and vice versa
    1184 * capture variables in scip and subscip
    1185 * catch global bound change events
    1186 */
    1187
    1188 SCIP_CALL( SCIPgetVarsData(bucket->subscip, &subvars, &nsubvars, NULL, NULL, NULL, NULL) );
    1189
    1190 SCIP_CALL( SCIPallocClearBufferArray(scip, &bucket->sub2scip, nsubvars) );
    1191 SCIP_CALL( SCIPallocClearBufferArray(scip, &bucket->scip2sub, nvars) );
    1192
    1193 /* iteration over varsmap to get the original and corresponding subscip variables*/
    1194 for( i = 0; i < SCIPhashmapGetNEntries(varsmap); i++ )
    1195 {
    1196 SCIP_HASHMAPENTRY* entry;
    1197 entry = SCIPhashmapGetEntry(varsmap, i);
    1198 if( entry != NULL )
    1199 {
    1200 var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
    1201 subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
    1202 assert(subvar != NULL);
    1203 assert(SCIPvarGetProbindex(subvar) >= 0);
    1204 assert(SCIPvarGetProbindex(subvar) <= nsubvars);
    1205
    1206 if( SCIPvarIsActive(var) )
    1207 {
    1208 assert(SCIPvarGetProbindex(var) <= nvars);
    1209 assert(bucket->scip2sub[SCIPvarGetProbindex(var)] == NULL);
    1210 bucket->scip2sub[SCIPvarGetProbindex(var)] = subvar;
    1211 }
    1212 assert(bucket->sub2scip[SCIPvarGetProbindex(subvar)] == NULL);
    1213 bucket->sub2scip[SCIPvarGetProbindex(subvar)] = var;
    1214 }
    1215 }
    1216
    1217#ifdef SCIP_DEBUG
    1218 for( i = 0; i < nsubvars; i++ )
    1219 {
    1220 subvar = SCIPgetVars(bucket->subscip)[i];
    1221 assert(SCIPvarGetProbindex(subvar) == i);
    1222 var = bucket->sub2scip[i];
    1223
    1226 }
    1227#endif
    1228
    1229 SCIPhashmapFree(&varsmap);
    1230
    1231 /* avoid recursive calls */
    1233
    1234 /* do not abort subproblem on CTRL-C */
    1235 SCIP_CALL( SCIPsetBoolParam(bucket->subscip, "misc/catchctrlc", FALSE) );
    1236
    1237 /* forbid recursive call of DKS heuristic on subproblems */
    1238 if( SCIPisParamFixed(bucket->subscip, "heuristics/" HEUR_NAME "/freq") )
    1239 {
    1240 SCIPwarningMessage(scip, "unfixing param heuristics/" HEUR_NAME "/freq in DKS to avoid recursive calls\n");
    1241 SCIP_CALL( SCIPunfixParam(bucket->subscip, "heuristics/" HEUR_NAME "/freq") );
    1242 }
    1243 SCIP_CALL( SCIPsetIntParam(bucket->subscip, "heuristics/" HEUR_NAME "/freq", -1) );
    1244
    1245#ifdef SCIP_DEBUG
    1246 /* for debugging, enable full output */
    1247 SCIP_CALL( SCIPsetIntParam(bucket->subscip, "display/verblevel", 5) );
    1248 SCIP_CALL( SCIPsetIntParam(bucket->subscip, "display/freq", 100000000) );
    1249#else
    1250 /* disable statistic timing inside sub SCIP and output to console */
    1251 SCIP_CALL( SCIPsetIntParam(bucket->subscip, "display/verblevel", 0) );
    1252 SCIP_CALL( SCIPsetBoolParam(bucket->subscip, "timing/statistictiming", FALSE) );
    1253#endif
    1254
    1255 SCIPdebugMsg(scip, "created subscip of bucket %d\n", bucket->number);
    1256
    1257 return SCIP_OKAY;
    1258}
    1259
    1260/** create bucketlist and initialize buckets */
    1261static
    1263 SCIP* scip, /**< SCIP data structure */
    1264 SCIP_Bool usetransprob, /**< indication whether to use the transformed problem (or the original) */
    1265 int nbuckets, /**< number of buckets (without kernel only) */
    1266 BUCKETLIST** bucketlist, /**< pointer to store bucketlist structure */
    1267 SCIP_Bool* success /**< pointer to store if the creation process was successfull */
    1268 )
    1269{
    1270 BUCKET* bucket;
    1271 int b;
    1272
    1273 bucket = NULL;
    1274 *success = TRUE;
    1275
    1276 /* init bucketlist data structure with nbucket + 1 because the initial bucket with kernel vars is included */
    1277 SCIP_CALL( initBucketlist(scip, bucketlist, nbuckets + 1) );
    1278 assert((*bucketlist)->buckets != NULL);
    1279
    1280 /* loop over all buckets and the initial "kernel"bucket */
    1281 for( b = 0; b < nbuckets + 1; b++ )
    1282 {
    1283 SCIP_CALL( initBucket(*bucketlist) );
    1284 assert((*bucketlist)->nbuckets == b + 1);
    1285
    1286 bucket = &(*bucketlist)->buckets[b];
    1287
    1288 /* build subscip for bucket */
    1289 SCIP_CALL( bucketCreateSubscip(bucket, usetransprob, success) );
    1290
    1291 if( !(*success) )
    1292 return SCIP_OKAY;
    1293 }
    1294 assert(nbuckets + 1 == (*bucketlist)->nbuckets);
    1295
    1296 return SCIP_OKAY;
    1297}
    1298
    1299/** search variable in kernel and bucket */
    1300static
    1302 BUCKET* bucket, /**< bucket to be solved next */
    1303 SCIP_VAR** contkernelvars, /**< continuous variables in the latest kernel */
    1304 int ncontkernelvars, /**< amount of continuous variables in the latest kernel */
    1305 SCIP_VAR** kernelvars, /**< variables in the kernel */
    1306 int nkernelvars, /**< amount of variables in the kernel */
    1307 SCIP_VAR** intkernelvars, /**< variables in the integer kernel, if 2-level buckets are present */
    1308 int nintkernelvars, /**< amount of variables in the integer kernel */
    1309 SCIP_VAR* var, /**< variable to search for in the kernel/buckets */
    1310 SCIP_Bool* found /**< is the variable present in the current bucket or the kernel? */
    1311 )
    1312{
    1313 int j;
    1314
    1315 *found = FALSE;
    1316
    1317 /* search in the current continuous kernel for the given variable */
    1319 {
    1320 for( j = 0; j < ncontkernelvars; j++ )
    1321 {
    1322 if( contkernelvars[j] != NULL && var == contkernelvars[j] )
    1323 {
    1324 *found = TRUE;
    1325 return SCIP_OKAY;
    1326 }
    1327 }
    1328
    1329 /* search for the current variable in the continuous bucket variables */
    1330 for( j = 0; j < bucket->ncontbucketvars; j++ )
    1331 {
    1332 if( var == bucket->contbucketvars[j] )
    1333 {
    1334 *found = TRUE;
    1335 return SCIP_OKAY;
    1336 }
    1337 }
    1338 }
    1339
    1340 /* search in the current (binary) kernel for the variable */
    1341 for( j = 0; j < nkernelvars; j++ )
    1342 {
    1343 if( kernelvars[j] != NULL && var == kernelvars[j] )
    1344 {
    1345 *found = TRUE;
    1346 return SCIP_OKAY;
    1347 }
    1348 }
    1349
    1350 /* if 2-level buckets are used, also search for the current variable in the integer kernel */
    1351 for( j = 0; j < nintkernelvars; j++ )
    1352 {
    1353 if( intkernelvars[j] != NULL && var == intkernelvars[j] )
    1354 {
    1355 *found = TRUE;
    1356 return SCIP_OKAY;
    1357 }
    1358 }
    1359
    1360 /* search for the current variable in the (binary) bucket variables */
    1361 for( j = 0; j < bucket->nbucketvars; j++ )
    1362 {
    1363 if( var == bucket->bucketvars[j] )
    1364 {
    1365 *found = TRUE;
    1366 return SCIP_OKAY;
    1367 }
    1368 }
    1369
    1370 /* if 2-level buckets are used, also search for the current variable in the integer bucket variables */
    1371 for( j = 0; j < bucket->nintbucketvars; j++ )
    1372 {
    1373 if( var == bucket->intbucketvars[j] )
    1374 {
    1375 *found = TRUE;
    1376 return SCIP_OKAY;
    1377 }
    1378 }
    1379
    1380 return SCIP_OKAY;
    1381}
    1382
    1383/** adjust the kernel variables */
    1384static
    1386 SCIP* scip, /**< current scip */
    1387 BUCKET* bucket, /**< bucket that was solved last */
    1388 SCIP_VAR*** contkernelvars, /**< cont. kernelvars to adjust */
    1389 int* ncontkernelvars, /**< amount of cont. kernelvars */
    1390 int maxcontkernelsize, /**< maximal size of the continuous kernel */
    1391 SCIP_VAR*** kernelvars, /**< kernelvars to adjust */
    1392 int* nkernelvars, /**< amount of kernelvars */
    1393 int maxkernelsize, /**< maximal size of the kernel */
    1394 SCIP_VAR*** intkernelvars, /**< integer kernelvars to adjust */
    1395 int* nintkernelvars, /**< amount of integer kernelvars */
    1396 int maxintkernelsize, /**< maximal size of the integer kernel */
    1397 SCIP_Bool twolevel /**< is a twolevel structure necessary */
    1398 )
    1399{
    1400 SCIP_VAR** contkvars; /* temporary storage for the continuous kernel variables */
    1401 SCIP_VAR** kvars; /* temporary storage for the (binary/integer) kernel variables */
    1402 SCIP_VAR** intkvars; /* temporary storage for the integer kernel variables */
    1403 SCIP_VAR *var; /* temporary variable */
    1404 SCIP_Real val; /* variable value in solution */
    1405 SCIP_Real lb; /* variable lower bound */
    1406 SCIP_SOL* solution; /* solution of the current bucket */
    1407 int nnewcontkernelvars; /* number of new continuous kernel variables */
    1408 int nnewkernelvars; /* number of new (binary/integer) kernel variables */
    1409 int nnewintkernelvars; /* number of new integer kernel variables */
    1410 int n; /* temporary variable counter */
    1411
    1412 /* definition of old kernel arrays to update the actual ones live */
    1413 contkvars = *contkernelvars;
    1414 kvars = *kernelvars;
    1415 intkvars = *intkernelvars;
    1416
    1417 solution = SCIPgetBestSol(bucket->subscip);
    1418
    1419 /* deletion of variables from the kernel */
    1420 /* continuous kernelvariables with value equal to zero or their lb get deleted from the kernel */
    1421 /* todo: after x tries, maybe with seperate kernelindexarray */
    1422 nnewintkernelvars = 0;
    1423 nnewcontkernelvars = 0;
    1424 for( n = 0; n < *ncontkernelvars; n++ )
    1425 {
    1426 if( contkvars[n] == NULL )
    1427 continue;
    1428
    1429 /* get the value of the current variable and its lower bound */
    1430 if( SCIPvarIsActive(contkvars[n]) )
    1431 {
    1432 assert(SCIPvarGetProbindex(contkvars[n]) <= SCIPgetNVars(scip));
    1433 var = bucket->scip2sub[SCIPvarGetProbindex(contkvars[n])];
    1434
    1435 if( var != NULL )
    1436 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1437 else
    1438 continue;
    1439 }
    1440 else
    1441 continue;
    1442
    1443 lb = SCIPvarGetLbLocal(contkvars[n]);
    1444
    1445 /* if deviating from lb and zero, re-add into current kernel vars */
    1446 if( (!SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb)) )
    1447 (*contkernelvars)[nnewcontkernelvars++] = contkvars[n];
    1448 /* otherwise, delete it */
    1449 else
    1450 contkvars[n] = NULL;
    1451 }
    1452
    1453 /* dependent on #levels, check the solution value of the bin/int value to be unequal to 0 and/or its lb */
    1454 nnewkernelvars = 0;
    1455 for( n = 0; n < *nkernelvars; n++ )
    1456 {
    1457 if( kvars[n] == NULL )
    1458 continue;
    1459
    1460 /* get the value of the current kernel variable in the solution and its lower bound */
    1461 if( SCIPvarIsActive(kvars[n]) )
    1462 {
    1463 assert(SCIPvarGetProbindex(kvars[n]) <= SCIPgetNVars(scip));
    1464 var = bucket->scip2sub[SCIPvarGetProbindex(kvars[n])];
    1465 if( var != NULL )
    1466 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1467 else
    1468 continue;
    1469 }
    1470 else
    1471 continue;
    1472
    1473 lb = SCIPvarGetLbLocal(kvars[n]);
    1474
    1475 /* if two-level structure is required, the binary case occurs and only deviation to 0 has to be checked */
    1476 if( (twolevel && !SCIPisEQ(scip, val, 0.0)) )
    1477 (*kernelvars)[nnewkernelvars++] = kvars[n];
    1478 /* if one-level case, the variable has to deviate from 0 and its lb */
    1479 else if( (!twolevel && !SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb)) )
    1480 (*kernelvars)[nnewkernelvars++] = kvars[n];
    1481 /* otherwise delete the variable from its current position in the kernel */
    1482 else
    1483 kvars[n] = NULL;
    1484 }
    1485
    1486 /* if necessary check the relevance of pure integer variables in the current kernel */
    1487 if( twolevel )
    1488 {
    1489 nnewintkernelvars = 0;
    1490
    1491 for( n = 0; n < *nintkernelvars; n++ )
    1492 {
    1493 if( intkvars[n] == NULL )
    1494 continue;
    1495
    1496 /* get the value of the current variable in the solution and its lower bound */
    1497 if( SCIPvarIsActive(intkvars[n]) )
    1498 {
    1499 assert(SCIPvarGetProbindex(intkvars[n]) <= SCIPgetNVars(scip));
    1500 var = bucket->scip2sub[SCIPvarGetProbindex(intkvars[n])];
    1501
    1502 if( var != NULL )
    1503 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1504 else
    1505 continue;
    1506 }
    1507 else
    1508 continue;
    1509
    1510 lb = SCIPvarGetLbLocal(intkvars[n]);
    1511
    1512 /* if variable value is unequal to 0 and its lower bound, it is re-added into the kernel */
    1513 if( (!SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb)) )
    1514 (*intkernelvars)[nnewintkernelvars++] = intkvars[n];
    1515 else
    1516 intkvars[n] = NULL;
    1517 }
    1518 }
    1519
    1520 /* addition of new variables from the bucket to the kernel */
    1521
    1522 /* add continuous bucket variables with suitable values to the kernel */
    1523 for( n = 0; n < bucket->ncontbucketvars; n++ )
    1524 {
    1525 if( bucket->contbucketvars[n] == NULL )
    1526 continue;
    1527
    1528 if( SCIPvarIsActive(bucket->contbucketvars[n]) )
    1529 {
    1530 assert(SCIPvarGetProbindex(bucket->contbucketvars[n]) <= SCIPgetNVars(scip));
    1531 var = bucket->scip2sub[SCIPvarGetProbindex(bucket->contbucketvars[n])];
    1532
    1533 if( var != NULL )
    1534 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1535 else
    1536 continue;
    1537 }
    1538 else
    1539 continue;
    1540
    1541 lb = SCIPvarGetLbLocal(bucket->contbucketvars[n]);
    1542
    1543 /* if the solution value of the bucket var != zero and != its lb, add it to the cont kernel vars */
    1544 if( !SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb) )
    1545 {
    1546 if( SCIPisGT(scip, (SCIP_Real)nnewcontkernelvars, (SCIP_Real)maxcontkernelsize) )
    1547 break;
    1548 else
    1549 (*contkernelvars)[nnewcontkernelvars++] = bucket->contbucketvars[n];
    1550 }
    1551 }
    1552
    1553 /* the size of the continuous kernel might be different -> change it */
    1554 *ncontkernelvars = nnewcontkernelvars;
    1555
    1556 /* add binary/integer bucketvariables with suitable values to the kernel */
    1557 for( n = 0; n < bucket->nbucketvars; n++ )
    1558 {
    1559 if( bucket->bucketvars[n] == NULL )
    1560 continue;
    1561
    1562 if( SCIPvarIsActive(bucket->bucketvars[n]) )
    1563 {
    1564 assert(SCIPvarGetProbindex(bucket->bucketvars[n]) <= SCIPgetNVars(scip));
    1565 var = bucket->scip2sub[SCIPvarGetProbindex(bucket->bucketvars[n])];
    1566 if( var != NULL )
    1567 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1568 else
    1569 continue;
    1570 }
    1571 else
    1572 continue;
    1573
    1574 lb = SCIPvarGetLbLocal(bucket->bucketvars[n]);
    1575
    1576 /* if bucket var != zero and != its lower bound (in epsilon), try adding it to the kernel vars */
    1577 if( twolevel && !SCIPisEQ(scip, val, 0.0) )
    1578 {
    1579 if( SCIPisGT(scip, (SCIP_Real)nnewkernelvars, (SCIP_Real)maxkernelsize) )
    1580 break;
    1581 else
    1582 (*kernelvars)[nnewkernelvars++] = bucket->bucketvars[n];
    1583 }
    1584 /* if one-level case, the variable has to deviate from 0 and its lb */
    1585 else if( !twolevel && !SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb) )
    1586 {
    1587 if( SCIPisGT(scip, (SCIP_Real)nnewkernelvars, (SCIP_Real)maxkernelsize) )
    1588 break; /* @potential todo: if kernel is "full", find a suitable variable to delete or extend kernel */
    1589 else
    1590 (*kernelvars)[nnewkernelvars++] = bucket->bucketvars[n];
    1591 }
    1592 }
    1593
    1594 /* the size of the kernel might be different, so change it */
    1595 *nkernelvars = nnewkernelvars;
    1596
    1597 /* if necessary, add integer bucket variables with suitable values to the integer kernel */
    1598 if( twolevel )
    1599 {
    1600 for( n = 0; n < bucket->nintbucketvars; n++ )
    1601 {
    1602 if( bucket->intbucketvars[n] == NULL )
    1603 continue;
    1604
    1605 if( SCIPvarIsActive(bucket->intbucketvars[n]) )
    1606 {
    1607 assert(SCIPvarGetProbindex(bucket->intbucketvars[n]) <= SCIPgetNVars(scip));
    1608 var = bucket->scip2sub[SCIPvarGetProbindex(bucket->intbucketvars[n])];
    1609 if( var != NULL )
    1610 val = SCIPgetSolVal(bucket->subscip, solution, var);
    1611 else
    1612 continue;
    1613 }
    1614 else
    1615 continue;
    1616
    1617 lb = SCIPvarGetLbLocal(bucket->intbucketvars[n]);
    1618
    1619 /* if the bucket variable's value is unequal to zero and its lb, try adding it to the integer kernel */
    1620 if( !SCIPisEQ(scip, val, 0.0) && !SCIPisEQ(scip, val, lb) )
    1621 {
    1622 if( SCIPisGT(scip, (SCIP_Real)nnewintkernelvars, (SCIP_Real)maxintkernelsize) )
    1623 break;
    1624 else
    1625 (*intkernelvars)[nnewintkernelvars++] = bucket->intbucketvars[n];
    1626 }
    1627 }
    1628 /* if the size of the kernel is different, change it */
    1629 *nintkernelvars = nnewintkernelvars;
    1630 }
    1631
    1632 return SCIP_OKAY;
    1633}
    1634
    1635/** add usuage constraint */
    1636static
    1638 BUCKET* bucket /**< current bucket to look at */
    1639 )
    1640{
    1641 SCIP_CONS* constraint;
    1642 SCIP_VAR** subvars;
    1643 SCIP_VAR *var;
    1644 char consname[SCIP_MAXSTRLEN];
    1645 SCIP_Real* coeffs;
    1646 SCIP_Real rhs;
    1647 SCIP_Real lb;
    1648 int n;
    1649 int k;
    1650
    1651 /* add an array to store the binary and integer variables of the constraint to add separatly */
    1652 SCIP_CALL( SCIPallocBufferArray(bucket->subscip, &subvars, bucket->nbucketvars + bucket->nintbucketvars) );
    1653
    1654 /* add an array for the coefficients of the binary and integer variables in the constraint */
    1655 SCIP_CALL( SCIPallocBufferArray(bucket->subscip, &coeffs, bucket->nbucketvars + bucket->nintbucketvars) );
    1656
    1657 /* for all (binary/integer) variables in the current bucket add the variables to the subvars and add coeff -1 */
    1658 k = 0;
    1659 rhs = -1.0;
    1660 for( n = 0; n < bucket->nbucketvars ; n++ )
    1661 {
    1662 if( bucket->bucketvars[n] == NULL )
    1663 continue;
    1664 if( SCIPvarIsActive(bucket->bucketvars[n]) )
    1665 var = bucket->scip2sub[SCIPvarGetProbindex(bucket->bucketvars[n])];
    1666 else
    1667 var = NULL;
    1668
    1669 if( var != NULL )
    1670 {
    1671 lb = SCIPvarGetLbLocal(bucket->bucketvars[n]);
    1672
    1673 /* skip variables with infinite lower bound, since subtraction is not reasonable */
    1674 /**@todo optionally take the upper bound if finite and add with coefficient +1 to bound away from the ub */
    1675 if( SCIPisInfinity(bucket->subscip, -lb) )
    1676 continue;
    1677
    1678 subvars[k] = var;
    1679 coeffs[k++] = -1.0; /* constraint: (sum of x_i >= 1) iff (-1 * sum of x_1 <= -1) */
    1680
    1681 /* if the variable has a positive lower bound, it is substracted from the rhs of the constraint */
    1682 rhs -= lb;
    1683 }
    1684 }
    1685
    1686 for( n = 0; n < bucket->nintbucketvars; n++ )
    1687 {
    1688 if( bucket->intbucketvars[n] == NULL )
    1689 continue;
    1690 if( SCIPvarIsActive(bucket->intbucketvars[n]) )
    1691 var = bucket->scip2sub[SCIPvarGetProbindex(bucket->intbucketvars[n])];
    1692 else
    1693 var = NULL;
    1694
    1695 if( var != NULL )
    1696 {
    1697 lb = SCIPvarGetLbLocal(bucket->intbucketvars[n]);
    1698
    1699 /* skip variables with infinite lower bound, since subtraction is not reasonable */
    1700 /**@todo optionally take the upper bound if finite and add with coefficient +1 to bound away from the ub */
    1701 if( SCIPisInfinity(bucket->subscip, -lb) )
    1702 continue;
    1703
    1704 subvars[k] = var;
    1705 coeffs[k++] = -1.0;
    1706
    1707 /* if the integer variable has a positive lower bound, it is added to the rhs of the new constraint */
    1708 rhs -= lb;
    1709 }
    1710 }
    1711
    1712 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "useconstraint_bucket_%d", bucket->number);
    1713
    1714 /* add the constraint: (-1 * sum of bucket variables <= - sum of lbs - 1) s.t. at least 1 of these vars is nonzero */
    1715 SCIP_CALL( SCIPcreateConsBasicLinear(bucket->subscip, &constraint, consname, k, subvars, coeffs, -SCIPinfinity(bucket->subscip), rhs) );
    1716 SCIP_CALL( SCIPaddCons(bucket->subscip, constraint) );
    1717 SCIP_CALL( SCIPreleaseCons(bucket->subscip, &constraint) );
    1718
    1719 /* free the arrays */
    1720 if( subvars != NULL )
    1721 SCIPfreeBufferArray(bucket->subscip, &subvars);
    1722
    1723 if( coeffs != NULL )
    1724 SCIPfreeBufferArray(bucket->subscip, &coeffs);
    1725
    1726 return SCIP_OKAY;
    1727}
    1728
    1729/*
    1730 * Callback methods of primal heuristic
    1731 */
    1732
    1733/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    1734static
    1736{ /*lint --e{715}*/
    1737 assert(scip != NULL);
    1738 assert(heur != NULL);
    1739 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1740
    1741 /* call inclusion method of primal heuristic */
    1743
    1744 return SCIP_OKAY;
    1745}
    1746
    1747
    1748/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    1749static
    1751{ /*lint --e{715}*/
    1752 SCIP_HEURDATA* heurdata;
    1753
    1754 assert(heur != NULL);
    1755 assert(scip != NULL);
    1756
    1757 heurdata = SCIPheurGetData(heur);
    1758 assert(heurdata != NULL);
    1759
    1760 SCIPfreeBlockMemory(scip, &heurdata);
    1761 SCIPheurSetData(heur, NULL);
    1762
    1763 return SCIP_OKAY;
    1764}
    1765
    1766/** execution method of primal heuristic */
    1767static
    1769{ /*lint --e{715}*/
    1770 SCIP_HEURDATA* heurdata;
    1771 SCIP_DECOMP** alldecomps;
    1772 SCIP_DECOMP* decomp = NULL;
    1773 SCIP_HASHMAP* lbvarmap = NULL; /* variable map connecting transformed vars to their original lower bd */
    1774 SCIP_CONSHDLR* conshdlr; /* constraint handler to check for indicator constraints */
    1775 SCIP_VAR*** bw_contkernelvars = NULL;
    1776 SCIP_VAR*** bw_contnonkernelvars = NULL;
    1777 SCIP_VAR*** bw_kernelvars = NULL;
    1778 SCIP_VAR*** bw_nonkernelvars = NULL;
    1779 SCIP_VAR*** bw_intkernelvars = NULL;
    1780 SCIP_VAR*** bw_intnonkernelvars = NULL;
    1781 SCIP_VAR** vars = NULL;
    1782 SCIP_VAR** contkernelvars = NULL;
    1783 SCIP_VAR** contnonkernelvars = NULL;
    1784 SCIP_VAR** kernelvars = NULL; /* just the bin kernel vars if problem includes bin AND int vars */
    1785 SCIP_VAR** nonkernelvars = NULL; /* just the bin non kernel vars if problem includes bin AND int vars */
    1786 SCIP_VAR** intkernelvars = NULL; /* used if problem includes binary AND integer variables */
    1787 SCIP_VAR** intnonkernelvars = NULL; /* used if problem includes binary AND integer variables */
    1788 SCIP_VAR** binintvars = NULL;
    1789 SCIP_CONS** conss = NULL;
    1790 SCIP_CONS** bucketconss = NULL;
    1791 SCIP_Real gapfactor;
    1792 SCIP_Real maxcontkernelsize;
    1793 SCIP_Real maxcontnonkernelsize;
    1794 SCIP_Real maxkernelsize;
    1795 SCIP_Real maxnonkernelsize;
    1796 SCIP_Real maxintkernelsize; /* used if problem includes binary AND integer variables */
    1797 SCIP_Real maxintnonkernelsize;
    1798 SCIP_Real memory;
    1799 SCIP_Real bestlocval;
    1800 SCIP_Real mipgap;
    1801 SCIP_Real linkscore;
    1802 SCIP_Real** bw_cont_redcost = NULL;
    1803 SCIP_Real** bw_redcost = NULL;
    1804 SCIP_Real** bw_int_redcost = NULL;
    1805 SCIP_STATUS status;
    1806 SCIP_Bool success;
    1807 SCIP_Bool twolevel; /* clarifying if two level buckets are used */
    1808 SCIP_Bool usebestsol;
    1809 SCIP_SOL* bestcurrsol = NULL;
    1810 BUCKETLIST* bucketlist = NULL;
    1811 BUCKET* bucket;
    1812 int* varlabels = NULL;
    1813 int* conslabels = NULL;
    1814 int* block2index = NULL;
    1815 int* blocklabels = NULL;
    1816 int* bw_ncontkernelvars = NULL;
    1817 int* bw_ncontnonkernelvars = NULL;
    1818 int* bw_nkernelvars = NULL;
    1819 int* bw_nnonkernelvars = NULL;
    1820 int* bw_nintkernelvars = NULL;
    1821 int* bw_nintnonkernelvars = NULL;
    1822 int* bw_contkernelcount = NULL;
    1823 int* bw_contnonkernelcount = NULL;
    1824 int* bw_kernelcount = NULL;
    1825 int* bw_nonkernelcount = NULL;
    1826 int* bw_intkernelcount = NULL;
    1827 int* bw_intnonkernelcount = NULL;
    1828 SCIP_Longint nodesleft;
    1830 int gapcall;
    1831 int blklbl_offset;
    1832 int nblocks;
    1833 int ndecomps;
    1834 int nvars;
    1835 int ncontkernelvars;
    1836 int ncontnonkernelvars;
    1837 int nkernelvars;
    1838 int nnonkernelvars;
    1839 int nintkernelvars;
    1840 int nintnonkernelvars;
    1841 int ncontvars;
    1842 int nbinvars;
    1843 int nintvars;
    1844 int nbuckets;
    1845 int nconss;
    1846 int nbestbucket;
    1847 int nusedratios;
    1848 int nblocklabels;
    1849 int iters;
    1850 int b;
    1851 int i;
    1852 int j;
    1853 int k;
    1854 int l;
    1855 int m;
    1856 int n;
    1857
    1858 assert(scip != NULL);
    1859 assert(heur != NULL);
    1860 assert(result != NULL);
    1861
    1862 heurdata = SCIPheurGetData(heur);
    1863 assert(heurdata != NULL);
    1864
    1865 *result = SCIP_DIDNOTRUN;
    1866
    1867 bestlocval = SCIPinfinity(scip);
    1868 twolevel = FALSE;
    1869 success = TRUE;
    1870
    1871 gapfactor = 1.0;
    1872 gapcall = 0;
    1873 blklbl_offset = 0;
    1874 ndecomps = 0;
    1875 nvars = 0;
    1876 ncontkernelvars = 0;
    1877 ncontnonkernelvars = 0;
    1878 nkernelvars = 0;
    1879 nnonkernelvars = 0;
    1880 nintkernelvars = 0;
    1881 nintnonkernelvars = 0;
    1882 ncontvars = 0;
    1883 nbinvars = 0;
    1884 nintvars = 0;
    1885 nbestbucket = -1;
    1886 iters = 0;
    1887 nblocklabels = 0;
    1888
    1889#ifdef DKS_WRITE_PROBLEMS
    1890 SCIP_CALL( SCIPwriteOrigProblem(scip, "orig_problem.lp", NULL, FALSE) );
    1891 SCIP_CALL( SCIPwriteTransProblem(scip, "trans_problem.lp", NULL, FALSE) );
    1892#endif
    1893
    1894 /* exit DKS whenever indicator constraints are present as they can not handle fixed variables */
    1895 conshdlr = SCIPfindConshdlr(scip, "indicator");
    1896 if( conshdlr != NULL && SCIPconshdlrGetNConss(conshdlr) > 0 )
    1897 return SCIP_OKAY;
    1898
    1899 /* exit DKS whenever there is not even an LP solution */
    1901 return SCIP_OKAY;
    1902
    1903 /* do not run heuristic if it was not successful in previous calls */
    1904 if( heurdata->uselesscall )
    1905 return SCIP_OKAY;
    1906
    1907 heurdata->ncalls++;
    1908
    1909 /* extract variables, constraints and number of constraints */
    1910 if( heurdata->usetransprob )
    1911 {
    1912 SCIP_VAR* tempvar = NULL; /* the transformed variable to each original variable */
    1913
    1914 /* Extract the decompositions of the transformed problem */
    1915 SCIPgetDecomps(scip, &alldecomps, &ndecomps, FALSE);
    1916
    1917 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, &ncontvars) );
    1918
    1919 /* create and initialize the hashmap for the original lower bounds */
    1920 SCIP_CALL( SCIPhashmapCreate(&lbvarmap, SCIPblkmem(scip), nvars) );
    1921 for( i = 0; i < nvars; i++ )
    1922 {
    1923 SCIP_Real scalar;
    1924 SCIP_Real constant;
    1925 tempvar = vars[i];
    1926
    1927 SCIP_CALL( SCIPvarGetOrigvarSum(&tempvar, &scalar, &constant) );
    1928
    1929 if( tempvar != NULL )
    1930 SCIP_CALL( SCIPhashmapSetImageReal(lbvarmap, vars[i], SCIPvarGetLbOriginal(tempvar)) );
    1931 }
    1932
    1933 /* initialize the constraints of the transformed problem */
    1934 nconss = SCIPgetNConss(scip);
    1935 conss = SCIPgetConss(scip);
    1936 }
    1937 else
    1938 {
    1939 /* extract the decompositions of the original problem */
    1940 SCIPgetDecomps(scip, &alldecomps, &ndecomps, TRUE);
    1941
    1942 /* get variable data like amount of integers, binaries, overall and the variables */
    1943 SCIP_CALL( SCIPgetOrigVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, &ncontvars) );
    1944
    1945 /* it is necessary to take the original variables here! otherwise they cant be used later on */
    1946 vars = SCIPgetOrigVars(scip);
    1947 nconss = SCIPgetNOrigConss(scip);
    1948 conss = SCIPgetOrigConss(scip);
    1949 }
    1950
    1951 if( ndecomps > 0 && heurdata->usedecomp )
    1952 {
    1953 /* take the first decomposition */
    1954 decomp = alldecomps[0];
    1955 SCIPdebugMsg(scip, "First original decomposition is selected\n");
    1956 assert(decomp != NULL);
    1957
    1958 nblocks = SCIPdecompGetNBlocks(decomp);
    1959 }
    1960 else
    1961 {
    1962 SCIPdebugMsg(scip, "No decompositions available or wanted, going ahead without decomp\n");
    1963 ndecomps = 0; /* set to 0 for later unnecessary ifs */
    1964 nblocks = 0; /* 0 means no decomp in use */
    1965 }
    1966
    1967 /* if problem has no constraints or no variables, terminate */
    1968 if( nvars == 0 || nconss == 0 )
    1969 {
    1970 SCIPdebugMsg(scip, "problem has no constraints or variables\n");
    1971 goto TERMINATE;
    1972 }
    1973
    1974 /* verify if the heuristic should be used only for problems with bin vars or for problems with excl bin + int vars */
    1975 if( heurdata->runbinprobsonly )
    1976 {
    1977 if( nbinvars == 0 || ncontvars > 0 )
    1978 {
    1979 SCIPdebugMsg(scip, "do not run dks if continuous variables or only integer variables are present\n");
    1980 goto TERMINATE;
    1981 }
    1982 }
    1983
    1984 /* estimate required memory and terminate if not enough memory is available */
    1985 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memory) );
    1986 if( (SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip)) / 1048576.0 >= memory )
    1987 {
    1988 SCIPdebugMsg(scip, "The estimated memory usage is too large.\n");
    1989 goto TERMINATE;
    1990 }
    1991
    1992 SCIP_CALL( SCIPallocBufferArray(scip, &varlabels, nvars) );
    1993 SCIP_CALL( SCIPallocBufferArray(scip, &conslabels, nconss) );
    1994
    1995 if( ndecomps > 0 && heurdata->usedecomp )
    1996 {
    1997 /* extract the varlabels to identify linking variables */
    1998 SCIPdecompGetVarsLabels(decomp, vars, varlabels, nvars);
    1999 SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
    2000
    2001 /* prepare the distinct finding of blocklabels */
    2002 SCIP_CALL( SCIPallocBufferArray(scip, &blocklabels, nblocks) );
    2003
    2004 /* check if linking score of the instance is sufficiently low to get called */
    2005 SCIP_CALL( getLinkingScoreAndBlocklabels(blocklabels, varlabels, conslabels, &linkscore, &nblocklabels,
    2006 nblocks, nvars, nconss) );
    2007 if( linkscore > heurdata->maxlinkscore )
    2008 {
    2009 SCIPdebugMsg(scip, "decomposition has not required linking score\n");
    2010 goto TERMINATE;
    2011 }
    2012
    2013 if( nblocklabels > 0 )
    2014 {
    2015 SCIPsortInt(blocklabels, nblocklabels);
    2016
    2017 /* if it exists the blocklabel 0, we have to add an offset of 1 to store the linking variables at 0 */
    2018 if( blocklabels[0] == 0 )
    2019 blklbl_offset = 1;
    2020
    2021 /* fill the mapping of blocklabels to blockindices */
    2022 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, blocklabels[nblocklabels - 1] + 1 + blklbl_offset) );
    2023 }
    2024 else
    2025 {
    2026 assert(nblocks == 0);
    2027 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, 1) );
    2028 }
    2029
    2030 block2index[0] = 0; /* SCIP_DECOMP_LINKVAR = -1, but are saved at index 0 */
    2031 for( b = 0; b < nblocklabels; b++ )
    2032 block2index[blocklabels[b] + blklbl_offset] = b + 1;
    2033 }
    2034 else
    2035 {
    2036 /* initialize dummy varlabels to avoid further distinctions in the following code*/
    2037 int v;
    2038
    2039 for( v = 0; v < nvars; v++ )
    2040 varlabels[v] = 0;
    2041
    2042 /* fill the mapping of blocklabels 0 to blockindices 0; nblocks = 0 in this case */
    2043 assert(nblocks == 0);
    2044 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, 1) );
    2045 block2index[0] = 0;
    2046 }
    2047
    2048 /* if necessary store the current best solution for later use */
    2049 usebestsol = heurdata->usebestsol;
    2050 if( heurdata->usebestsol )
    2051 {
    2052 if( SCIPgetNSols(scip) > 1 )
    2053 bestcurrsol = SCIPgetBestSol(scip);
    2054 else
    2055 usebestsol = FALSE;
    2056 }
    2057
    2058 /* initialize a kernel variable counter and a non kernel variable counter for each block + linking block (="+ 1") */
    2059 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_ncontkernelvars, nblocks + 1) );
    2060 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_ncontnonkernelvars, nblocks + 1) );
    2061 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nkernelvars, nblocks + 1) );
    2062 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nnonkernelvars, nblocks + 1) );
    2063
    2064 /* if there are either integer variables or binary variables only, just consider these */
    2065 if( nbinvars == 0 || nintvars == 0 || !heurdata->usetwolevel )
    2066 {
    2067 SCIP_CALL( countKernelVariables(scip, vars, bestcurrsol, lbvarmap,
    2068 twolevel, usebestsol, heurdata->usetransprob, heurdata->translbkernel,
    2069 bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars, NULL, NULL,
    2070 &ncontkernelvars, &ncontnonkernelvars, &nkernelvars, &nnonkernelvars, NULL, NULL,
    2071 block2index, varlabels, blklbl_offset, nvars) );
    2072
    2073 SCIPdebugMsg(scip, "%d initial kernel variables\n", nkernelvars);
    2074
    2075 /* if every variable is zero or its lower bound in the lp solution, terminate */
    2076 if( nkernelvars == 0 )
    2077 {
    2078 SCIPdebugMsg(scip, "No suitable variables for dks found. Leaving heuristic. \n");
    2079 goto TERMINATE;
    2080 }
    2081 else if( nkernelvars > nnonkernelvars )
    2082 /* @possible todo: if kernel vars >> nonkernel vars or >x% of all integer/binary variables => adjust */
    2083 SCIPdebugMsg(scip, "There are more kernel variables than not in the kernel\n");
    2084 }
    2085 else
    2086 {
    2087 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nintkernelvars, nblocks + 1) );
    2088 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nintnonkernelvars, nblocks + 1) );
    2089
    2090 /* assumption before kernel variable count: we use 2-level buckets */
    2091 twolevel = TRUE;
    2092
    2093 SCIP_CALL( countKernelVariables(scip, vars, bestcurrsol, lbvarmap,
    2094 twolevel, usebestsol, heurdata->usetransprob, heurdata->translbkernel,
    2095 bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars, bw_nintkernelvars,
    2096 bw_nintnonkernelvars, &ncontkernelvars, &ncontnonkernelvars, &nkernelvars, &nnonkernelvars,
    2097 &nintkernelvars, &nintnonkernelvars, block2index, varlabels, blklbl_offset, nvars) );
    2098
    2099 SCIPdebugMsg(scip, "%d initial bin kernel vars\n%d initial int kernel vars\n", nkernelvars, nintkernelvars);
    2100
    2101 if( nkernelvars == 0 )
    2102 {
    2103 if( nintkernelvars == 0 )
    2104 {
    2105 SCIPdebugMsg(scip, "No suitable variables for the construction of a kernel. Leaving heuristic. \n");
    2106 goto TERMINATE; /* @possible todo: if continuous variables are also considered, possibly continue here */
    2107 }
    2108 else
    2109 {
    2110 /* bin vars are all zero in lp sol -> 1-level buckets with int first and bin vars in kernel afterwards */
    2111 nkernelvars = nintkernelvars;
    2112 nnonkernelvars += nintnonkernelvars;
    2113 nintkernelvars = 0;
    2114 nintnonkernelvars = 0;
    2115
    2116 /* update the blockwise figures describing kernel sizes */
    2117 for( b = 0; b < nblocks + 1; b++ )
    2118 {
    2119 bw_nkernelvars[b] = bw_nintkernelvars[b];
    2120 bw_nnonkernelvars[b] += bw_nintnonkernelvars[b];
    2121 bw_nintnonkernelvars[b] = 0;
    2122 }
    2123
    2124 twolevel = FALSE;
    2125 }
    2126 }
    2127 else if( nintkernelvars == 0 )
    2128 {
    2129 /* int vars are all zero in lp sol -> 1-level buckets with bin first and int vars in the kernel afterwards */
    2130 nnonkernelvars += nintnonkernelvars;
    2131 nintnonkernelvars = 0;
    2132
    2133 /* update the blockwise figures describing kernel sizes */
    2134 for( b = 0; b < nblocks + 1; b++ )
    2135 {
    2136 bw_nnonkernelvars[b] += bw_nintnonkernelvars[b];
    2137 bw_nintnonkernelvars[b] = 0;
    2138 }
    2139
    2140 twolevel = FALSE;
    2141 }
    2142 else if( nkernelvars > nnonkernelvars || nintkernelvars > nintnonkernelvars )
    2143 /* @potential todo: if kernel vars >> nonkernel vars or >x% of all integer/binary variables => adjust */
    2144 SCIPdebugMsg(scip, "There are more kernel variables than not in the kernel\n");
    2145 }
    2146
    2147 /* kernel initialization for all blocks + the linking block (= "+ 1") */
    2148 SCIP_CALL( SCIPallocBufferArray(scip, &bw_contkernelvars, nblocks + 1) );
    2149 SCIP_CALL( SCIPallocBufferArray(scip, &bw_contnonkernelvars, nblocks + 1) );
    2150 SCIP_CALL( SCIPallocBufferArray(scip, &bw_kernelvars, nblocks + 1) );
    2151 SCIP_CALL( SCIPallocBufferArray(scip, &bw_nonkernelvars, nblocks + 1) );
    2152
    2153 if( twolevel )
    2154 {
    2155 SCIP_CALL( SCIPallocBufferArray(scip, &bw_intkernelvars, nblocks + 1 ) );
    2156 SCIP_CALL( SCIPallocBufferArray(scip, &bw_intnonkernelvars, nblocks + 1) );
    2157 }
    2158
    2159 /* initialize kernel and non kernel variables for each block */
    2160 for( b = 0; b < nblocks + 1; b++ )
    2161 {
    2162 int contblocksize = bw_ncontkernelvars[b] + bw_ncontnonkernelvars[b];
    2163 int blocksize = bw_nkernelvars[b] + bw_nnonkernelvars[b];
    2164
    2165 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_contkernelvars[b]), contblocksize) );
    2166 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_contnonkernelvars[b]), contblocksize) );
    2167 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_kernelvars[b]), blocksize) );
    2168 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_nonkernelvars[b]), blocksize) );
    2169
    2170 if( twolevel )
    2171 {
    2172 int intblocksize;
    2173
    2174 assert(bw_nintkernelvars != NULL);
    2175 assert(bw_nintnonkernelvars != NULL);
    2176
    2177 intblocksize = bw_nintkernelvars[b] + bw_nintnonkernelvars[b];
    2178
    2179 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_intkernelvars[b]), intblocksize) );
    2180 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_intnonkernelvars[b]), intblocksize) );
    2181 }
    2182 }
    2183
    2184 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontkernelvars) < (ncontkernelvars + ncontnonkernelvars) )
    2185 maxcontkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontkernelvars);
    2186 else
    2187 maxcontkernelsize = ncontkernelvars + ncontnonkernelvars;
    2188
    2189 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontnonkernelvars) < (ncontkernelvars + ncontnonkernelvars) )
    2190 maxcontnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontnonkernelvars);
    2191 else
    2192 maxcontnonkernelsize = ncontkernelvars + ncontnonkernelvars;
    2193
    2194 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nkernelvars) < (nkernelvars + nnonkernelvars) )
    2195 maxkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nkernelvars);
    2196 else
    2197 maxkernelsize = nkernelvars + nnonkernelvars;
    2198
    2199 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nnonkernelvars) < (nkernelvars + nnonkernelvars) )
    2200 maxnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nnonkernelvars);
    2201 else
    2202 maxnonkernelsize = nkernelvars + nnonkernelvars;
    2203
    2204 /* initialize the kernel and non kernel variable arrays (just binary (non/)kernel variables if 2-level buckets) */
    2205 SCIP_CALL( SCIPallocBufferArray(scip, &contkernelvars, maxcontkernelsize) );
    2206 SCIP_CALL( SCIPallocBufferArray(scip, &contnonkernelvars, maxcontnonkernelsize) );
    2207 SCIP_CALL( SCIPallocBufferArray(scip, &kernelvars, maxkernelsize) );
    2208 SCIP_CALL( SCIPallocBufferArray(scip, &nonkernelvars, maxnonkernelsize) );
    2209
    2210 /* include all binary AND integer variables as a separate array */
    2211 SCIP_CALL( SCIPallocBufferArray(scip, &binintvars, nbinvars + nintvars) );
    2212
    2213 /* extract (potential) init kernel vars (value > 0) and not kernel vars for all blocks + the linking one (= "+ 1") */
    2214 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_contkernelcount, nblocks + 1) );
    2215 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_contnonkernelcount, nblocks + 1) );
    2216 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_kernelcount, nblocks + 1) );
    2217 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nonkernelcount, nblocks + 1) );
    2218
    2219 maxintkernelsize = 0;
    2220
    2221 /* 2-level buckets are necessary */
    2222 if( twolevel )
    2223 {
    2224 /* additionally determine maximal integer kernel size */
    2225 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintkernelvars) < (nintkernelvars + nintnonkernelvars) )
    2226 maxintkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintkernelvars);
    2227 else
    2228 maxintkernelsize = nintkernelvars + nintnonkernelvars;
    2229
    2230 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintnonkernelvars) < (nintkernelvars + nintnonkernelvars) )
    2231 maxintnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintnonkernelvars);
    2232 else
    2233 maxintnonkernelsize = nintkernelvars + nintnonkernelvars;
    2234
    2235 /* additionally initialize the integer kernel and the non integer kernel variable arrays */
    2236 SCIP_CALL( SCIPallocBufferArray(scip, &intkernelvars, maxintkernelsize) );
    2237 SCIP_CALL( SCIPallocBufferArray(scip, &intnonkernelvars, maxintnonkernelsize) );
    2238
    2239 /* allocate memory for counting the pure integer variables for all blocks + the linking block (= "+ 1") */
    2240 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_intkernelcount, nblocks + 1) );
    2241 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_intnonkernelcount, nblocks + 1) );
    2242
    2243 /* filling of the kernels with the variables */
    2244 SCIP_CALL( fillKernels(scip, vars, binintvars,
    2245 bw_contkernelvars, bw_contnonkernelvars, bw_kernelvars, bw_nonkernelvars,
    2246 bw_intkernelvars, bw_intnonkernelvars, bestcurrsol, lbvarmap, twolevel, usebestsol,
    2247 heurdata->usetransprob, heurdata->translbkernel, bw_contkernelcount,
    2248 bw_contnonkernelcount, bw_kernelcount, bw_nonkernelcount, bw_intkernelcount,
    2249 bw_intnonkernelcount, bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars,
    2250 bw_nintkernelvars, bw_nintnonkernelvars, block2index, varlabels, blklbl_offset, nvars) );
    2251 }
    2252 else
    2253 /* filling of the kernels with the variables */
    2254 SCIP_CALL( fillKernels(scip, vars, binintvars,
    2255 bw_contkernelvars, bw_contnonkernelvars, bw_kernelvars, bw_nonkernelvars, NULL, NULL,
    2256 bestcurrsol, lbvarmap, twolevel, usebestsol, heurdata->usetransprob,
    2257 heurdata->translbkernel, bw_contkernelcount, bw_contnonkernelcount, bw_kernelcount,
    2258 bw_nonkernelcount, NULL, NULL, bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars,
    2259 NULL, NULL, block2index, varlabels, blklbl_offset, nvars) );
    2260
    2261 /* sorting of bucket variables according to the reduced costs in non-decreasing order */
    2262 if( heurdata->redcostsort || heurdata->redcostlogsort )
    2263 {
    2264 SCIP_CALL( reducedCostSort(scip, bw_contnonkernelvars, bw_nonkernelvars, bw_intnonkernelvars,
    2265 &bw_cont_redcost, &bw_redcost, &bw_int_redcost, bw_ncontnonkernelvars, bw_nnonkernelvars,
    2266 bw_nintnonkernelvars, twolevel, nblocks) );
    2267 }
    2268
    2269 /* initialization of the buckets */
    2270 /* determine the amount of buckets needed */
    2271 /* continuous variables are not included when calculating the number of buckets, since they are easier to handle */
    2272 nusedratios = 0;
    2273 if( twolevel )
    2274 {
    2275 SCIP_Real intratio;
    2276 SCIP_Real binratio;
    2277
    2278 nbuckets = 0;
    2279 for( b = 0; b < nblocks + 1; b++ )
    2280 {
    2281 /* calculate the upper gauss bracket of the ratio of the integer (binary) kernel and non kernel variables */
    2282 if( bw_nintnonkernelvars[b] > 0 && bw_nintkernelvars[b] > 0 )
    2283 intratio = SCIPceil(scip, bw_nintnonkernelvars[b] / (SCIP_Real)bw_nintkernelvars[b]);
    2284 else
    2285 intratio = SCIPinfinity(scip);
    2286
    2287 if( bw_nnonkernelvars[b] > 0 && bw_nkernelvars[b] > 0 )
    2288 binratio = SCIPceil(scip, bw_nnonkernelvars[b] / (SCIP_Real)bw_nkernelvars[b]);
    2289 else
    2290 binratio = SCIPinfinity(scip);
    2291
    2292 if( !SCIPisInfinity(scip, intratio) )
    2293 {
    2294 nbuckets += (int)intratio;
    2295 nusedratios++;
    2296 }
    2297 if( !SCIPisInfinity(scip, binratio) )
    2298 {
    2299 nbuckets += (int)binratio;
    2300 nusedratios++;
    2301 }
    2302 }
    2303 }
    2304 else
    2305 {
    2306 /* take the rounded down average bucket ratio of all blocks*/
    2307 nbuckets = 0;
    2308 for( b = 0; b < nblocks + 1; b++ )
    2309 {
    2310 if( bw_nnonkernelvars[b] > 0 && bw_nkernelvars[b] > 0 )
    2311 {
    2312 nbuckets += (int)SCIPceil(scip, (SCIP_Real)bw_nnonkernelvars[b] / (SCIP_Real)bw_nkernelvars[b]);
    2313 nusedratios++;
    2314 }
    2315 }
    2316 }
    2317 /* taking the average ratio as final one for all blocks */
    2318 if( nusedratios > 0 )
    2319 nbuckets = (int)SCIPceil(scip, (SCIP_Real)nbuckets / (SCIP_Real)nusedratios);
    2320 else
    2321 nbuckets = 0;
    2322
    2323 /* determine the amount of iterations over the buckets/ amount of investigated buckets */
    2324 iters = MIN(nbuckets, heurdata->maxbucks) + 1;
    2325
    2326 /* create an extra array for the bucket constraints for hashmap creation in createBucketlistAndBuckets() */
    2327 SCIP_CALL( SCIPduplicateBufferArray(scip, &bucketconss, conss, nconss) );
    2328
    2329 /* create the bucketlist and initialize as much buckets as investigated later on with a subscip for every bucket */
    2330 SCIP_CALL( createBucketlistAndBuckets(scip, heurdata->usetransprob, iters - 1, &bucketlist, &success) );
    2331 if( !success )
    2332 goto TERMINATE;
    2333
    2334 /* fill every bucket with its variables, nothing to do for the first ('kernel') bucket -> k = 1 */
    2335 if( iters > 1 )
    2336 {
    2337 SCIP_CALL( fillBuckets(scip, &bucketlist,
    2338 bw_contnonkernelvars, bw_nonkernelvars, bw_intnonkernelvars,
    2339 bw_ncontnonkernelvars, bw_nnonkernelvars, bw_nintnonkernelvars,
    2340 bw_cont_redcost, bw_redcost, bw_int_redcost,
    2341 twolevel, heurdata->redcostlogsort, iters - 1, nblocks) );
    2342 }
    2343
    2344 /* build the kernelvariables out of each blocks kernel variables */
    2345 j = 0;
    2346 n = 0;
    2347 m = 0;
    2348 for( b = 0; b < nblocks + 1; b++ )
    2349 {
    2350 for( l = 0; l < bw_ncontkernelvars[b]; l++ )
    2351 contkernelvars[j++] = bw_contkernelvars[b][l];
    2352
    2353 for( l = 0; l < bw_nkernelvars[b]; l++ )
    2354 kernelvars[n++] = bw_kernelvars[b][l];
    2355
    2356 if( twolevel )
    2357 {
    2358 for( l = 0; l < bw_nintkernelvars[b]; l++ )
    2359 intkernelvars[m++] = bw_intkernelvars[b][l];
    2360 }
    2361 }
    2362 assert(j == ncontkernelvars);
    2363 assert(n == nkernelvars);
    2364 if( twolevel )
    2365 assert(m == nintkernelvars);
    2366
    2367 /* loop over all buckets, solve the small MIP defined by the bucket, adjust kernel */
    2368 mipgap = 0.0;
    2369 nodesleft = heurdata->maxnodes;
    2370 nnodes = 0;
    2371 for( k = 0; k < iters; k++ )
    2372 {
    2373 SCIP_Bool found;
    2374 SCIP_Bool infeasible;
    2375 SCIP_Bool fixed;
    2376 SCIP_Real lb;
    2377 SCIP_Real ub;
    2378 SCIP_Real timeused;
    2379 SCIP_Real totaltimelimit;
    2380 SCIP_Real subtimelimit;
    2381 SCIP_VAR *var;
    2382
    2383 bucket = &bucketlist->buckets[k];
    2384
    2385 /* do not compute the current bucket if the number of free bin/int variables exceeds some percentage */
    2386 if( SCIPisGT(scip, (SCIP_Real)(nkernelvars + nintkernelvars + bucket->nbucketvars + bucket->nintbucketvars),
    2387 heurdata->maxbuckfrac * (SCIP_Real)(nintvars + nbinvars)) )
    2388 continue;
    2389
    2390 /* fix all integer and binary variables to zero that are neither in the kernel nor in the current bucket */
    2391 for( i = 0; i < nvars ; i++ )
    2392 {
    2393 found = FALSE;
    2394 infeasible = TRUE;
    2395 fixed = FALSE;
    2396
    2397 var = vars[i];
    2398
    2399 if( var == NULL )
    2400 SCIPdebugMsg(scip, "Variable is null!\n");
    2401
    2403 SCIPdebugMsg(scip, "Hit a cont variable");
    2404
    2405 /* search for the current variable in the kernel and in the current bucket */
    2406 SCIP_CALL( searchKernelAndBucket(bucket, contkernelvars, ncontkernelvars, kernelvars, nkernelvars,
    2407 intkernelvars, nintkernelvars, var, &found) );
    2408
    2409 if( found == TRUE )
    2410 continue;
    2411
    2412 if( var == NULL )
    2413 goto TERMINATE;
    2414
    2415 /* variable not in kernel or bucket -> deactivate by fixing to bound or zero */
    2416 assert(SCIPvarIsActive(var));
    2417
    2418 var = bucket->scip2sub[SCIPvarGetProbindex(var)];
    2419 if( var != NULL )
    2420 {
    2421 lb = SCIPvarGetLbLocal(vars[i]);
    2422 ub = SCIPvarGetUbLocal(vars[i]);
    2423
    2424 /* fix to lb if finite, else to zero if ub nonnegative, else to ub */
    2425 if( !SCIPisInfinity(scip, -lb) )
    2426 {
    2427 SCIP_CALL( SCIPfixVar(bucket->subscip, var, lb, &infeasible, &fixed) );
    2428 }
    2429 else if( ub >= 0.0 )
    2430 {
    2431 SCIP_CALL( SCIPfixVar(bucket->subscip, var, 0.0, &infeasible, &fixed) );
    2432 }
    2433 else
    2434 {
    2435 SCIP_CALL( SCIPfixVar(bucket->subscip, var, ub, &infeasible, &fixed) );
    2436 }
    2437 assert(!infeasible);
    2438 assert(fixed);
    2439 }
    2440 }
    2441
    2442 /* construct a constraint that ensures the use of the bucketvariables */
    2443 if( heurdata->addUseConss && bucket->bucketvars != NULL )
    2444 SCIP_CALL( addUseConstraint(bucket) );
    2445
    2446 /* add objective cutoff if desired */
    2447 if( heurdata->objcutoff )
    2448 {
    2450
    2451 if( !SCIPisInfinity(scip, cutoff) )
    2452 SCIP_CALL( SCIPsetObjlimit(bucket->subscip, cutoff) );
    2453 }
    2454
    2455#ifdef DKS_WRITE_PROBLEMS
    2456 if( bucket->number < 0 )
    2457 {
    2458 char name[SCIP_MAXSTRLEN];
    2459 /* write the current bucket problem */
    2460 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "subscip_bucket_%d.lp", bucket->number);
    2461 SCIP_CALL( SCIPwriteOrigProblem(bucket->subscip, name, NULL, FALSE) );
    2462 }
    2463#endif
    2464 /* update the time limit */
    2465 timeused = SCIPgetTotalTime(scip);
    2466 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &totaltimelimit) );
    2467 subtimelimit = totaltimelimit - timeused;
    2468 if( subtimelimit > 1.0 )
    2469 SCIP_CALL( SCIPsetRealParam(bucket->subscip, "limits/time", subtimelimit) );
    2470 else
    2471 goto TERMINATE;
    2472
    2473 /* update the remaining number of nodes */
    2474 nodesleft -= nnodes;
    2475
    2476 /* get the node limit which results from evenly distributing the remaining nodes */
    2477 if( nodesleft > 0 )
    2478 {
    2479 SCIP_Longint nodes_evenly_dist;
    2480 nodes_evenly_dist = (SCIP_Longint)SCIPceil(scip, ((SCIP_Real)nodesleft) / ((SCIP_Real)(iters - k)));
    2481 if( 1LL > nodes_evenly_dist )
    2482 nnodes = 1LL;
    2483 else
    2484 nnodes = nodes_evenly_dist;
    2485 }
    2486 else
    2487 {
    2488 SCIPdebugMsg(scip, "Overall node limit reached.\n");
    2489 goto TERMINATE;
    2490 }
    2491
    2492 /* set the node limit parameter for the subscip */
    2493 SCIP_CALL( SCIPsetLongintParam(bucket->subscip, "limits/nodes", nnodes) );
    2494
    2495 /* set the mipgap parameter for the subscip */
    2496 SCIP_CALL( SCIPsetRealParam(bucket->subscip, "limits/gap", mipgap) );
    2497
    2498 /* solve the current subscip */
    2499 SCIP_CALL_ABORT( SCIPsolve(bucket->subscip) );
    2500 status = SCIPgetStatus(bucket->subscip);
    2501
    2502 /* compute the nodes used by the subscip */
    2503 nnodes = SCIPgetNNodes(bucket->subscip);
    2504
    2505 if( bucket->number == 0 )
    2506 *result = SCIP_DIDNOTFIND;
    2507
    2508 /* if the node limit was reached, increase the mip gap */
    2509 /* gapcall = 1 signals node limit was reached before, -1 signals gap limit, 0 means no status was reached */
    2510 if( status == SCIP_STATUS_NODELIMIT )
    2511 {
    2512 if( gapcall != 0 )
    2513 gapfactor /= 2.0;
    2514
    2515 mipgap += (heurdata->buckmaxgap / iters) * gapfactor;
    2516 gapcall = 1;
    2517 }
    2518 else if( status == SCIP_STATUS_GAPLIMIT )
    2519 {
    2520 if( gapcall != 0 )
    2521 gapfactor /= 2.0;
    2522
    2523 mipgap -= (heurdata->buckmaxgap / iters) * gapfactor;
    2524 gapcall = -1;
    2525 }
    2526
    2527 /* check if the solution is better if one of the three cases occur:
    2528 - solution is optimal
    2529 - solution reached gaplimit
    2530 - node limit is reached and there is one solution */
    2531
    2532 if( status == SCIP_STATUS_OPTIMAL || status == SCIP_STATUS_GAPLIMIT ||
    2533 (status == SCIP_STATUS_NODELIMIT && SCIPgetNSols(bucket->subscip) > 0) )
    2534 {
    2535 SCIP_Real val;
    2536 SCIP_SOL* sol;
    2537
    2538 sol = SCIPgetBestSol(bucket->subscip);
    2539 val = SCIPgetSolOrigObj(bucket->subscip, sol);
    2540
    2541 /* if there is no solution yet or if the value of the current solution is better than the saved solution */
    2542 if( SCIPisInfinity(scip, bestlocval) || val <= bestlocval )
    2543 {
    2544 bestlocval = val;
    2545 nbestbucket = bucket->number;
    2546
    2547 if( heurdata->primalonly )
    2548 break;
    2549
    2550 /* adjust the kernel(/-variables) */
    2551 SCIP_CALL( adjustKernelVars(scip, bucket, &contkernelvars, &ncontkernelvars, (int)maxcontkernelsize,
    2552 &kernelvars, &nkernelvars, (int)maxkernelsize, &intkernelvars, &nintkernelvars, (int)maxintkernelsize,
    2553 twolevel) );
    2554 }
    2555 success = FALSE;
    2556 }
    2557 else if( status == SCIP_STATUS_NODELIMIT )
    2558 SCIPdebugMsg(scip, "Bucket reached node limit. No optimal solution available.\n");
    2559 else if( status == SCIP_STATUS_INFEASIBLE )
    2560 SCIPdebugMsg(scip, "Bucket infeasible, starting over with next one\n");
    2561 else
    2562 {
    2563 SCIPdebugMsg(scip, "Bucket solving status %d is not supported\n", status);
    2564 goto TERMINATE;
    2565 }
    2566
    2568
    2569#ifdef DKS_KERNEL_INFO
    2570 fclose(variable_info);
    2571#endif
    2572 }
    2573
    2574 /* if a solution of a bucket was found, save it to the scip */
    2575 if( nbestbucket > -1 )
    2576 {
    2577 SCIP_SOL* newsol;
    2578 SCIP_SOL* bestsol;
    2579 BUCKET* bestbucket;
    2580
    2581 /* bucket with the best solution */
    2582 bestbucket = &bucketlist->buckets[nbestbucket];
    2583
    2584 /* get the best solution */
    2585 bestsol = SCIPgetBestSol(bestbucket->subscip);
    2586 if( bestsol == NULL )
    2587 {
    2588 SCIPdebugMsg(scip, "Function SCIPgetBestSol() has returned a NULL pointer\n");
    2589 *result = SCIP_DIDNOTFIND;
    2590 goto TERMINATE;
    2591 }
    2592
    2593 SCIPdebug( SCIP_CALL( SCIPprintSol(bestbucket->subscip, bestsol, NULL, FALSE) ) );
    2594
    2595 /* extract the values of all variables in the best solution of a bucket found */
    2596 SCIP_CALL( SCIPtranslateSubSol(scip, bestbucket->subscip, bestsol, heur, bestbucket->scip2sub, &newsol) );
    2597
    2598 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, newsol, NULL, FALSE) ) );
    2599 SCIPdebugMsg(scip, "Objective value %.2f\n", SCIPgetSolOrigObj(scip, newsol));
    2600 SCIPdebugMsg(scip, "Objective value of subscip %.2f\n", SCIPgetSolOrigObj(bestbucket->subscip, bestsol));
    2601
    2602 /* check the feasibilty of the new created solution, save it if so and free it */
    2603 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    2604
    2605 if( !success )
    2606 {
    2607 SCIPdebugMsg(scip, "Solution copy failed\n");
    2608 *result = SCIP_DIDNOTFIND;
    2609 }
    2610 else
    2611 {
    2612 SCIPdebugMsg(scip, "Solution copy successfull after %f sec\n", SCIPgetSolvingTime(scip));
    2613 *result = SCIP_FOUNDSOL;
    2614 }
    2615 }
    2616 else
    2617 {
    2618 SCIPdebugMsg(scip, "no solution found\n");
    2619 *result = SCIP_DIDNOTFIND;
    2620 }
    2621
    2622 /* remember if the heuristic has not provided a solution */
    2623 if( *result != SCIP_FOUNDSOL )
    2624 heurdata->uselesscall = TRUE;
    2625
    2626TERMINATE:
    2627 if( bucketconss != NULL )
    2628 SCIPfreeBufferArray(scip, &bucketconss);
    2629
    2630 if( bw_intnonkernelcount != NULL )
    2631 SCIPfreeBufferArray(scip, &bw_intnonkernelcount);
    2632
    2633 if( bw_intkernelcount != NULL )
    2634 SCIPfreeBufferArray(scip, &bw_intkernelcount);
    2635
    2636 if( intnonkernelvars != NULL )
    2637 SCIPfreeBufferArray(scip, &intnonkernelvars);
    2638
    2639 if( intkernelvars != NULL )
    2640 SCIPfreeBufferArray(scip, &intkernelvars);
    2641
    2642 if( bw_nonkernelcount != NULL )
    2643 SCIPfreeBufferArray(scip, &bw_nonkernelcount);
    2644
    2645 if( bw_kernelcount != NULL )
    2646 SCIPfreeBufferArray(scip, &bw_kernelcount);
    2647
    2648 if( bw_contnonkernelcount != NULL )
    2649 SCIPfreeBufferArray(scip, &bw_contnonkernelcount);
    2650
    2651 if( bw_contkernelcount != NULL )
    2652 SCIPfreeBufferArray(scip, &bw_contkernelcount);
    2653
    2654 if( binintvars != NULL )
    2655 SCIPfreeBufferArray(scip, &binintvars);
    2656
    2657 if( nonkernelvars != NULL )
    2658 SCIPfreeBufferArray(scip, &nonkernelvars);
    2659
    2660 if( kernelvars != NULL )
    2661 SCIPfreeBufferArray(scip, &kernelvars);
    2662
    2663 if( contnonkernelvars != NULL )
    2664 SCIPfreeBufferArray(scip, &contnonkernelvars);
    2665
    2666 if( contkernelvars != NULL )
    2667 SCIPfreeBufferArray(scip, &contkernelvars);
    2668
    2669 if( bw_intkernelvars != NULL )
    2670 {
    2671 for( b = nblocks; b >= 0; b-- )
    2672 {
    2673 if( bw_intnonkernelvars[b] != NULL )
    2674 SCIPfreeBufferArray(scip, &(bw_intnonkernelvars[b]));
    2675 if( bw_intkernelvars[b] != NULL )
    2676 SCIPfreeBufferArray(scip, &(bw_intkernelvars[b]));
    2677 }
    2678 }
    2679
    2680 if( bw_kernelvars != NULL )
    2681 {
    2682 for( b = nblocks; b >= 0; b-- )
    2683 {
    2684 if( bw_nonkernelvars[b] != NULL )
    2685 SCIPfreeBufferArray(scip, &(bw_nonkernelvars[b]));
    2686 if( bw_kernelvars[b] != NULL )
    2687 SCIPfreeBufferArray(scip, &(bw_kernelvars[b]));
    2688 }
    2689 }
    2690
    2691 if( bw_contkernelvars != NULL )
    2692 {
    2693 for( b = nblocks; b >= 0; b-- )
    2694 {
    2695 if( bw_contnonkernelvars[b] != NULL )
    2696 SCIPfreeBufferArray(scip, &(bw_contnonkernelvars[b]));
    2697 if( bw_contkernelvars[b] != NULL )
    2698 SCIPfreeBufferArray(scip, &(bw_contkernelvars[b]));
    2699 }
    2700 }
    2701
    2702 if( bw_intnonkernelvars != NULL )
    2703 SCIPfreeBufferArray(scip, &bw_intnonkernelvars);
    2704
    2705 if( bw_intkernelvars != NULL )
    2706 SCIPfreeBufferArray(scip, &bw_intkernelvars);
    2707
    2708 if( bw_nonkernelvars != NULL )
    2709 SCIPfreeBufferArray(scip, &bw_nonkernelvars);
    2710
    2711 if( bw_kernelvars != NULL )
    2712 SCIPfreeBufferArray(scip, &bw_kernelvars);
    2713
    2714 if( bw_contnonkernelvars != NULL )
    2715 SCIPfreeBufferArray(scip, &bw_contnonkernelvars);
    2716
    2717 if( bw_contkernelvars != NULL )
    2718 SCIPfreeBufferArray(scip, &bw_contkernelvars);
    2719
    2720 if( bw_nintnonkernelvars != NULL )
    2721 SCIPfreeBufferArray(scip, &bw_nintnonkernelvars);
    2722
    2723 if( bw_nintkernelvars != NULL )
    2724 SCIPfreeBufferArray(scip, &bw_nintkernelvars);
    2725
    2726 if( bw_nnonkernelvars != NULL )
    2727 SCIPfreeBufferArray(scip, &bw_nnonkernelvars);
    2728
    2729 if( bw_nkernelvars != NULL )
    2730 SCIPfreeBufferArray(scip, &bw_nkernelvars);
    2731
    2732 if( bw_ncontnonkernelvars != NULL )
    2733 SCIPfreeBufferArray(scip, &bw_ncontnonkernelvars);
    2734
    2735 if( bw_ncontkernelvars != NULL )
    2736 SCIPfreeBufferArray(scip, &bw_ncontkernelvars);
    2737
    2738 if( block2index != NULL )
    2739 {
    2740 if( nblocklabels > 0 )
    2741 {
    2742 assert(blocklabels != NULL);
    2743 SCIPfreeBlockMemoryArray(scip, &block2index, blocklabels[nblocklabels - 1] + 1 + blklbl_offset);
    2744 }
    2745 else
    2746 SCIPfreeBlockMemoryArray(scip, &block2index, 1);
    2747 }
    2748
    2749 if( blocklabels != NULL )
    2750 SCIPfreeBufferArray(scip, &blocklabels);
    2751
    2752 if( conslabels != NULL )
    2753 SCIPfreeBufferArray(scip, &conslabels);
    2754
    2755 if( varlabels != NULL )
    2756 SCIPfreeBufferArray(scip, &varlabels);
    2757
    2758 SCIP_CALL( freeRedcostArrays(scip, &bw_cont_redcost, &bw_redcost, &bw_int_redcost, nblocks) );
    2759
    2760 if( lbvarmap != NULL )
    2761 SCIPhashmapFree(&lbvarmap);
    2762
    2763 if( bucketlist != NULL )
    2764 {
    2765 for( k = bucketlist->nbuckets - 1; k >= 1; k-- )
    2766 {
    2767 SCIP_CALL( freeBucket(scip, &bucketlist->buckets[k]) );
    2768 SCIP_CALL( freeBucketArrays(scip, &bucketlist->buckets[k], twolevel) );
    2769 }
    2770 SCIP_CALL( freeBucket(scip, &bucketlist->buckets[0]) );
    2771 }
    2772
    2773 if( bucketlist != NULL )
    2774 {
    2775 SCIP_CALL( freeBucketlist(&bucketlist, iters) );
    2776 }
    2777
    2778 SCIPdebugMsg(scip, "Leave dks heuristic\n");
    2779
    2780 return SCIP_OKAY;
    2781}
    2782
    2783
    2784/*
    2785 * primal heuristic specific interface methods
    2786 */
    2787
    2788/** creates the DKS primal heuristic and includes it in SCIP */
    2790 SCIP* scip /**< SCIP data structure */
    2791 )
    2792{
    2793 SCIP_HEURDATA* heurdata = NULL;
    2794 SCIP_HEUR* heur = NULL;
    2795
    2796 /* create dks primal heuristic data */
    2797 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    2798 assert(heurdata != NULL);
    2799 heurdata->ncalls = 0;
    2800 heurdata->uselesscall = FALSE;
    2801
    2802 /* include primal heuristic */
    2805 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDKS, heurdata) );
    2806
    2807 assert(heur != NULL);
    2808
    2809 /* set non fundamental callbacks via setter functions */
    2810 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDKS) );
    2811 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDKS) );
    2812
    2813 /* add dks primal heuristic parameters */
    2814 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxbucks",
    2815 "maximal number of buckets to be investigated",
    2816 &heurdata->maxbucks, TRUE, DEFAULT_MAXBUCKS, 1, 100, NULL, NULL) );
    2817
    2818 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/kernelsizefactor",
    2819 "factor with which the initial kernel size can grow max",
    2820 &heurdata->kernelsizefactor, TRUE, DEFAULT_KERNELSIZEFACTOR, 1.0, 10.0, NULL, NULL) );
    2821
    2822 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/addUseConss",
    2823 "should a constraint be added ensuring that bucket variables are used?",
    2824 &heurdata->addUseConss, TRUE, DEFAULT_ADDUSECONSS, NULL, NULL) );
    2825
    2826 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/linkbucksize",
    2827 "should the linking variables in the kernel influence the size of the buckets?",
    2828 &heurdata->linkbucksize, TRUE, DEFAULT_LINKBUCKSIZE, NULL, NULL) );
    2829
    2830 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/translbkernel",
    2831 "should a variable with different lower bound in transformed and original problem be in the kernel?",
    2832 &heurdata->translbkernel, TRUE, DEFAULT_TRANSLBKERNEL, NULL, NULL) );
    2833
    2834 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/lesslockskernel",
    2835 "should a variable with max one uplock and one downlock be in the kernel?",
    2836 &heurdata->lesslockskernel, TRUE, DEFAULT_LESSLOCKSKERNEL, NULL, NULL) );
    2837
    2838 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usetransprob",
    2839 "should dks use the transformed problem?",
    2840 &heurdata->usetransprob, TRUE, DEFAULT_USETRANSPROB, NULL, NULL) );
    2841
    2842 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/buckmaxgap",
    2843 "defines the maximum mipgap a bucket can be solved to",
    2844 &heurdata->buckmaxgap, TRUE, DEFAULT_BUCKMAXGAP, 0.0, 1.0, NULL, NULL) );
    2845
    2846 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxlinkscore",
    2847 "defines a bound to the linkscore of the decomp",
    2848 &heurdata->maxlinkscore, TRUE, DEFAULT_MAXLINKSCORE, 0.0, 1.0, NULL, NULL) );
    2849
    2850 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxbuckfrac",
    2851 "defines a maximal share of bin/int variables for a bucket to be respected",
    2852 &heurdata->maxbuckfrac, TRUE, DEFAULT_MAXBUCKFRAC, 0.0, 1.0, NULL, NULL) );
    2853
    2854 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    2855 "maximum number of nodes to regard in all subproblems",
    2856 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    2857
    2858 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usetwolevel",
    2859 "should a two level bucket structure be used if possible?",
    2860 &heurdata->usetwolevel, FALSE, DEFAULT_USETWOLEVEL, NULL, NULL) );
    2861
    2862 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedecomp",
    2863 "should a decomposition be used if given?",
    2864 &heurdata->usedecomp, FALSE, DEFAULT_USEDECOMP, NULL, NULL) );
    2865
    2866 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usebestsol",
    2867 "should the best solution instead of the LP solution be used?",
    2868 &heurdata->usebestsol, FALSE, DEFAULT_USEBESTSOL, NULL, NULL) );
    2869
    2870 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/redcostsort",
    2871 "should the bucket variables be sorted by reduced costs in the LP solution?",
    2872 &heurdata->redcostsort, FALSE, DEFAULT_REDCOSTSORT, NULL, NULL) );
    2873
    2874 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/primalonly",
    2875 "should the heuristic terminate after the first primal solution is found?",
    2876 &heurdata->primalonly, FALSE, DEFAULT_PRIMALONLY, NULL, NULL) );
    2877
    2878 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/redcostlogsort",
    2879 "should the bucket variables be sorted logarithmically by reduced costs in the LP solution?",
    2880 &heurdata->redcostlogsort, FALSE, DEFAULT_REDCOSTLOGSORT, NULL, NULL) ) ;
    2881
    2882 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/objcutoff",
    2883 "should the next solution at least satisfy the old objective?",
    2884 &heurdata->objcutoff, FALSE, DEFAULT_OBJCUTOFF, NULL, NULL) );
    2885
    2886 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/runbinprobsonly",
    2887 "should the heuristic be used only for binary problems or problems with integer and binary variables?",
    2888 &heurdata->runbinprobsonly, FALSE, DEFAULT_RUNBINPROBSONLY, NULL, NULL) );
    2889
    2890 return SCIP_OKAY;
    2891}
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    Constraint handler for linear constraints in their most general form, .
    methods for debugging
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define nnodes
    Definition: gastrans.c:74
    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 SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:276
    SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global)
    Definition: scip_copy.c:1167
    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:1580
    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:1397
    SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:2547
    SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3292
    void SCIPgetDecomps(SCIP *scip, SCIP_DECOMP ***decomps, int *ndecomps, SCIP_Bool original)
    Definition: scip_dcmp.c:263
    int SCIPdecompGetNBlocks(SCIP_DECOMP *decomp)
    Definition: dcmp.c:279
    void SCIPdecompGetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
    Definition: dcmp.c:198
    void SCIPdecompGetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
    Definition: dcmp.c:149
    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 SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2753
    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
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
    Definition: scip_prob.c:2811
    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
    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
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3613
    SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3344
    SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
    Definition: misc.c:3434
    int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3584
    SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
    Definition: misc.c:3592
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3603
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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 SCIPunfixParam(SCIP *scip, const char *name)
    Definition: scip_param.c:385
    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 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 SCIPincludeHeurDKS(SCIP *scip)
    Definition: heur_dks.c:2789
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4778
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    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
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    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 SCIPallocClearBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:97
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #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 SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2349
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    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:4109
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPgetTotalTime(SCIP *scip)
    Definition: scip_timing.c:351
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(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_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18320
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
    Definition: var.c:24020
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2608
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    void SCIPsortRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
    void SCIPsortInt(int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE fillBuckets(SCIP *scip, BUCKETLIST **bucketlist, SCIP_VAR ***bw_contnonkernelvars, SCIP_VAR ***bw_nonkernelvars, SCIP_VAR ***bw_intnonkernelvars, int *bw_ncontnonkernelvars, int *bw_nnonkernelvars, int *bw_nintnonkernelvars, SCIP_Real **bw_cont_redcost, SCIP_Real **bw_redcost, SCIP_Real **bw_int_redcost, SCIP_Bool twolevel, SCIP_Bool redcostlogsort, int nbuckets, int nblocks)
    Definition: heur_dks.c:699
    static SCIP_RETCODE searchKernelAndBucket(BUCKET *bucket, SCIP_VAR **contkernelvars, int ncontkernelvars, SCIP_VAR **kernelvars, int nkernelvars, SCIP_VAR **intkernelvars, int nintkernelvars, SCIP_VAR *var, SCIP_Bool *found)
    Definition: heur_dks.c:1301
    #define DEFAULT_OBJCUTOFF
    Definition: heur_dks.c:106
    static SCIP_DECL_HEUREXEC(heurExecDKS)
    Definition: heur_dks.c:1768
    #define DEFAULT_LINKBUCKSIZE
    Definition: heur_dks.c:92
    #define DEFAULT_MAXNODES
    Definition: heur_dks.c:99
    #define DEFAULT_BUCKMAXGAP
    Definition: heur_dks.c:96
    #define DEFAULT_ADDUSECONSS
    Definition: heur_dks.c:91
    static SCIP_RETCODE reducedCostSort(SCIP *scip, SCIP_VAR ***bw_contnonkernelvars, SCIP_VAR ***bw_nonkernelvars, SCIP_VAR ***bw_intnonkernelvars, SCIP_Real ***bw_cont_redcost, SCIP_Real ***bw_redcost, SCIP_Real ***bw_int_redcost, int *bw_ncontnonkernelvars, int *bw_nnonkernelvars, int *bw_nintnonkernelvars, SCIP_Bool twolevel, int nblocks)
    Definition: heur_dks.c:544
    #define HEUR_TIMING
    Definition: heur_dks.c:86
    #define DEFAULT_KERNELSIZEFACTOR
    Definition: heur_dks.c:90
    #define DEFAULT_TRANSLBKERNEL
    Definition: heur_dks.c:93
    #define HEUR_FREQOFS
    Definition: heur_dks.c:84
    #define HEUR_DESC
    Definition: heur_dks.c:80
    static SCIP_RETCODE createBucketlistAndBuckets(SCIP *scip, SCIP_Bool usetransprob, int nbuckets, BUCKETLIST **bucketlist, SCIP_Bool *success)
    Definition: heur_dks.c:1262
    static SCIP_RETCODE freeBucketArrays(SCIP *scip, BUCKET *bucket, SCIP_Bool twolevel)
    Definition: heur_dks.c:944
    #define DEFAULT_REDCOSTLOGSORT
    Definition: heur_dks.c:105
    static SCIP_RETCODE initBucket(BUCKETLIST *bucketlist)
    Definition: heur_dks.c:962
    #define HEUR_DISPCHAR
    Definition: heur_dks.c:81
    #define HEUR_MAXDEPTH
    Definition: heur_dks.c:85
    #define HEUR_PRIORITY
    Definition: heur_dks.c:82
    #define DEFAULT_MAXLINKSCORE
    Definition: heur_dks.c:97
    #define DEFAULT_USETWOLEVEL
    Definition: heur_dks.c:100
    struct Bucket BUCKET
    #define HEUR_NAME
    Definition: heur_dks.c:79
    static SCIP_DECL_HEURFREE(heurFreeDKS)
    Definition: heur_dks.c:1750
    static SCIP_RETCODE getLinkingScoreAndBlocklabels(int *blocklabels, int *varlabels, int *conslabels, SCIP_Real *linkscore, int *nblocklabels, int nblocks, int nvars, int nconss)
    Definition: heur_dks.c:174
    static SCIP_RETCODE adjustKernelVars(SCIP *scip, BUCKET *bucket, SCIP_VAR ***contkernelvars, int *ncontkernelvars, int maxcontkernelsize, SCIP_VAR ***kernelvars, int *nkernelvars, int maxkernelsize, SCIP_VAR ***intkernelvars, int *nintkernelvars, int maxintkernelsize, SCIP_Bool twolevel)
    Definition: heur_dks.c:1385
    #define DEFAULT_MAXBUCKFRAC
    Definition: heur_dks.c:98
    static SCIP_RETCODE freeBucket(SCIP *scip, BUCKET *bucket)
    Definition: heur_dks.c:993
    static SCIP_RETCODE freeRedcostArrays(SCIP *scip, SCIP_Real ***bw_cont_redcost, SCIP_Real ***bw_redcost, SCIP_Real ***bw_int_redcost, int nblocks)
    Definition: heur_dks.c:613
    static SCIP_RETCODE bucketCreateSubscip(BUCKET *bucket, SCIP_Bool usetransprob, SCIP_Bool *success)
    Definition: heur_dks.c:1067
    #define DEFAULT_USEBESTSOL
    Definition: heur_dks.c:102
    #define DEFAULT_REDCOSTSORT
    Definition: heur_dks.c:103
    static SCIP_DECL_HEURCOPY(heurCopyDKS)
    Definition: heur_dks.c:1735
    static SCIP_RETCODE countKernelVariables(SCIP *scip, SCIP_VAR **vars, SCIP_SOL *bestcurrsol, SCIP_HASHMAP *lbvarmap, SCIP_Bool twolevel, SCIP_Bool usebestsol, SCIP_Bool usetransprob, SCIP_Bool usetranslb, int *bw_ncontkernelvars, int *bw_ncontnonkernelvars, int *bw_nkernelvars, int *bw_nnonkernelvars, int *bw_nintkernelvars, int *bw_nintnonkernelvars, int *ncontkernelvars, int *ncontnonkernelvars, int *nkernelvars, int *nnonkernelvars, int *nintkernelvars, int *nintnonkernelvars, int *block2index, int *varlabels, int blklbl_offset, int nvars)
    Definition: heur_dks.c:240
    #define DEFAULT_PRIMALONLY
    Definition: heur_dks.c:104
    static SCIP_RETCODE freeBucketlist(BUCKETLIST **bucketlist, int nbuckets)
    Definition: heur_dks.c:1043
    static SCIP_RETCODE addUseConstraint(BUCKET *bucket)
    Definition: heur_dks.c:1637
    static SCIP_RETCODE initBucketlist(SCIP *scip, BUCKETLIST **bucketlist, int nbuckets)
    Definition: heur_dks.c:1015
    #define HEUR_FREQ
    Definition: heur_dks.c:83
    #define DEFAULT_USEDECOMP
    Definition: heur_dks.c:101
    static SCIP_RETCODE fillKernels(SCIP *scip, SCIP_VAR **vars, SCIP_VAR **binintvars, SCIP_VAR ***bw_contkernelvars, SCIP_VAR ***bw_contnonkernelvars, SCIP_VAR ***bw_kernelvars, SCIP_VAR ***bw_nonkernelvars, SCIP_VAR ***bw_intkernelvars, SCIP_VAR ***bw_intnonkernelvars, SCIP_SOL *bestcurrsol, SCIP_HASHMAP *lbvarmap, SCIP_Bool twolevel, SCIP_Bool usebestsol, SCIP_Bool usetransprob, SCIP_Bool usetranslb, int *bw_contkernelcount, int *bw_contnonkernelcount, int *bw_kernelcount, int *bw_nonkernelcount, int *bw_intkernelcount, int *bw_intnonkernelcount, int *bw_ncontkernelvars, int *bw_ncontnonkernelvars, int *bw_nkernelvars, int *bw_nnonkernelvars, int *bw_nintkernelvars, int *bw_nintnonkernelvars, int *block2index, int *varlabels, int blklbl_offset, int nvars)
    Definition: heur_dks.c:369
    #define DEFAULT_LESSLOCKSKERNEL
    Definition: heur_dks.c:94
    #define DEFAULT_MAXBUCKS
    Definition: heur_dks.c:89
    #define HEUR_USESSUBSCIP
    Definition: heur_dks.c:87
    #define DEFAULT_RUNBINPROBSONLY
    Definition: heur_dks.c:107
    static SCIP_Bool isInCurrentLogBucket(SCIP *scip, SCIP_Real base, SCIP_Real redcost, SCIP_Real redcostmin, int currentindex, int nbuckets)
    Definition: heur_dks.c:662
    #define DEFAULT_USETRANSPROB
    Definition: heur_dks.c:95
    dks primal heuristic
    methods commonly used by primal heuristics
    memory allocation routines
    public methods for managing constraints
    public methods for managing events
    wrapper functions to map file i/o to standard or zlib file i/o
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    public data structures and miscellaneous methods
    methods for selecting (weighted) 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
    public methods for event handler plugins and event handlers
    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
    default SCIP plugins
    internal methods for storing primal CIP solutions
    int ncontbucketvars
    Definition: heur_dks.c:125
    SCIP_VAR ** bucketvars
    Definition: heur_dks.c:123
    BUCKETLIST * bucketlist
    Definition: heur_dks.c:119
    SCIP_VAR ** scip2sub
    Definition: heur_dks.c:130
    SCIP * subscip
    Definition: heur_dks.c:120
    SCIP_VAR ** sub2scip
    Definition: heur_dks.c:129
    SCIP_VAR ** intbucketvars
    Definition: heur_dks.c:124
    int number
    Definition: heur_dks.c:121
    int nbucketvars
    Definition: heur_dks.c:126
    SCIP_Bool twolevel
    Definition: heur_dks.c:128
    int nintbucketvars
    Definition: heur_dks.c:127
    SCIP_VAR ** contbucketvars
    Definition: heur_dks.c:122
    int nbuckets
    Definition: heur_dks.c:138
    BUCKET * buckets
    Definition: heur_dks.c:137
    SCIP * scip
    Definition: heur_dks.c:136
    #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_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_GAPLIMIT
    Definition: type_stat.h:56
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64