Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_dps.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_dps.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief dynamic partition search
    28 * @author Katrin Halbig
    29 *
    30 * The dynamic partition search (DPS) is a construction heuristic which additionally needs a
    31 * user decomposition with linking constraints only.
    32 *
    33 * This heuristic splits the problem into several sub-SCIPs according to the given decomposition. Thereby the linking constraints
    34 * with their right-hand and left-hand sides are also split. DPS searches for a partition of the sides on the blocks
    35 * so that a feasible solution is obtained.
    36 * For each block the parts of the original linking constraints are extended by slack variables. Moreover, the objective function
    37 * is replaced by the sum of these additional variables weighted by penalty parameters lambda. If all blocks have an optimal solution
    38 * of zero, the algorithm terminates with a feasible solution for the main problem. Otherwise, the partition and the penalty parameters
    39 * are updated, and the sub-SCIPs are solved again.
    40 *
    41 * A detailed description can be found in
    42 * K. Halbig, A. Göß and D. Weninger (2023). Exploiting user-supplied Decompositions inside Heuristics. https://optimization-online.org/?p=23386
    43 */
    44
    45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    46
    47#include "scip/heur_dps.h"
    48#include "scip/pub_dcmp.h"
    49#include "scip/pub_heur.h"
    50#include "scip/pub_misc.h"
    51#include "scip/scipdefplugins.h"
    52#include "scip/scip_cons.h"
    53#include "scip/scip_dcmp.h"
    54#include "scip/scip_exact.h"
    55#include "scip/scip_general.h"
    56#include "scip/scip_heur.h"
    57#include "scip/scip_mem.h"
    58#include "scip/scip_message.h"
    59#include "scip/scip_param.h"
    60#include "scip/scip_prob.h"
    61
    62
    63#define HEUR_NAME "dps"
    64#define HEUR_DESC "primal heuristic for decomposable MIPs"
    65#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    66#define HEUR_PRIORITY 75000
    67#define HEUR_FREQ -1
    68#define HEUR_FREQOFS 0
    69#define HEUR_MAXDEPTH -1
    70#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE | SCIP_HEURTIMING_AFTERNODE
    71#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    72
    73#define DEFAULT_MAXIT 50 /**< maximum number of iterations */
    74#define DEFAULT_PENALTY 100.0 /**< multiplier for absolute increase of penalty parameters */
    75
    76/* event handler properties */
    77#define EVENTHDLR_NAME "Dps"
    78#define EVENTHDLR_DESC "event handler for " HEUR_NAME " heuristic"
    79
    80/*
    81 * Data structures
    82 */
    83
    84/** primal heuristic data */
    85struct SCIP_HeurData
    86{
    87 SCIP_CONS** linkingconss; /**< linking constraints */
    88 int nlinking; /**< number of linking constraints */
    89 int nblocks; /**< number of blocks */
    90 int maxit; /**< maximal number of iterations */
    91 int timing; /**< should the heuristic run before or after the processing of the node?
    92 (0: before, 1: after, 2: both)*/
    93 SCIP_Real maxlinkscore; /**< maximal linking score of used decomposition (equivalent to percentage of linking constraints) */
    94 SCIP_Real penalty; /**< multiplier for absolute increase of penalty parameters */
    95 SCIP_Bool reoptimize; /**< should the problem get reoptimized with the original objective function? */
    96 SCIP_Bool reuse; /**< should solutions get reused in subproblems? */
    97 SCIP_Bool reoptlimits; /**< should strict limits for reoptimization be set? */
    98};
    99
    100/** data related to one block */
    102{
    103 SCIP* blockscip; /**< SCIP data structure */
    104 SCIP_VAR** slackvars; /**< slack variables */
    105 SCIP_CONS** linkingconss; /**< linking constraints */
    106 int* linkingindices; /**< indices of linking constraints in original problem */
    107 int nlinking; /**< number of linking constraints */
    108 int nblockvars; /**< number of block variables */
    109 int nslackvars; /**< number of slack variables */
    110 SCIP_Real* origobj; /**< original objective coefficients */
    111};
    113
    114/** data related to one linking constraint */
    116{
    117 SCIP_CONS* linkingcons; /**< corresponding linking constraint of original problem */
    118 SCIP_CONS** blockconss; /**< linking constraints of the blocks */
    119 SCIP_VAR** slacks; /**< slackvars of the blocks */
    120 SCIP_Real* minactivity; /**< minimal activity of constraint for each block */
    121 SCIP_Real* maxactivity; /**< maximal activity of constraint for each block */
    122 SCIP_Real* currentrhs; /**< current partition of rhs */
    123 SCIP_Real* currentlhs; /**< current partition of lhs */
    124 int* blocknumbers; /**< number of the blocks */
    125 int nblocks; /**< number of blocks in which this linking constraint participates; dimension of arrays */
    126 int nslacks; /**< number of slack variables */
    127 int nslacksperblock; /**< 2, if ranged constraint; 1, if only rhs or lhs */
    128 int lastviolations; /**< number of iterations in which the constraint was violated in succession */
    129 SCIP_Bool hasrhs; /**< has linking constraint finite right-hand side? */
    130 SCIP_Bool haslhs; /**< has linking constraint finite left-hand side? */
    131};
    132typedef struct Linking LINKING;
    133
    134/*
    135 * Local methods
    136 */
    137
    138/** assigns linking variables to last block
    139 *
    140 * The labels are copied to newdecomp and the linking variables are assigned to the last block (i.e., highest block label).
    141 * Constraint labels and statistics are recomputed.
    142 */
    143static
    145 SCIP* scip, /**< SCIP data structure */
    146 SCIP_DECOMP* newdecomp, /**< decomposition with assigned linking variables */
    147 SCIP_VAR** vars, /**< sorted array of variables */
    148 SCIP_CONS** conss, /**< sorted array of constraints */
    149 int* varlabels, /**< sorted array of variable labels */
    150 int* conslabels, /**< sorted array of constraint labels */
    151 int nvars, /**< number of variables */
    152 int nconss, /**< number of constraints */
    153 int nlinkvars /**< number of linking variables */
    154 )
    155{
    156 int newlabel;
    157 int v;
    158
    159 assert(scip != NULL);
    160 assert(newdecomp != NULL);
    161 assert(vars != NULL);
    162 assert(conss != NULL);
    163 assert(varlabels != NULL);
    164 assert(conslabels != NULL);
    165
    166 /* copy the labels */
    167 SCIP_CALL( SCIPdecompSetVarsLabels(newdecomp, vars, varlabels, nvars) );
    168 SCIP_CALL( SCIPdecompSetConsLabels(newdecomp, conss, conslabels, nconss) );
    169
    170 /* assign linking variables */
    171 newlabel = varlabels[nvars - 1]; /* take always label of last block */
    172 assert(newlabel >= 0);
    173 for( v = 0; v < nlinkvars; v++ )
    174 {
    175 SCIP_CALL( SCIPdecompSetVarsLabels(newdecomp, &vars[v], &newlabel, 1) );
    176 }
    177 SCIPdebugMsg(scip, "assigned %d linking variables\n", nlinkvars);
    178
    179 /* recompute constraint labels and statistics */
    180 SCIP_CALL( SCIPcomputeDecompConsLabels(scip, newdecomp, conss, nconss) );
    182 nlinkvars = SCIPdecompGetNBorderVars(newdecomp);
    183
    184 /* get new labels and sort */
    185 SCIPdecompGetConsLabels(newdecomp, conss, conslabels, nconss);
    186 SCIPdecompGetVarsLabels(newdecomp, vars, varlabels, nvars);
    187 SCIPsortIntPtr(conslabels, (void**)conss, nconss);
    188 SCIPsortIntPtr(varlabels, (void**)vars, nvars);
    189
    190 /* After assigning the linking variables, blocks can have zero constraints.
    191 * So the remaining variables are labeled as linking in SCIPcomputeDecompStats().
    192 * We assign this variables to the same label as above.
    193 */
    194 if( nlinkvars >= 1 )
    195 {
    196 assert(varlabels[0] == SCIP_DECOMP_LINKVAR);
    197 SCIPdebugMsg(scip, "assign again %d linking variables\n", nlinkvars);
    198
    199 for( v = 0; v < nlinkvars; v++ )
    200 {
    201 SCIP_CALL( SCIPdecompSetVarsLabels(newdecomp, &vars[v], &newlabel, 1) );
    202 }
    203 SCIP_CALL( SCIPcomputeDecompConsLabels(scip, newdecomp, conss, nconss) );
    205
    206 SCIPdecompGetConsLabels(newdecomp, conss, conslabels, nconss);
    207 SCIPdecompGetVarsLabels(newdecomp, vars, varlabels, nvars);
    208 SCIPsortIntPtr(conslabels, (void**)conss, nconss);
    209 SCIPsortIntPtr(varlabels, (void**)vars, nvars);
    210 }
    211 assert(varlabels[0] != SCIP_DECOMP_LINKVAR);
    212
    213 return SCIP_OKAY;
    214}
    215
    216/** creates a sub-SCIP and sets parameters */
    217static
    219 SCIP* scip, /**< main SCIP data structure */
    220 SCIP** subscip /**< pointer to store created sub-SCIP */
    221 )
    222{
    223 SCIP_Real infvalue;
    224
    225 assert(scip != NULL);
    226 assert(subscip != NULL);
    227
    228 /* create a new SCIP instance */
    229 SCIP_CALL( SCIPcreate(subscip) );
    231
    232 /* copy value for infinity */
    233 SCIP_CALL( SCIPgetRealParam(scip, "numerics/infinity", &infvalue) );
    234 SCIP_CALL( SCIPsetRealParam(*subscip, "numerics/infinity", infvalue) );
    235
    236 SCIP_CALL( SCIPcopyLimits(scip, *subscip) );
    237
    238 /* avoid recursive calls */
    239 SCIP_CALL( SCIPsetSubscipsOff(*subscip, TRUE) );
    240
    241 /* disable cutting plane separation */
    243
    244 /* disable expensive presolving */
    246
    247 /* disable expensive techniques */
    248 SCIP_CALL( SCIPsetIntParam(*subscip, "misc/usesymmetry", 0) );
    249
    250 /* do not abort subproblem on CTRL-C */
    251 SCIP_CALL( SCIPsetBoolParam(*subscip, "misc/catchctrlc", FALSE) );
    252
    253#ifdef SCIP_DEBUG
    254 /* for debugging, enable full output */
    255 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 5) );
    256 SCIP_CALL( SCIPsetIntParam(*subscip, "display/freq", 100000000) );
    257#else
    258 /* disable statistic timing inside sub SCIP and output to console */
    259 SCIP_CALL( SCIPsetIntParam(*subscip, "display/verblevel", 0) );
    260 SCIP_CALL( SCIPsetBoolParam(*subscip, "timing/statistictiming", FALSE) );
    261#endif
    262
    263 /* speed up sub-SCIP by not checking dual LP feasibility */
    264 SCIP_CALL( SCIPsetBoolParam(*subscip, "lp/checkdualfeas", FALSE) );
    265
    266 /* even when solving exactly, sub-SCIP heuristics should be run in floating-point mode, since the exactsol constraint
    267 * handler is in place to perform a final repair step
    268 */
    270
    271 return SCIP_OKAY;
    272}
    273
    274/** copies the given variables and constraints to the given sub-SCIP */
    275static
    277 SCIP* scip, /**< source SCIP */
    278 SCIP* subscip, /**< target SCIP */
    279 const char* name, /**< name for copied problem */
    280 SCIP_VAR** vars, /**< array of variables to copy */
    281 SCIP_CONS** conss, /**< array of constraints to copy */
    282 SCIP_HASHMAP* varsmap, /**< hashmap for copied variables */
    283 SCIP_HASHMAP* conssmap, /**< hashmap for copied constraints */
    284 int nvars, /**< number of variables to copy */
    285 int nconss, /**< number of constraints to copy */
    286 SCIP_Bool* success /**< was copying successful? */
    287 )
    288{
    289 SCIP_CONS* newcons;
    290 SCIP_VAR* newvar;
    291 int i;
    292
    293 assert(scip != NULL);
    294 assert(subscip != NULL);
    295 assert(vars != NULL);
    296 assert(conss != NULL);
    297 assert(varsmap != NULL);
    298 assert(conssmap != NULL);
    299 assert(success != NULL);
    300
    301 SCIPdebugMsg(scip, "copyToSubscip\n");
    302
    303 /* create problem in sub-SCIP */
    304 SCIP_CALL( SCIPcreateProb(subscip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
    305
    306 /* copy variables */
    307 for( i = 0; i < nvars; ++i )
    308 {
    309 SCIP_CALL( SCIPgetVarCopy(scip, subscip, vars[i], &newvar, varsmap, conssmap, FALSE, success) );
    310
    311 /* abort if variable was not successfully copied */
    312 if( !(*success) )
    313 {
    314 SCIPwarningMessage(scip, "Abort heuristic dps since not all variables were successfully copied.\n");
    315 SCIPABORT();
    316 return SCIP_OKAY;
    317 }
    318 }
    319 assert(nvars == SCIPgetNOrigVars(subscip));
    320
    321 /* copy constraints */
    322 for( i = 0; i < nconss; ++i )
    323 {
    324 assert(conss[i] != NULL);
    325 assert(!SCIPconsIsModifiable(conss[i]));
    326 assert(SCIPconsIsActive(conss[i]));
    327 assert(!SCIPconsIsDeleted(conss[i]));
    328
    329 /* copy the constraint */
    330 SCIP_CALL( SCIPgetConsCopy(scip, subscip, conss[i], &newcons, SCIPconsGetHdlr(conss[i]), varsmap, conssmap, NULL,
    331 SCIPconsIsInitial(conss[i]), SCIPconsIsSeparated(conss[i]), SCIPconsIsEnforced(conss[i]),
    332 SCIPconsIsChecked(conss[i]), SCIPconsIsPropagated(conss[i]), FALSE, FALSE,
    333 SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]), FALSE, FALSE, success) );
    334
    335 /* abort if constraint was not successfully copied */
    336 if( !(*success) )
    337 return SCIP_OKAY;
    338
    339 SCIP_CALL( SCIPaddCons(subscip, newcons) );
    340 SCIP_CALL( SCIPreleaseCons(subscip, &newcons) );
    341 }
    342
    343 /* block constraint contains variables which are not part of this block
    344 *
    345 * todo: maybe they are part of the block, but it is not recognized, because they are, for example, negated or aggregated.
    346 */
    347 if( nvars != SCIPgetNOrigVars(subscip) )
    348 *success = FALSE;
    349
    350 return SCIP_OKAY;
    351}
    352
    353/** creates the subscip for a given block */
    354static
    356 SCIP* scip, /**< SCIP data structure */
    357 BLOCKPROBLEM* blockproblem, /**< blockproblem that should be created */
    358 LINKING** linkings, /**< linkings that will be (partially) initialized */
    359 SCIP_CONS** conss, /**< sorted array of constraints of this block */
    360 SCIP_VAR** vars, /**< sorted array of variables of this block */
    361 int nconss, /**< number of constraints of this block */
    362 int nvars, /**< number of variables of this block */
    363 SCIP_CONS** linkingconss, /**< linking constraints in the original problem */
    364 int nlinking, /**< number of linking constraints in the original problem */
    365 int blocknumber, /**< number of block that should be created */
    366 SCIP_Bool* success /**< pointer to store whether creation was successful */
    367 )
    368{
    369 char name[SCIP_MAXSTRLEN];
    370 SCIP_HASHMAP* varsmap;
    371 SCIP_HASHMAP* conssmap;
    372 SCIP_VAR** consvars; /* all vars in original linking cons */
    373 SCIP_Real* consvals;
    374 int nconsvars;
    375 SCIP_VAR** blockvars; /* vars of current linking cons of current block */
    376 SCIP_Real* blockvals;
    377 int nblockvars;
    378 SCIP_VAR** subvars; /* all vars of subscip */
    379 int maxnconsvars; /* current size of arrays */
    380 int c;
    381 int v;
    382
    383 assert(scip != NULL);
    384 assert(blockproblem != NULL);
    385 assert(conss != NULL);
    386 assert(vars != NULL);
    387 assert(blockproblem->blockscip != NULL);
    388
    389 maxnconsvars = 20; /* start size; increase size if necessary */
    390
    391 SCIPdebugMsg(scip, "Create blockproblem %d\n", blocknumber);
    392
    393 /* create the variable/constraint mapping hash map */
    394 SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
    395 SCIP_CALL( SCIPhashmapCreate(&conssmap, SCIPblkmem(scip), nconss) );
    396
    397 /* get name of the original problem and add "comp_nr" */
    398 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_comp_%d", SCIPgetProbName(scip), blocknumber);
    399
    400 SCIP_CALL( copyToSubscip(scip, blockproblem->blockscip, name, vars, conss, varsmap, conssmap,
    401 nvars, nconss, success) );
    402 if( !(*success) )
    403 {
    404 SCIPdebugMsg(scip, "Copy to subscip failed\n");
    405 SCIPhashmapFree(&conssmap);
    406 SCIPhashmapFree(&varsmap);
    407
    408 return SCIP_OKAY;
    409 }
    410
    411 /* save number of variables that have a corresponding variable in original problem*/
    412 blockproblem->nblockvars = SCIPgetNVars(blockproblem->blockscip);
    413
    414 /* save original objective and set objective to zero */
    415 subvars = SCIPgetVars(blockproblem->blockscip);
    416 for( v = 0; v < nvars; v++ )
    417 {
    418 blockproblem->origobj[v] = SCIPvarGetObj(subvars[v]);
    419 SCIP_CALL( SCIPchgVarObj(blockproblem->blockscip, subvars[v], 0.0) );
    420 }
    421
    422 /* allocate memory */
    423 SCIP_CALL( SCIPallocBufferArray(blockproblem->blockscip, &blockvars, nvars + 2) ); /* two entries for the slack variables */
    424 SCIP_CALL( SCIPallocBufferArray(blockproblem->blockscip, &blockvals, nvars + 2) );
    425 SCIP_CALL( SCIPallocBufferArray(blockproblem->blockscip, &consvars, maxnconsvars) );
    426 SCIP_CALL( SCIPallocBufferArray(blockproblem->blockscip, &consvals, maxnconsvars) );
    427
    428 /* find and add parts of linking constraints */
    429 SCIPdebugMsg(scip, "add parts of linking constraints\n");
    430 for( c = 0; c < nlinking; c++ )
    431 {
    432 const char* conshdlrname;
    433 char consname[SCIP_MAXSTRLEN];
    434 SCIP_CONS* newcons;
    435 SCIP_Real rhs;
    436 SCIP_Real lhs;
    437 SCIP_Real minact;
    438 SCIP_Real maxact;
    439 SCIP_Bool mininfinite;
    440 SCIP_Bool maxinfinite;
    441
    442 assert(linkingconss[c] != NULL);
    443
    444 newcons = NULL;
    445
    446#ifdef SCIP_MORE_DEBUG
    447 SCIPdebugMsg(scip, "consider constraint %s\n", SCIPconsGetName(linkingconss[c]));
    448 SCIPdebugPrintCons(scip, linkingconss[c], NULL);
    449#endif
    450
    451 nblockvars = 0;
    452
    453 /* every constraint with linear representation is allowed */
    454 conshdlrname = SCIPconshdlrGetName(SCIPconsGetHdlr(linkingconss[c]));
    455 if( !( (strcmp(conshdlrname, "linear") == 0) || (strcmp(conshdlrname, "setppc") == 0)
    456 || (strcmp(conshdlrname, "logicor") == 0) || (strcmp(conshdlrname, "knapsack") == 0)
    457 || (strcmp(conshdlrname, "varbound") == 0) ) )
    458 {
    459 SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "Heuristic %s cannot handle linking constraints of type %s\n", HEUR_NAME, conshdlrname);
    460 /* TODO which other types can we handle/transform in a linear constraint? */
    461
    462 *success = FALSE;
    463 break; /* releases memory and breaks heuristic */
    464 }
    465
    466 SCIP_CALL( SCIPgetConsNVars(scip, linkingconss[c], &nconsvars, success) );
    467
    468 /* reallocate memory if we have more variables than maxnconsvars */
    469 if( nconsvars > maxnconsvars )
    470 {
    471 int newsize;
    472
    473 /* calculate new size */
    474 newsize = SCIPcalcMemGrowSize(scip, MAX(2 * maxnconsvars, nconsvars)); /* at least double size */
    475
    476 SCIP_CALL( SCIPreallocBufferArray(blockproblem->blockscip, &consvars, newsize) );
    477 SCIP_CALL( SCIPreallocBufferArray(blockproblem->blockscip, &consvals, newsize) );
    478 maxnconsvars = newsize;
    479 }
    480
    481 SCIP_CALL( SCIPgetConsVars(scip, linkingconss[c], consvars, nconsvars, success) );
    482 SCIP_CALL( SCIPgetConsVals(scip, linkingconss[c], consvals, nconsvars, success) );
    483
    484 if( !(*success) )
    485 {
    486 SCIPdebugMsg(scip, "Create blockproblem failed\n");
    487 break; /* releases memory and breaks heuristic */
    488 }
    489
    490 /* check if constraint contains variables of this block */
    491 for( v = 0; v < nconsvars; v++ )
    492 {
    493 if( SCIPhashmapExists(varsmap, (void*)consvars[v]) )
    494 {
    495 blockvars[nblockvars] = (SCIP_VAR*) SCIPhashmapGetImage(varsmap, (void*)consvars[v]);
    496 blockvals[nblockvars] = consvals[v];
    497 ++nblockvars;
    498 }
    499 /* handle negated variables*/
    500 else if( SCIPvarGetStatus(consvars[v]) == SCIP_VARSTATUS_NEGATED)
    501 {
    502 if( SCIPhashmapExists(varsmap, (void*)SCIPvarGetNegationVar(consvars[v])) ) /* negation exists in this block */
    503 {
    504 /* save negated variable */
    505 SCIP_VAR* origblockvar = (SCIP_VAR*) SCIPhashmapGetImage(varsmap, (void*)SCIPvarGetNegationVar(consvars[v]));
    506 SCIP_VAR* negblockvar = NULL;
    507 SCIP_CALL( SCIPgetNegatedVar(blockproblem->blockscip, origblockvar, &negblockvar) );
    508 blockvars[nblockvars] = negblockvar;
    509 blockvals[nblockvars] = consvals[v];
    510 ++nblockvars;
    511 }
    512 }
    513 }
    514
    515 /* continue with next linking constraint if it has no part in current block */
    516 if( nblockvars == 0 )
    517 continue;
    518
    519 /* get rhs and/or lhs */
    520 rhs = SCIPconsGetRhs(scip, linkingconss[c], success);
    521 if( !(*success) )
    522 {
    523 SCIPdebugMsg(scip, "Create blockproblem failed\n");
    524 return SCIP_OKAY;
    525 }
    526 lhs = SCIPconsGetLhs(scip, linkingconss[c], success);
    527 if( !(*success) )
    528 {
    529 SCIPdebugMsg(scip, "Create blockproblem failed\n");
    530 return SCIP_OKAY;
    531 }
    532 assert(!SCIPisInfinity(scip, rhs) || !SCIPisInfinity(scip, -lhs)); /* at least one side bounded */
    533 assert(SCIPisLE(scip, lhs, rhs));
    534
    535 if( !SCIPisInfinity(scip, rhs) )
    536 linkings[c]->hasrhs = TRUE;
    537 if( !SCIPisInfinity(scip, -lhs) )
    538 linkings[c]->haslhs = TRUE;
    539 if( !SCIPisInfinity(scip, rhs) && !SCIPisInfinity(scip, -lhs))
    540 linkings[c]->nslacksperblock = 2;
    541 else
    542 linkings[c]->nslacksperblock = 1;
    543
    544 /* add slack variable for rhs */
    545 if( linkings[c]->hasrhs )
    546 {
    547 /* slack variable z_r >= 0 */
    548 char varname[SCIP_MAXSTRLEN];
    549 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "z_r_%s", SCIPconsGetName(linkingconss[c]));
    550 SCIP_CALL( SCIPcreateVarBasic(blockproblem->blockscip, &blockvars[nblockvars], varname,
    552 blockvals[nblockvars] = -1.0;
    553 SCIP_CALL( SCIPaddVar(blockproblem->blockscip, blockvars[nblockvars]) );
    554#ifdef SCIP_MORE_DEBUG
    555 SCIPdebugMsg(scip, "Add variable %s\n", SCIPvarGetName(blockvars[nblockvars]));
    556#endif
    557 linkings[c]->slacks[linkings[c]->nslacks] = blockvars[nblockvars];
    558 blockproblem->slackvars[blockproblem->nslackvars] = blockvars[nblockvars];
    559 ++blockproblem->nslackvars;
    560 ++linkings[c]->nslacks;
    561 ++nblockvars;
    562 }
    563
    564 /* add slack variable for lhs */
    565 if( linkings[c]->haslhs )
    566 {
    567 /* slack variable z_l >= 0 */
    568 char varname[SCIP_MAXSTRLEN];
    569 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "z_l_%s", SCIPconsGetName(linkingconss[c]));
    570 SCIP_CALL( SCIPcreateVarBasic(blockproblem->blockscip, &blockvars[nblockvars], varname,
    572 blockvals[nblockvars] = 1.0;
    573 SCIP_CALL( SCIPaddVar(blockproblem->blockscip, blockvars[nblockvars]) );
    574#ifdef SCIP_MORE_DEBUG
    575 SCIPdebugMsg(scip, "Add variable %s\n", SCIPvarGetName(blockvars[nblockvars]));
    576#endif
    577 linkings[c]->slacks[linkings[c]->nslacks] = blockvars[nblockvars];
    578 blockproblem->slackvars[blockproblem->nslackvars] = blockvars[nblockvars];
    579 ++blockproblem->nslackvars;
    580 ++linkings[c]->nslacks;
    581 ++nblockvars;
    582 }
    583
    584 /* add linking constraint with slack variable */
    585 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s", SCIPconsGetName(linkingconss[c]));
    586 SCIP_CALL( SCIPcreateConsBasicLinear(blockproblem->blockscip, &newcons, consname, nblockvars, blockvars, blockvals, lhs, rhs) );
    587 SCIP_CALL( SCIPaddCons(blockproblem->blockscip, newcons) );
    588#ifdef SCIP_MORE_DEBUG
    589 SCIPdebugMsg(blockproblem->blockscip, "add constraint %s\n", SCIPconsGetName(newcons));
    590 SCIPdebugPrintCons(blockproblem->blockscip, newcons, NULL);
    591#endif
    592
    593 blockproblem->linkingconss[blockproblem->nlinking] = newcons;
    594 linkings[c]->blockconss[linkings[c]->nblocks] = newcons;
    595 linkings[c]->blocknumbers[linkings[c]->nblocks] = blocknumber;
    596 blockproblem->linkingindices[blockproblem->nlinking] = c;
    597
    598 /* calculate minimal und maximal activity (exclude slack variables) */
    599 minact = 0;
    600 maxact = 0;
    601 mininfinite = FALSE;
    602 maxinfinite = FALSE;
    603 for( v = 0; v < nblockvars - linkings[c]->nslacksperblock && (!mininfinite || !maxinfinite); v++ )
    604 {
    605 SCIP_Real lb;
    606 SCIP_Real ub;
    607 lb = SCIPvarGetLbGlobal(blockvars[v]);
    608 ub = SCIPvarGetUbGlobal(blockvars[v]);
    609
    610 if( blockvals[v] >= 0.0 )
    611 {
    612 mininfinite = (mininfinite || SCIPisInfinity(scip, -lb));
    613 maxinfinite = (maxinfinite || SCIPisInfinity(scip, ub));
    614 if( !mininfinite )
    615 minact += blockvals[v] * lb;
    616 if( !maxinfinite )
    617 maxact += blockvals[v] * ub;
    618 }
    619 else
    620 {
    621 mininfinite = (mininfinite || SCIPisInfinity(scip, ub));
    622 maxinfinite = (maxinfinite || SCIPisInfinity(scip, -lb));
    623 if( !mininfinite )
    624 minact += blockvals[v] * ub;
    625 if( !maxinfinite )
    626 maxact += blockvals[v] * lb;
    627 }
    628 }
    629
    630 if( mininfinite )
    631 linkings[c]->minactivity[linkings[c]->nblocks] = -SCIPinfinity(scip);
    632 else
    633 linkings[c]->minactivity[linkings[c]->nblocks] = minact;
    634 if( maxinfinite )
    635 linkings[c]->maxactivity[linkings[c]->nblocks] = SCIPinfinity(scip);
    636 else
    637 linkings[c]->maxactivity[linkings[c]->nblocks] = maxact;
    638 assert(SCIPisLE(scip, linkings[c]->minactivity[linkings[c]->nblocks], linkings[c]->maxactivity[linkings[c]->nblocks]));
    639
    640 linkings[c]->nblocks++;
    641 blockproblem->nlinking++;
    642
    643 for( v = 1; v <= linkings[c]->nslacksperblock; v++ )
    644 {
    645 SCIP_CALL( SCIPreleaseVar(blockproblem->blockscip, &blockvars[nblockvars - v]) );
    646 }
    647
    648 SCIP_CALL( SCIPreleaseCons(blockproblem->blockscip, &newcons) );
    649 }
    650 assert(blockproblem->nlinking <= nlinking);
    651
    652 /* free memory */
    653 SCIPfreeBufferArray(blockproblem->blockscip, &consvals);
    654 SCIPfreeBufferArray(blockproblem->blockscip, &consvars);
    655 SCIPfreeBufferArray(blockproblem->blockscip, &blockvals);
    656 SCIPfreeBufferArray(blockproblem->blockscip, &blockvars);
    657
    658 SCIPhashmapFree(&conssmap);
    659 SCIPhashmapFree(&varsmap);
    660
    661 return SCIP_OKAY;
    662}
    663
    664/** creates data structures and splits problem into blocks */
    665static
    667 SCIP* scip, /**< SCIP data structure */
    668 SCIP_HEURDATA* heurdata, /**< heuristic data */
    669 SCIP_DECOMP* decomp, /**< decomposition data structure */
    670 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    671 LINKING** linkings, /**< array of linking data structures */
    672 SCIP_VAR** vars, /**< sorted array of variables */
    673 SCIP_CONS** conss, /**< sorted array of constraints */
    674 SCIP_Bool* success /**< pointer to store whether splitting was successful */
    675 )
    676{
    677 int* nconssblock;
    678 int* nvarsblock;
    679 int conssoffset;
    680 int varsoffset;
    681 int i; /* blocknumber */
    682
    683 assert(scip != NULL);
    684 assert(heurdata != NULL);
    685 assert(vars != NULL);
    686 assert(conss != NULL);
    687
    688 SCIP_CALL( SCIPallocBufferArray(scip, &nvarsblock, heurdata->nblocks + 1) );
    689 SCIP_CALL( SCIPallocBufferArray(scip, &nconssblock, heurdata->nblocks + 1) );
    690 SCIP_CALL( SCIPdecompGetVarsSize(decomp, nvarsblock, heurdata->nblocks + 1) );
    691 SCIP_CALL( SCIPdecompGetConssSize(decomp, nconssblock, heurdata->nblocks + 1) );
    692 assert(0 == nvarsblock[0]);
    693
    694 varsoffset = 0;
    695 conssoffset = 0;
    696
    697 for( i = 0; i < heurdata->nblocks; i++)
    698 {
    699 conssoffset += nconssblock[i];
    700 varsoffset += nvarsblock[i];
    701
    702 SCIP_CALL( createBlockproblem(scip, blockproblem[i], linkings, &conss[conssoffset], &vars[varsoffset], nconssblock[i+1], nvarsblock[i+1],
    703 heurdata->linkingconss, heurdata->nlinking, i, success) );
    704 if( !(*success) )
    705 break;
    706 }
    707
    708 SCIPfreeBufferArray(scip, &nconssblock);
    709 SCIPfreeBufferArray(scip, &nvarsblock);
    710
    711 return SCIP_OKAY;
    712}
    713
    714/** rounds partition for one linking constraint to integer value if variables and coefficients are integer
    715 *
    716 * changes only currentrhs/currentlhs
    717 */
    718static
    720 SCIP* scip, /**< SCIP data structure */
    721 LINKING* linking, /**< one linking data structure */
    722 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    723 SCIP_Bool roundbyrhs /**< round by right hand side? */
    724 )
    725{
    726 SCIP_Real* fracPart;
    727 int* sorting;
    728 int* isinteger;
    729 SCIP_Real sumbefor; /* includes value at idx */
    730 SCIP_Real sumafter;
    731 SCIP_Real diff;
    732 int nnonintblocks; /* number of non integer blocks */
    733 int idx;
    734 int b;
    735 int i;
    736 int k;
    737
    738 assert(scip != NULL);
    739 assert(linking != NULL);
    740 assert(blockproblem != NULL);
    741
    742 nnonintblocks = 0;
    743 idx = 0;
    744
    745 SCIP_CALL( SCIPallocBufferArray(scip, &fracPart, linking->nblocks) );
    746 SCIP_CALL( SCIPallocBufferArray(scip, &sorting, linking->nblocks) );
    747 SCIP_CALL( SCIPallocBufferArray(scip, &isinteger, linking->nblocks) );
    748
    749 /* get integer blocks and fractional parts */
    750 for( b = 0; b < linking->nblocks; b++ )
    751 {
    752 SCIP* subscip;
    753 SCIP_CONS* blockcons;
    754 SCIP_VAR** blockvars;
    755 SCIP_Real* blockvals;
    756 int nblockvars;
    757 int length; /* number of block variables without slack variables */
    758 SCIP_Bool success;
    759
    760 subscip = blockproblem[linking->blocknumbers[b]]->blockscip;
    761 blockcons = linking->blockconss[b];
    762 sorting[b] = b; /* store current sorting to sort back */
    763
    764 SCIP_CALL( SCIPgetConsNVars(subscip, blockcons, &nblockvars, &success) );
    765 assert(success);
    766 SCIP_CALL( SCIPallocBufferArray(scip, &blockvars, nblockvars) );
    767 SCIP_CALL( SCIPallocBufferArray(scip, &blockvals, nblockvars) );
    768
    769 SCIP_CALL( SCIPgetConsVars(subscip, blockcons, blockvars, nblockvars, &success) );
    770 assert(success);
    771 SCIP_CALL( SCIPgetConsVals(subscip, blockcons, blockvals, nblockvars, &success) );
    772 assert(success);
    773
    774 /* get number of block variables in this constraint without slack variables */
    775 length = nblockvars - linking->nslacksperblock;
    776
    777 /* get blocks with integer value */
    778 isinteger[b] = 1;
    779 for( i = 0; i < length; i++ )
    780 {
    781 if( !SCIPvarIsIntegral(blockvars[i]) || !SCIPisIntegral(scip, blockvals[i]) )
    782 {
    783 isinteger[b] = 0;
    784 nnonintblocks++;
    785 break;
    786 }
    787 }
    788
    789 /* get fractional part of blockconstraints */
    790 if( roundbyrhs )
    791 fracPart[b] = linking->currentrhs[b] - floor(linking->currentrhs[b]); /* do not use SCIPfrac()! */
    792 else
    793 fracPart[b] = linking->currentlhs[b] - floor(linking->currentlhs[b]);
    794
    795 SCIPfreeBufferArray(scip, &blockvals);
    796 SCIPfreeBufferArray(scip, &blockvars);
    797 }
    798
    799 /* sort non-integer blocks to the front */
    800 SCIPsortIntIntReal(isinteger, sorting, fracPart, linking->nblocks);
    801
    802 /* sort by fractional part */
    803 SCIPsortRealInt(fracPart, sorting, nnonintblocks);
    804 SCIPsortRealInt(&fracPart[nnonintblocks], &sorting[nnonintblocks], linking->nblocks - nnonintblocks);
    805
    806 /* detect blocks for rounding down and rounding up:
    807 * integer blocks with small fractional parts are rounded down
    808 * integer blocks with big fractional parts are rounded up
    809 */
    810
    811 sumbefor = 0.0;
    812 sumafter = 0.0;
    813
    814 for( i = 0; i < linking->nblocks - nnonintblocks; i++ )
    815 sumafter += 1 - fracPart[nnonintblocks + i];
    816
    817 for( i = 0; i < linking->nblocks - nnonintblocks; i++ )
    818 {
    819 sumbefor += fracPart[nnonintblocks + i];
    820 sumafter -= 1 - fracPart[nnonintblocks + i];
    821
    822 if( sumbefor >= sumafter )
    823 {
    824 for( k = 0; k <= i; k++ )
    825 fracPart[nnonintblocks + k] = -fracPart[nnonintblocks + k];
    826
    827 for( k = i + 1; k < linking->nblocks - nnonintblocks; k++ )
    828 fracPart[nnonintblocks + k] = 1 - fracPart[nnonintblocks + k];
    829
    830 idx = i;
    831 break;
    832 }
    833 }
    834 diff = sumbefor - sumafter;
    835 assert(SCIPisGE(scip, diff, 0.0));
    836
    837 /* add difference to last non integer block */
    838 for( i = nnonintblocks - 1; i >= 0; i-- )
    839 {
    840 if( SCIPisGT(scip, diff, 0.0) )
    841 {
    842 fracPart[i] = diff;
    843 diff = 0;
    844 }
    845 else
    846 fracPart[i] = 0;
    847 }
    848
    849 /* add difference to last rounded down block if no non integer block exists */
    850 if( SCIPisGT(scip, diff, 0.0))
    851 {
    852 assert(nnonintblocks == 0);
    853 fracPart[idx] += diff;
    854 }
    855
    856 /* sort back */
    857 SCIPsortIntReal(sorting, fracPart, linking->nblocks);
    858
    859 /* round partition
    860 * if we have a ranged constraint, both sides get rounded in the same way
    861 */
    862 for( b = 0; b < linking->nblocks; b++ )
    863 {
    864 if( linking->hasrhs )
    865 linking->currentrhs[b] += fracPart[b];
    866
    867 if( linking->haslhs )
    868 linking->currentlhs[b] += fracPart[b];
    869 }
    870
    871 SCIPfreeBufferArray(scip, &isinteger);
    872 SCIPfreeBufferArray(scip, &sorting);
    873 SCIPfreeBufferArray(scip, &fracPart);
    874
    875 return SCIP_OKAY;
    876}
    877
    878/** calculates initial partition and sets rhs/lhs in blockproblems */
    879static
    881 SCIP* scip, /**< SCIP data structure of main scip */
    882 LINKING** linkings, /**< array of linking data structures */
    883 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    884 SCIP_HEURTIMING heurtiming, /**< current point in the node solving process */
    885 int nlinking, /**< number of linking constraints */
    886 SCIP_Bool* success /**< pointer to store whether initialization was successful */
    887 )
    888{
    889 LINKING* linking;
    890 SCIP_Real rhs;
    891 SCIP_Real lhs;
    892 SCIP_Real residualrhs;
    893 SCIP_Real residuallhs;
    894 SCIP_Real goalvalue;
    895 int c;
    896 int b;
    897
    898 assert(scip != NULL);
    899 assert(linkings != NULL);
    900 assert(blockproblem != NULL);
    901 assert(nlinking > 0);
    902
    903 SCIPdebugMsg(scip, "initialize partition\n");
    904
    905 /* for each linking constraint the rhs/lhs is split between the blocks */
    906 for( c = 0; c < nlinking; c++ )
    907 {
    908 linking = linkings[c];
    909 rhs = SCIPconsGetRhs(scip, linking->linkingcons, success);
    910 assert(*success);
    911 lhs = SCIPconsGetLhs(scip, linking->linkingcons, success);
    912 assert(*success);
    913 residualrhs = rhs;
    914 residuallhs = lhs;
    915
    916 /* LP value for each block plus part of remaining amount if sum is not equal to rhs/lhs */
    917 if( (heurtiming & SCIP_HEURTIMING_AFTERNODE) && (linking->hasrhs || linking->haslhs) )
    918 {
    919 SCIP_Real sumrhs = 0.0;
    920 SCIP_Real sumlhs = 0.0;
    921 for( b = 0; b < linking->nblocks; b++ )
    922 {
    923 SCIP_VAR** consvars;
    924 SCIP_Real* consvals;
    925 SCIP_CONS* cons;
    926 int nconsvars;
    927 SCIP_Real lpvalue;
    928 int i;
    929
    930 /* get variables of linking constraint of one block */
    931 cons = linking->blockconss[b];
    932 SCIP_CALL( SCIPgetConsNVars(blockproblem[linking->blocknumbers[b]]->blockscip, cons, &nconsvars, success) );
    933 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
    934 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
    935 SCIP_CALL( SCIPgetConsVars(blockproblem[linking->blocknumbers[b]]->blockscip, cons, consvars, nconsvars, success) );
    936 SCIP_CALL( SCIPgetConsVals(blockproblem[linking->blocknumbers[b]]->blockscip, cons, consvals, nconsvars, success) );
    937 assert(success);
    938
    939 /* calculate value of partition variable in lp solution */
    940 lpvalue = 0.0;
    941 for( i = 0; i < nconsvars - linking->nslacksperblock; i++ )
    942 {
    943 SCIP_VAR* origvar;
    944 SCIP_Real varlpvalue;
    945
    946 origvar = SCIPfindVar(scip, SCIPvarGetName(consvars[i]));
    947 if( origvar == NULL ) /* e.g. variable is negated */
    948 {
    949 *success = FALSE;
    950 break;
    951 }
    952 varlpvalue = SCIPvarGetLPSol(origvar);
    953 lpvalue += varlpvalue * consvals[i];
    954 }
    955
    956 SCIPfreeBufferArray(scip, &consvals);
    957 SCIPfreeBufferArray(scip, &consvars);
    958
    959 if( !*success )
    960 return SCIP_OKAY;
    961
    962 sumrhs += lpvalue;
    963 sumlhs += lpvalue;
    964
    965 /* set currentrhs/lhs at lp value */
    966 if( linking->hasrhs )
    967 linking->currentrhs[b] = lpvalue;
    968 if( linking->haslhs )
    969 linking->currentlhs[b] = lpvalue;
    970 }
    971 assert(SCIPisLE(scip, sumrhs, rhs));
    972 assert(SCIPisGE(scip, sumlhs, lhs));
    973
    974 /* distribute remaining amount */
    975 if( !SCIPisEQ(scip, rhs, sumrhs) && linking->hasrhs )
    976 {
    977 SCIP_Real diff;
    978 SCIP_Real part;
    979 SCIP_Real residual;
    980 diff = rhs - sumrhs;
    981 residual = 0.0;
    982
    983 for( b = 0; b < linking->nblocks; b++ )
    984 {
    985 goalvalue = linking->currentrhs[b] + ( diff / linking->nblocks ) + residual;
    986 part = MIN(goalvalue, linking->maxactivity[b]);
    987 residual = goalvalue - part;
    988 linking->currentrhs[b] = part;
    989 }
    990 if( !SCIPisZero(scip, residual) )
    991 linking->currentrhs[0] += residual;
    992 }
    993 if( !SCIPisEQ(scip, lhs, sumlhs) && linking->haslhs )
    994 {
    995 SCIP_Real diff;
    996 SCIP_Real part;
    997 SCIP_Real residual;
    998 diff = sumlhs - lhs; /* always positive*/
    999 residual = 0.0;
    1000
    1001 for( b = 0; b < linking->nblocks; b++ )
    1002 {
    1003 goalvalue = linking->currentlhs[b] - ( diff / linking->nblocks ) + residual;
    1004 part = MAX(goalvalue, linking->minactivity[b]);
    1005 residual = goalvalue - part;
    1006 linking->currentlhs[b] = part;
    1007 }
    1008 if( !SCIPisZero(scip, residual) )
    1009 linking->currentlhs[0] += residual;
    1010 }
    1011 }
    1012 /* equal parts for each block with respect to minimal/maximal activity */
    1013 else if( linking->hasrhs || linking->haslhs )
    1014 {
    1015 if( linking->hasrhs )
    1016 {
    1017 for( b = 0; b < linking->nblocks; b++ )
    1018 {
    1019 goalvalue = residualrhs / (linking->nblocks - b);
    1020 linking->currentrhs[b] = MIN(MAX(goalvalue, linking->minactivity[b]), linking->maxactivity[b]);
    1021 residualrhs -= linking->currentrhs[b];
    1022 }
    1023 /* add residual partition to first block */
    1024 linking->currentrhs[0] += residualrhs;
    1025 }
    1026 if( linking->haslhs )
    1027 {
    1028 for( b = 0; b < linking->nblocks; b++ )
    1029 {
    1030 goalvalue = residuallhs / (linking->nblocks - b);
    1031 linking->currentlhs[b] = MIN(MAX(goalvalue, linking->minactivity[b]), linking->maxactivity[b]);
    1032 residuallhs -= linking->currentlhs[b];
    1033 }
    1034 /* add residual partition to first block */
    1035 linking->currentlhs[0] += residuallhs;
    1036 }
    1037 }
    1038 else
    1039 {
    1040 assert(linking->nblocks == 0 && !SCIPconsIsChecked(linking->linkingcons));
    1041 }
    1042
    1043 SCIP_CALL( roundPartition(scip, linking, blockproblem, linking->hasrhs) );
    1044
    1045 /* set sides in blockproblem at initial partition */
    1046 for( b = 0; b < linking->nblocks; b++ )
    1047 {
    1048 if( linking->hasrhs )
    1049 {
    1050 SCIP_CALL( SCIPchgRhsLinear(blockproblem[linking->blocknumbers[b]]->blockscip,
    1051 linking->blockconss[b], linking->currentrhs[b]) );
    1052#ifdef SCIP_MORE_DEBUG
    1053 SCIPdebugMsg(scip, "change rhs of %s in block %d to %f\n",
    1054 SCIPconsGetName(linking->linkingcons), linking->blocknumbers[b], linking->currentrhs[b]);
    1055#endif
    1056 }
    1057 if( linking->haslhs )
    1058 {
    1059 SCIP_CALL( SCIPchgLhsLinear(blockproblem[linking->blocknumbers[b]]->blockscip,
    1060 linking->blockconss[b], linking->currentlhs[b]) );
    1061#ifdef SCIP_MORE_DEBUG
    1062 SCIPdebugMsg(scip, "change lhs of %s in block %d to %f\n",
    1063 SCIPconsGetName(linking->linkingcons), linking->blocknumbers[b], linking->currentlhs[b]);
    1064#endif
    1065 }
    1066 }
    1067 }
    1068
    1069 return SCIP_OKAY;
    1070}
    1071
    1072/** calculates shift */
    1073static
    1075 SCIP* scip, /**< SCIP data structure of main scip */
    1076 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    1077 LINKING* linking, /**< one linking data structure */
    1078 SCIP_Real** shift, /**< pointer to store direction vector */
    1079 int* nviolatedblocksrhs, /**< pointer to store number of blocks which violate rhs */
    1080 int* nviolatedblockslhs, /**< pointer to store number of blocks which violate lhs */
    1081 SCIP_Bool* update /**< should we update the partition? */
    1082 )
    1083{
    1084 int* nonviolatedblocksrhs;
    1085 int* nonviolatedblockslhs;
    1086 SCIP_Real sumviols = 0.0;
    1087 int v;
    1088
    1089 if( linking->hasrhs )
    1090 {
    1091 SCIP_CALL( SCIPallocBufferArray(scip, &nonviolatedblocksrhs, linking->nblocks) );
    1092 }
    1093 if( linking->haslhs )
    1094 {
    1095 SCIP_CALL( SCIPallocBufferArray(scip, &nonviolatedblockslhs, linking->nblocks) );
    1096 }
    1097
    1098 /* get violated blocks and calculate shift */
    1099 for( v = 0; v < linking->nblocks; v++ )
    1100 {
    1101 SCIP* subscip;
    1102 SCIP_SOL* subsol;
    1103 SCIP_Real slackval;
    1104
    1105 subscip = blockproblem[linking->blocknumbers[v]]->blockscip;
    1106 subsol = SCIPgetBestSol(subscip);
    1107
    1108 /* if we have ranged constraints, the slack variables of the rhs are in front;
    1109 * get slack variable of block; save violated blocks
    1110 */
    1111 if( linking->hasrhs )
    1112 {
    1113 slackval = SCIPgetSolVal(subscip, subsol, linking->slacks[v * linking->nslacksperblock]);
    1114
    1115 /* block is violated */
    1116 if( SCIPisPositive(scip, slackval) )
    1117 {
    1118 (*nviolatedblocksrhs)++;
    1119
    1120 (*shift)[v] += slackval;
    1121 sumviols += slackval;
    1122 }
    1123 else
    1124 {
    1125 nonviolatedblocksrhs[v - *nviolatedblocksrhs] = v; /*lint !e644*/
    1126 }
    1127 }
    1128 if( linking->haslhs )
    1129 {
    1130 slackval = SCIPgetSolVal(subscip, subsol, linking->slacks[(v * linking->nslacksperblock) + linking->nslacksperblock - 1]);
    1131
    1132 /* block is violated */
    1133 if( SCIPisPositive(scip, slackval) )
    1134 {
    1135 (*nviolatedblockslhs)++;
    1136
    1137 (*shift)[v] -= slackval;
    1138 sumviols -= slackval;
    1139 }
    1140 else
    1141 {
    1142 nonviolatedblockslhs[v - *nviolatedblockslhs] = v; /*lint !e644*/
    1143 }
    1144 }
    1145 }
    1146
    1147 /* linking constraint is in no block violated or always violated -> do not update partition */
    1148 if( *nviolatedblocksrhs + *nviolatedblockslhs == 0 ||
    1149 linking->nblocks == *nviolatedblocksrhs || linking->nblocks == *nviolatedblockslhs )
    1150 {
    1151 *update = FALSE;
    1152 /* free memory */
    1153 if( linking->haslhs )
    1154 SCIPfreeBufferArray(scip, &nonviolatedblockslhs);
    1155 if( linking->hasrhs )
    1156 SCIPfreeBufferArray(scip, &nonviolatedblocksrhs);
    1157 return SCIP_OKAY;
    1158 }
    1159
    1160 /* set values of non violated blocks */
    1161 if( SCIPisPositive(scip, sumviols) )
    1162 {
    1163 /* rhs of original linking constraint is violated */
    1164 SCIP_Real residual = sumviols;
    1165 SCIP_Real part;
    1166 SCIP_Real shift_tmp;
    1167
    1168 assert(linking->hasrhs);
    1169 assert(*nviolatedblocksrhs != 0);
    1170
    1171 /* substract from each non violated block the same amount with respect to minimal/maximal activity,
    1172 * so that the shift is zero in sum
    1173 */
    1174 for( v = 0; v < linking->nblocks - *nviolatedblocksrhs; v++ )
    1175 {
    1176 /* coverity[uninit_use] */
    1177 part = linking->currentrhs[nonviolatedblocksrhs[v]] - residual/(linking->nblocks - *nviolatedblocksrhs - v);
    1178 part = MIN(MAX(part, linking->minactivity[nonviolatedblocksrhs[v]]), linking->maxactivity[nonviolatedblocksrhs[v]]);
    1179 shift_tmp = part - linking->currentrhs[nonviolatedblocksrhs[v]];
    1180 residual += shift_tmp;
    1181 (*shift)[nonviolatedblocksrhs[v]] += shift_tmp;
    1182 }
    1183 if( !SCIPisZero(scip, residual) )
    1184 {
    1185 /* assign residual to ... */
    1186 if( linking->nblocks - *nviolatedblocksrhs == 1 )
    1187 (*shift)[nonviolatedblocksrhs[0] == 0 ? 1 : 0] -= residual; /* first violated block */
    1188 else
    1189 (*shift)[nonviolatedblocksrhs[0]] -= residual; /* first nonviolated block */
    1190 }
    1191 }
    1192 if( SCIPisNegative(scip, sumviols) )
    1193 {
    1194 /* lhs of original linking constraint is violated */
    1195 SCIP_Real residual = sumviols;
    1196 SCIP_Real part;
    1197 SCIP_Real shift_tmp;
    1198
    1199 assert(linking->haslhs);
    1200 assert(*nviolatedblockslhs != 0);
    1201
    1202 /* add to each non violated block the same amount with respect to minimal/maximal activity,
    1203 * so that the shift is zero in sum
    1204 */
    1205 for( v = 0; v < linking->nblocks - *nviolatedblockslhs; v++ )
    1206 {
    1207 /* coverity[uninit_use] */
    1208 part = linking->currentlhs[nonviolatedblockslhs[v]] - residual/(linking->nblocks - *nviolatedblockslhs - v);
    1209 part = MIN(MAX(part, linking->minactivity[nonviolatedblockslhs[v]]), linking->maxactivity[nonviolatedblockslhs[v]]);
    1210 shift_tmp = part - linking->currentlhs[nonviolatedblockslhs[v]];
    1211 residual += shift_tmp;
    1212 (*shift)[nonviolatedblockslhs[v]] += shift_tmp;
    1213 }
    1214 if( !SCIPisZero(scip, residual) )
    1215 {
    1216 /* assign residual to ... */
    1217 if( linking->nblocks - *nviolatedblockslhs == 1 )
    1218 (*shift)[nonviolatedblockslhs[0] == 0 ? 1 : 0] -= residual; /* first violated block */
    1219 else
    1220 (*shift)[nonviolatedblockslhs[0]] -= residual; /* first nonviolated block */
    1221 }
    1222 }
    1223
    1224 *update = TRUE;
    1225
    1226 /* free memory */
    1227 if( linking->haslhs )
    1228 SCIPfreeBufferArray(scip, &nonviolatedblockslhs);
    1229 if( linking->hasrhs )
    1230 SCIPfreeBufferArray(scip, &nonviolatedblocksrhs);
    1231
    1232 return SCIP_OKAY;
    1233}
    1234
    1235/** update partition */
    1236static
    1238 SCIP* scip, /**< SCIP data structure of main scip */
    1239 LINKING** linkings, /**< linking data structure */
    1240 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    1241 int** nviolatedblocksrhs, /**< pointer to store number of blocks which violate rhs */
    1242 int** nviolatedblockslhs, /**< pointer to store number of blocks which violate lhs */
    1243 int nlinking, /**< number of linking constraints */
    1244 int nblocks, /**< number of blocks */
    1245 int iteration, /**< number of iteration */
    1246 SCIP_Bool* oneupdate /**< is at least partition of one constraint updated? */
    1247 )
    1248{
    1249 SCIP_Real* shift; /* direction vector */
    1250 int v;
    1251 int c;
    1252 SCIP_Bool update; /* is partition of current constraint updated? */
    1253
    1254 assert(scip != NULL);
    1255 assert(linkings != NULL);
    1256 assert(blockproblem != NULL);
    1257 assert(iteration >= 0);
    1258 assert(!*oneupdate);
    1259
    1260 SCIP_CALL( SCIPallocBufferArray(scip, &shift, nblocks) ); /* allocate memory only once */
    1261
    1262 for( c = 0; c < nlinking; c++ )
    1263 {
    1264 LINKING* linking; /* one linking data structure */
    1265
    1266 linking = linkings[c];
    1267 (*nviolatedblocksrhs)[c] = 0;
    1268 (*nviolatedblockslhs)[c] = 0;
    1269 update = TRUE;
    1270 BMSclearMemoryArray(shift, linking->nblocks);
    1271 assert(nblocks >= linking->nblocks);
    1272
    1273 SCIP_CALL( calculateShift(scip, blockproblem, linking, &shift, &(*nviolatedblocksrhs)[c], &(*nviolatedblockslhs)[c], &update) );
    1274
    1275 if( !update )
    1276 continue;
    1277
    1278 *oneupdate = TRUE;
    1279
    1280#ifdef SCIP_DEBUG
    1281 SCIP_Real sum = 0.0;
    1282 /* check sum of shift; must be zero */
    1283 for( v = 0; v < linking->nblocks; v++ )
    1284 sum += shift[v];
    1285 assert(SCIPisFeasZero(scip, sum));
    1286#endif
    1287
    1288 /* add shift to both sides */
    1289 for( v = 0; v < linking->nblocks; v++)
    1290 {
    1291 if( linking->hasrhs )
    1292 linking->currentrhs[v] += shift[v];
    1293
    1294 if( linking->haslhs )
    1295 linking->currentlhs[v] += shift[v];
    1296 }
    1297
    1298 SCIP_CALL( roundPartition(scip, linking, blockproblem, ((linking->hasrhs && ((*nviolatedblocksrhs)[c] != 0)) || !linking->haslhs)) );
    1299
    1300 /* set sides in blockproblems to new partition */
    1301 for( v = 0; v < linking->nblocks; v++ )
    1302 {
    1303 SCIP* subscip;
    1304 subscip = blockproblem[linking->blocknumbers[v]]->blockscip;
    1305
    1306 if( linking->hasrhs )
    1307 {
    1308 SCIP_CALL( SCIPchgRhsLinear(subscip, linking->blockconss[v], linking->currentrhs[v]) );
    1309 }
    1310 if( linking->haslhs )
    1311 {
    1312 SCIP_CALL( SCIPchgLhsLinear(subscip, linking->blockconss[v], linking->currentlhs[v]) );
    1313 }
    1314 }
    1315 }
    1316
    1317 /* free memory */
    1318 SCIPfreeBufferArray(scip, &shift);
    1319
    1320 return SCIP_OKAY;
    1321}
    1322
    1323/** update penalty parameters lambda
    1324 *
    1325 * if a linking constraint is violated two times in succession, the corresponding penalty parameter is increased in each block
    1326 */
    1327static
    1329 SCIP* scip, /**< SCIP data structure */
    1330 SCIP_HEURDATA* heurdata, /**< heuristic data */
    1331 LINKING** linkings, /**< array of linking data structures */
    1332 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    1333 int* nviolatedblocksrhs, /**< number of blocks which violate rhs */
    1334 int* nviolatedblockslhs, /**< number of blocks which violate lhs */
    1335 int nlinking /**< number of linking constraints */
    1336 )
    1337{
    1338 SCIP_VAR* slackvar;
    1339 SCIP_Real old_obj;
    1340 SCIP_Real new_obj;
    1341 int c;
    1342 int b;
    1343
    1344 assert(scip != NULL);
    1345 assert(linkings != NULL);
    1346 assert(blockproblem != NULL);
    1347
    1348 for( c = 0; c < nlinking; c++ )
    1349 {
    1350 assert(nviolatedblocksrhs[c] >= 0);
    1351 assert(nviolatedblockslhs[c] >= 0);
    1352
    1353 /* skip constraint if it is not violated */
    1354 if( nviolatedblocksrhs[c] + nviolatedblockslhs[c] == 0 )
    1355 {
    1356 linkings[c]->lastviolations = 0; /* reset flag */
    1357 continue;
    1358 }
    1359
    1360 /* add number of violated blocks multiplied with parameter "penalty" to lambda (initial value is 1) */
    1361 for( b = 0; b < linkings[c]->nblocks; b++ )
    1362 {
    1363 SCIP* subscip;
    1364 subscip = blockproblem[linkings[c]->blocknumbers[b]]->blockscip;
    1365 assert(subscip != NULL);
    1366
    1367 if( linkings[c]->hasrhs && (nviolatedblocksrhs[c] >= 1) && (linkings[c]->lastviolations >= 1) )
    1368 {
    1369 slackvar = linkings[c]->slacks[b * linkings[c]->nslacksperblock];
    1370 old_obj = SCIPvarGetObj(slackvar);
    1371 new_obj = old_obj + heurdata->penalty * nviolatedblocksrhs[c];
    1372
    1373 SCIP_CALL( SCIPchgVarObj(subscip, slackvar, new_obj) );
    1374 }
    1375 if( linkings[c]->haslhs && (nviolatedblockslhs[c] >= 1) && (linkings[c]->lastviolations >= 1) )
    1376 {
    1377 slackvar = linkings[c]->slacks[b * linkings[c]->nslacksperblock + linkings[c]->nslacksperblock - 1];
    1378 old_obj = SCIPvarGetObj(slackvar);
    1379 new_obj = old_obj + heurdata->penalty * nviolatedblockslhs[c];
    1380
    1381 SCIP_CALL( SCIPchgVarObj(subscip, slackvar, new_obj) );
    1382 }
    1383 }
    1384
    1385 /* update number of violations in the last iterations */
    1386 linkings[c]->lastviolations += 1;
    1387 }
    1388
    1389 return SCIP_OKAY;
    1390}
    1391
    1392/** computes feasible solution from last stored solution for each block and adds it to the solution storage */
    1393static
    1395 LINKING** linkings, /**< array of linking data structures */
    1396 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    1397 int nblocks /**< number of blocks */
    1398 )
    1399{
    1400 SCIP_SOL** sols;
    1401 SCIP_SOL* sol; /* solution of block that will be repaired */
    1402 SCIP_SOL* newsol;
    1403 SCIP_VAR** blockvars;
    1404 SCIP_Real* blockvals;
    1405 int nsols;
    1406 int nvars;
    1407 int b;
    1408 int c;
    1409 int i;
    1410 SCIP_Bool success;
    1411
    1412 assert(linkings != NULL);
    1413 assert(blockproblem != NULL);
    1414
    1415 for( b = 0; b < nblocks; b++ )
    1416 {
    1417 SCIP* subscip;
    1418
    1419 subscip = blockproblem[b]->blockscip;
    1420 nsols = SCIPgetNSols(subscip);
    1421
    1422 /* no solution in solution candidate storage found */
    1423 if( nsols == 0 )
    1424 return SCIP_OKAY;
    1425
    1426 /* take last solution */
    1427 sols = SCIPgetSols(subscip);
    1428 sol = sols[nsols - 1];
    1429
    1430 /* copy the solution */
    1431 nvars = SCIPgetNVars(subscip);
    1432 blockvars = SCIPgetVars(subscip);
    1433 SCIP_CALL( SCIPallocBufferArray(subscip, &blockvals, nvars) );
    1434 SCIP_CALL( SCIPgetSolVals(subscip, sol, nvars, blockvars, blockvals) );
    1435 SCIP_CALL( SCIPcreateOrigSol(subscip, &newsol, NULL) );
    1436 SCIP_CALL( SCIPsetSolVals(subscip, newsol, nvars, blockvars, blockvals) );
    1437
    1438 /* correct each coupling constraint:
    1439 * lhs <= orig_var - z_r + z_l <= rhs
    1440 * adapt slack variables so that constraint is feasible
    1441 */
    1442 for( c = 0; c < blockproblem[b]->nlinking; c++ )
    1443 {
    1444 LINKING* linking; /* linking data structure of this constraint */
    1445 SCIP_VAR* rvar; /* slack variable z_r */
    1446 SCIP_VAR* lvar; /* slack variable z_l */
    1447 SCIP_Real rval; /* value of slack variable z_r */
    1448 SCIP_Real lval; /* value of slack variable z_l */
    1449 SCIP_Real activitycons; /* activity of constraint*/
    1450 SCIP_Real activity; /* activity of constraint without slack variables */
    1451 SCIP_Real rhs; /* current right hand side */
    1452 SCIP_Real lhs; /* current left hand side */
    1453
    1454 linking = linkings[blockproblem[b]->linkingindices[c]];
    1455 rhs = SCIPgetRhsLinear(subscip, blockproblem[b]->linkingconss[c]);
    1456 lhs = SCIPgetLhsLinear(subscip, blockproblem[b]->linkingconss[c]);
    1457 assert(SCIPisGE(subscip, rhs, lhs));
    1458
    1459 activitycons = SCIPgetActivityLinear(subscip, blockproblem[b]->linkingconss[c], sol);
    1460
    1461 /* get slack variables and subtract their value from the activity;
    1462 * calculate and set values of slack variables
    1463 */
    1464 for( i = 0; i < linking->nblocks; i++ )
    1465 {
    1466 if( linking->blocknumbers[i] == b )
    1467 {
    1468 if( linking->hasrhs && linking->haslhs )
    1469 {
    1470 rvar = linking->slacks[2 * i];
    1471 lvar = linking->slacks[2 * i + 1];
    1472 rval = SCIPgetSolVal(subscip, sol, rvar);
    1473 lval = SCIPgetSolVal(subscip, sol, lvar);
    1474 activity = activitycons + rval - lval;
    1475 SCIP_CALL( SCIPsetSolVal(subscip, newsol, rvar, MAX(0.0, activity - rhs)) );
    1476 SCIP_CALL( SCIPsetSolVal(subscip, newsol, lvar, MAX(0.0, lhs - activity)) );
    1477 }
    1478 else if( linking->hasrhs )
    1479 {
    1480 rvar = linking->slacks[i];
    1481 rval = SCIPgetSolVal(subscip, sol, rvar);
    1482 activity = activitycons + rval;
    1483 SCIP_CALL( SCIPsetSolVal(subscip, newsol, rvar, MAX(0.0, activity - rhs)) );
    1484 }
    1485 else /* linking->haslhs */
    1486 {
    1487 assert(linking->haslhs);
    1488 lvar = linking->slacks[i];
    1489 lval = SCIPgetSolVal(subscip, sol, lvar);
    1490 activity = activitycons - lval;
    1491 SCIP_CALL( SCIPsetSolVal(subscip, newsol, lvar, MAX(0.0, lhs - activity)) );
    1492 }
    1493 break;
    1494 }
    1495 }
    1496 }
    1497
    1498 SCIPdebugMsg(subscip, "Try adding solution with objective value %.2f\n", SCIPgetSolOrigObj(subscip, newsol));
    1499 SCIP_CALL( SCIPaddSolFree(subscip, &newsol, &success) );
    1500
    1501 if( !success )
    1502 SCIPdebugMsg(subscip, "Correcting solution failed\n"); /* maybe not better than old solutions */
    1503 else
    1504 SCIPdebugMsg(subscip, "Correcting solution successful\n");
    1505
    1506 SCIPfreeBufferArray(subscip, &blockvals);
    1507 }
    1508
    1509 return SCIP_OKAY;
    1510}
    1511
    1512/** reoptimizes the heuristic solution with original objective function */
    1513static
    1515 SCIP* scip, /**< SCIP data structure */
    1516 SCIP_HEUR* heur, /**< pointer to heuristic */
    1517 SCIP_SOL* sol, /**< heuristic solution */
    1518 BLOCKPROBLEM** blockproblem, /**< array of blockproblem data structures */
    1519 int nblocks, /**< number of blockproblems */
    1520 SCIP_Bool limits, /**< should strict limits be set? */
    1521 SCIP_SOL** newsol, /**< pointer to store improved solution */
    1522 SCIP_Bool* success /**< pointer to store whether reoptimization was successful */
    1523 )
    1524{
    1525 SCIP_Real time;
    1526 SCIP_Real timesubscip;
    1527 SCIP_Bool check;
    1528 int b;
    1529 int v;
    1530
    1531 assert(scip != NULL);
    1532 assert(heur != NULL);
    1533 assert(sol != NULL);
    1534 assert(blockproblem != NULL);
    1535
    1536 *success = FALSE;
    1537 check = FALSE;
    1538
    1539 /* get used time */
    1540 timesubscip = SCIPgetTotalTime(blockproblem[0]->blockscip);
    1541
    1542 /* for each blockproblem:
    1543 * - change back to original objective function
    1544 * - fix slack variables to zero
    1545 * - set limits and solve problem
    1546 */
    1547 for( b = 0; b < nblocks; b++ )
    1548 {
    1549 SCIP* subscip;
    1550 SCIP_VAR** blockvars;
    1551 SCIP_Real infvalue;
    1552 int nvars;
    1553 int nsols;
    1554
    1555 subscip = blockproblem[b]->blockscip;
    1556 blockvars = SCIPgetOrigVars(subscip);
    1557 nvars = SCIPgetNOrigVars(subscip);
    1558 nsols = 0;
    1559
    1560 /* in order to change objective function */
    1561 SCIP_CALL( SCIPfreeTransform(subscip) );
    1562
    1563 /* change back to original objective function */
    1564 for( v = 0; v < blockproblem[b]->nblockvars; v++ )
    1565 {
    1566 SCIP_CALL( SCIPchgVarObj(subscip, blockvars[v], blockproblem[b]->origobj[v]) );
    1567 }
    1568
    1569 /* fix slack variables to zero */
    1570 for( v = blockproblem[b]->nblockvars; v < nvars; v++ )
    1571 {
    1572 SCIP_CALL( SCIPchgVarUb(subscip, blockvars[v], 0.0) );
    1573 SCIP_CALL( SCIPchgVarLb(subscip, blockvars[v], 0.0) );
    1574 }
    1575
    1576 /* do not abort subproblem on CTRL-C */
    1577 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    1578
    1579 /* forbid recursive call of heuristics and separators solving sub-SCIPs */
    1580 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    1581
    1582#ifdef SCIP_DEBUG
    1583 /* for debugging, enable full output */
    1584 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    1585 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
    1586#else
    1587 /* disable statistic timing inside sub SCIP and output to console */
    1588 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    1589 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    1590#endif
    1591
    1592 /* disable cutting plane separation */
    1594
    1595 /* disable expensive presolving */
    1597
    1598 /* disable expensive techniques */
    1599 SCIP_CALL( SCIPsetIntParam(subscip, "misc/usesymmetry", 0) );
    1600
    1601 /* speed up sub-SCIP by not checking dual LP feasibility */
    1602 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    1603
    1604 /* copy value for infinity */
    1605 SCIP_CALL( SCIPgetRealParam(scip, "numerics/infinity", &infvalue) );
    1606 SCIP_CALL( SCIPsetRealParam(subscip, "numerics/infinity", infvalue) );
    1607
    1608 /* set limits; do not use more time in each subproblem than the heuristic has already used for first solution */
    1609 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    1610 if( limits )
    1611 {
    1612 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) );
    1613 SCIP_CALL( SCIPgetRealParam(subscip, "limits/time", &time) );
    1614 if( timesubscip < time - 1.0 )
    1615 {
    1616 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timesubscip + 1.0) );
    1617 }
    1618 SCIP_CALL( SCIPtransformProb(subscip) );
    1619 nsols = SCIPgetNSols(subscip);
    1620 /* one improving solution */
    1621 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", nsols + 1) );
    1622 }
    1623 else
    1624 {
    1625 /* only 50% of remaining time */
    1626 SCIP_CALL( SCIPgetRealParam(subscip, "limits/time", &time) );
    1627 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", time * 0.5) );
    1628 /* set big node limits */
    1629 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1000LL) );
    1630 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", 100LL) );
    1631 }
    1632
    1633 /* reoptimize problem */
    1634 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    1635
    1636 if( SCIPgetNSols(subscip) == 0 )
    1637 {
    1638 /* we found no solution */
    1639 return SCIP_OKAY;
    1640 }
    1641 else if( SCIPgetStatus(subscip) == SCIP_STATUS_BESTSOLLIMIT ||
    1642 SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL ||
    1643 SCIPgetNSols(subscip) > nsols )
    1644 {
    1645 check = TRUE;
    1646 }
    1647 }
    1648
    1649 if( !check )
    1650 {
    1651 /* we have no better solution */
    1652 return SCIP_OKAY;
    1653 }
    1654
    1655 /* create sol of main scip */
    1656 SCIP_CALL( SCIPcreateSol(scip, newsol, heur) );
    1657
    1658 /* copy solution to main scip */
    1659 for( b = 0; b < nblocks; b++ )
    1660 {
    1661 SCIP_SOL* blocksol;
    1662 SCIP_VAR** blockvars;
    1663 SCIP_Real* blocksolvals;
    1664 int nblockvars;
    1665
    1666 /* get solution of block variables (without slack variables) */
    1667 blocksol = SCIPgetBestSol(blockproblem[b]->blockscip);
    1668 blockvars = SCIPgetOrigVars(blockproblem[b]->blockscip);
    1669 nblockvars = blockproblem[b]->nblockvars;
    1670
    1671 SCIP_CALL( SCIPallocBufferArray(scip, &blocksolvals, nblockvars) );
    1672 SCIP_CALL( SCIPgetSolVals(blockproblem[b]->blockscip, blocksol, nblockvars, blockvars, blocksolvals) );
    1673
    1674 for( v = 0; v < nblockvars; v++ )
    1675 {
    1676 SCIP_VAR* origvar;
    1677
    1678 origvar = SCIPfindVar(scip, SCIPvarGetName(blockvars[v]));
    1679 SCIP_CALL( SCIPsetSolVal(scip, *newsol, origvar, blocksolvals[v]) );
    1680 }
    1681
    1682 SCIPfreeBufferArray(scip, &blocksolvals);
    1683 }
    1684
    1685 *success = TRUE;
    1686
    1687 return SCIP_OKAY;
    1688}
    1689
    1690
    1691/* ---------------- Callback methods of event handler ---------------- */
    1692
    1693/* exec the event handler
    1694 *
    1695 * interrupt solution process of sub-SCIP if dual bound is greater than zero and a solution is available
    1696 */
    1697static
    1699{
    1700 assert(eventhdlr != NULL);
    1701 assert(eventdata != NULL);
    1702 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    1703 assert(event != NULL);
    1705
    1706 SCIPdebugMsg(scip, "dual bound: %.2f\n", SCIPgetDualbound(scip));
    1707
    1709 {
    1710 SCIPdebugMsg(scip, "DPS: interrupt subscip\n");
    1712 }
    1713
    1714 return SCIP_OKAY;
    1715}
    1716
    1717
    1718/*
    1719 * Callback methods of primal heuristic
    1720 */
    1721
    1722/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    1723static
    1725{ /*lint --e{715}*/
    1726 assert(scip != NULL);
    1727 assert(heur != NULL);
    1728 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1729
    1730 /* call inclusion method of primal heuristic */
    1732
    1733 return SCIP_OKAY;
    1734}
    1735
    1736/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    1737static
    1739{ /*lint --e{715}*/
    1740 SCIP_HEURDATA* heurdata;
    1741
    1742 assert(heur != NULL);
    1743 assert(scip != NULL);
    1744
    1745 /* free heuristic data */
    1746 heurdata = SCIPheurGetData(heur);
    1747 assert(heurdata != NULL);
    1748
    1749 SCIPfreeBlockMemory(scip, &heurdata);
    1750 SCIPheurSetData(heur, NULL);
    1751
    1752 return SCIP_OKAY;
    1753}
    1754
    1755/** execution method of primal heuristic */
    1756static
    1758{ /*lint --e{715}*/
    1759 SCIP_DECOMP** alldecomps;
    1760 SCIP_DECOMP* decomp;
    1761 SCIP_DECOMP* assigneddecomp;
    1762 SCIP_VAR** vars;
    1763 SCIP_CONS** conss;
    1764 SCIP_VAR** sortedvars;
    1765 SCIP_CONS** sortedconss;
    1766 SCIP_HEURDATA* heurdata;
    1767 BLOCKPROBLEM** blockproblem;
    1768 LINKING** linkings;
    1769 int* sortedvarlabels;
    1770 int* sortedconslabels;
    1771 SCIP_EVENTHDLR* eventhdlr; /* event handler */
    1772 SCIP_Real memory; /* in MB */
    1773 SCIP_Real timelimit;
    1774 SCIP_Real allslacksval;
    1775 SCIP_Real blocksolval;
    1776 SCIP_STATUS status;
    1777 SCIP_Bool avoidmemout;
    1778 SCIP_Bool disablemeasures;
    1779 int maxgraphedge;
    1780 int ndecomps;
    1781 int nvars;
    1782 int nconss;
    1783 int nblocks;
    1784 SCIP_Bool success;
    1785 int b;
    1786 int c;
    1787 int k;
    1788
    1789 assert( heur != NULL );
    1790 assert( scip != NULL );
    1791 assert( result != NULL );
    1792
    1793 heurdata = SCIPheurGetData(heur);
    1794 assert(heurdata != NULL);
    1795
    1796 assigneddecomp = NULL;
    1797 blockproblem = NULL;
    1798 linkings = NULL;
    1799 eventhdlr = NULL;
    1800
    1801 *result = SCIP_DIDNOTRUN;
    1802
    1803 if( !((heurtiming & SCIP_HEURTIMING_BEFORENODE) && (heurdata->timing == 0 || heurdata->timing == 2))
    1804 && !((heurtiming & SCIP_HEURTIMING_AFTERNODE) && (heurdata->timing == 1 || heurdata->timing == 2)) )
    1805 {
    1806 return SCIP_OKAY;
    1807 }
    1808
    1809 /* call heuristic only once */
    1810 if( SCIPheurGetNCalls(heur) > 0 )
    1811 return SCIP_OKAY;
    1812
    1813 /* -------------------------------------------------------------------- */
    1814 SCIPdebugMsg(scip, "initialize dps heuristic\n");
    1815
    1816 /* take the first transformed decomposition */
    1817 SCIPgetDecomps(scip, &alldecomps, &ndecomps, FALSE);
    1818 if( ndecomps == 0 )
    1819 return SCIP_OKAY;
    1820
    1821 decomp = alldecomps[0];
    1822 assert(decomp != NULL);
    1823 SCIPdebugMsg(scip, "First transformed decomposition is selected\n");
    1824
    1825 nblocks = SCIPdecompGetNBlocks(decomp);
    1826 nconss = SCIPgetNConss(scip);
    1827 nvars = SCIPgetNVars(scip);
    1828
    1829 /* if problem has no constraints, no variables or less than two blocks, return */
    1830 if( nconss == 0 || nvars == 0 || nblocks <= 1 )
    1831 {
    1832 SCIPdebugMsg(scip, "problem has no constraints, no variables or less than two blocks\n");
    1833 return SCIP_OKAY;
    1834 }
    1835
    1836 /* estimate required memory for all blocks and terminate if not enough memory is available */
    1837 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memory) );
    1838 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    1839 if( avoidmemout && (((SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip))/1048576.0) * (nblocks/4.0 + 2) >= memory) )
    1840 {
    1841 SCIPdebugMsg(scip, "The estimated memory usage for %d blocks is too large.\n", nblocks);
    1842 return SCIP_OKAY;
    1843 }
    1844
    1845 /* we do not need the block decomposition graph and expensive measures of the decomposition statistics */
    1846 SCIP_CALL( SCIPgetIntParam(scip, "decomposition/maxgraphedge", &maxgraphedge) );
    1847 if( !SCIPisParamFixed(scip, "decomposition/maxgraphedge") )
    1848 {
    1849 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", 0) );
    1850 }
    1851 SCIP_CALL( SCIPgetBoolParam(scip, "decomposition/disablemeasures", &disablemeasures) );
    1852 if( !SCIPisParamFixed(scip, "decomposition/disablemeasures") )
    1853 {
    1854 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", TRUE) );
    1855 }
    1856
    1857 vars = SCIPgetVars(scip);
    1858 conss = SCIPgetConss(scip);
    1859 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedvars, vars, nvars) );
    1860 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
    1861 SCIP_CALL( SCIPallocBufferArray(scip, &sortedvarlabels, nvars) );
    1862 SCIP_CALL( SCIPallocBufferArray(scip, &sortedconslabels, nconss) );
    1863
    1864 /* get labels and sort in increasing order */
    1865 SCIPdecompGetVarsLabels(decomp, sortedvars, sortedvarlabels, nvars);
    1866 SCIPdecompGetConsLabels(decomp, sortedconss, sortedconslabels, nconss);
    1867 SCIPsortIntPtr(sortedvarlabels, (void**)sortedvars, nvars);
    1868 SCIPsortIntPtr(sortedconslabels, (void**)sortedconss, nconss);
    1869
    1870 if( sortedvarlabels[0] == SCIP_DECOMP_LINKVAR )
    1871 {
    1872 /* create new decomposition; don't change the decompositions in the decompstore */
    1874
    1875 SCIP_CALL( assignLinking(scip, assigneddecomp, sortedvars, sortedconss, sortedvarlabels, sortedconslabels, nvars, nconss, SCIPdecompGetNBorderVars(decomp)) );
    1876 assert(SCIPdecompGetNBlocks(decomp) >= SCIPdecompGetNBlocks(assigneddecomp));
    1877 decomp = assigneddecomp;
    1878
    1879 /* number of blocks can get smaller */
    1880 nblocks = SCIPdecompGetNBlocks(decomp);
    1881 }
    1882 else
    1883 {
    1884 /* The decomposition statistics were computed during transformation of the decomposition store.
    1885 * Since propagators can have changed the number of constraints/variables,
    1886 * the statistics are no longer up-to-date and have to be recomputed.
    1887 */
    1889 nblocks = SCIPdecompGetNBlocks(decomp);
    1890 }
    1891
    1892 /* reset parameters */
    1893 SCIP_CALL( SCIPsetIntParam(scip, "decomposition/maxgraphedge", maxgraphedge) );
    1894 SCIP_CALL( SCIPsetBoolParam(scip, "decomposition/disablemeasures", disablemeasures) );
    1895
    1896#ifdef SCIP_DEBUG
    1897 char buffer[SCIP_MAXSTRLEN];
    1898 SCIPdebugMsg(scip, "DPS used decomposition:\n%s\n", SCIPdecompPrintStats(decomp, buffer));
    1899#endif
    1900
    1901 /* check properties of used decomposition */
    1902 if( heurdata->maxlinkscore != 1.0 )
    1903 {
    1904 SCIP_Real linkscore;
    1905 int nlinkconss;
    1906
    1907 nlinkconss = SCIPdecompGetNBorderConss(decomp);
    1908
    1909 linkscore = (SCIP_Real)nlinkconss / (SCIP_Real)nconss;
    1910
    1911 if( linkscore > heurdata->maxlinkscore )
    1912 {
    1913 SCIPdebugMsg(scip, "decomposition has not the required properties\n");
    1914 goto TERMINATE;
    1915 }
    1916 }
    1917
    1918 if( sortedvarlabels[0] == SCIP_DECOMP_LINKVAR ||
    1919 sortedconslabels[0] != SCIP_DECOMP_LINKCONS ||
    1920 nblocks <= 1 )
    1921 {
    1922 SCIPdebugMsg(scip, "Problem has linking variables or no linking constraints or less than two blocks\n");
    1923 goto TERMINATE;
    1924 }
    1925
    1926 /* initialize heurdata */
    1927 heurdata->linkingconss = sortedconss;
    1928 heurdata->nlinking = SCIPdecompGetNBorderConss(decomp);
    1929 heurdata->nblocks = nblocks;
    1930
    1931 /* allocate memory for blockproblems and initialize partially */
    1932 SCIP_CALL( SCIPallocBufferArray(scip, &blockproblem, nblocks) );
    1933 for( b = 0; b < nblocks; b++ )
    1934 {
    1935 SCIP_CALL( SCIPallocBlockMemory(scip, &(blockproblem[b])) ); /*lint !e866*/
    1936 SCIP_CALL( createSubscip(scip, &blockproblem[b]->blockscip) );
    1937
    1938 SCIP_CALL( SCIPallocBufferArray(scip, &blockproblem[b]->linkingconss, heurdata->nlinking) );
    1939 SCIP_CALL( SCIPallocBufferArray(scip, &blockproblem[b]->linkingindices, heurdata->nlinking) );
    1940 SCIP_CALL( SCIPallocBufferArray(scip, &blockproblem[b]->slackvars, heurdata->nlinking * 2) ); /* maximum two slacks per linking constraint */
    1941 SCIP_CALL( SCIPallocBufferArray(scip, &blockproblem[b]->origobj, nvars) );
    1942 blockproblem[b]->nblockvars = 0;
    1943 blockproblem[b]->nlinking = 0;
    1944 blockproblem[b]->nslackvars = 0;
    1945 }
    1946
    1947 /* allocate memory for linkings and initialize partially */
    1948 SCIP_CALL( SCIPallocBufferArray(scip, &linkings, heurdata->nlinking) );
    1949 for( c = 0; c < heurdata->nlinking; c++ )
    1950 {
    1951 SCIP_CALL( SCIPallocBlockMemory(scip, &(linkings[c])) ); /*lint !e866*/
    1952 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->blockconss, heurdata->nblocks) );
    1953 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->slacks, heurdata->nblocks*2) ); /* maximum two slacks per block */
    1954 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->blocknumbers, heurdata->nblocks) );
    1955 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->minactivity, heurdata->nblocks) );
    1956 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->maxactivity, heurdata->nblocks) );
    1957
    1958 linkings[c]->linkingcons = heurdata->linkingconss[c];
    1959 linkings[c]->currentrhs = NULL;
    1960 linkings[c]->currentlhs = NULL;
    1961 linkings[c]->nblocks = 0;
    1962 linkings[c]->nslacks = 0;
    1963 linkings[c]->nslacksperblock = 0;
    1964 linkings[c]->lastviolations = 0;
    1965 linkings[c]->hasrhs = FALSE;
    1966 linkings[c]->haslhs = FALSE;
    1967 }
    1968
    1969 SCIP_CALL( createAndSplitProblem(scip, heurdata, decomp, blockproblem, linkings, sortedvars, sortedconss, &success) );
    1970 if( !success )
    1971 {
    1972 SCIPdebugMsg(scip, "Create and split problem failed\n");
    1973 goto TERMINATE;
    1974 }
    1975
    1976 /* allocate memory for current partition*/
    1977 for( c = 0; c < heurdata->nlinking; c++ )
    1978 {
    1979 if( linkings[c]->hasrhs )
    1980 {
    1981 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->currentrhs, linkings[c]->nblocks ) );
    1982 }
    1983
    1984 if( linkings[c]->haslhs )
    1985 {
    1986 SCIP_CALL( SCIPallocBufferArray(scip, &(linkings[c])->currentlhs, linkings[c]->nblocks ) );
    1987 }
    1988 }
    1989
    1990 /* initialize partition */
    1991 SCIP_CALL( initCurrent(scip, linkings, blockproblem, heurtiming, heurdata->nlinking, &success) );
    1992 if( !success )
    1993 {
    1994 SCIPdebugMsg(scip, "Initialization of partition failed\n");
    1995 goto TERMINATE;
    1996 }
    1997
    1998 /* ------------------------------------------------------------------------ */
    1999 SCIPdebugMsg(scip, "Start heuristik DPS\n");
    2000 *result = SCIP_DIDNOTFIND;
    2001
    2002 for( k = 0; k < heurdata->maxit; k++ )
    2003 {
    2004 /* do not exceed the timelimit */
    2005 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    2006 if( (timelimit - SCIPgetSolvingTime(scip)) <= 0 )
    2007 goto TERMINATE;
    2008
    2009 /* solve the subproblems */
    2010 allslacksval = 0.0;
    2011 for( b = 0; b < heurdata->nblocks; b++ )
    2012 {
    2013 SCIP* subscip;
    2014 subscip = blockproblem[b]->blockscip;
    2015
    2016 /* update time and memory limit of subproblem */
    2017 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
    2018
    2019 /* create event handler for LP events */
    2020 if( k == 0 )
    2021 {
    2022 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecDps, NULL) );
    2023 if( eventhdlr == NULL )
    2024 {
    2025 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
    2026 return SCIP_PLUGINNOTFOUND;
    2027 }
    2028 }
    2029
    2030 /* catch LP events of sub-SCIP */
    2031 SCIP_CALL( SCIPtransformProb(subscip) );
    2032 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
    2033
    2034 SCIPdebugMsg(scip, "Solve blockproblem %d\n", b);
    2035 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    2036
    2037 /* drop LP events of sub-SCIP */
    2038 SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
    2039
    2040 /* get status and objective value if available */
    2041 status = SCIPgetStatus(subscip);
    2042 if( status == SCIP_STATUS_INFEASIBLE )
    2043 {
    2044 SCIPdebugMsg(scip, "Subproblem is infeasible\n");
    2045 goto TERMINATE;
    2046 }
    2047 else if( status == SCIP_STATUS_UNBOUNDED )
    2048 {
    2049 SCIPdebugMsg(scip, "Subproblem is unbounded\n");
    2050 goto TERMINATE;
    2051 }
    2052 else if( SCIPgetNSols(subscip) >= 1 )
    2053 {
    2054 blocksolval = SCIPgetPrimalbound(subscip);
    2055
    2056 if( status == SCIP_STATUS_TIMELIMIT && !SCIPisZero(scip, blocksolval) )
    2057 {
    2058 SCIPdebugMsg(scip, "Subproblem reached timelimit without optimal solution\n");
    2059 goto TERMINATE;
    2060 }
    2061 SCIPdebugMsg(scip, "Solution value: %f\n", blocksolval);
    2062 allslacksval += blocksolval;
    2063 }
    2064 else
    2065 {
    2066 SCIPdebugMsg(scip, "No subproblem solution available\n");
    2067 goto TERMINATE;
    2068 }
    2069 }
    2070
    2071 /* all slack variables are zero -> we found a feasible solution */
    2072 if( SCIPisZero(scip, allslacksval) )
    2073 {
    2074 SCIP_SOL* newsol;
    2075
    2076 SCIPdebugMsg(scip, "Feasible solution found after %i iterations\n", k);
    2077
    2078 /* create new solution */
    2079 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
    2080 for( b = 0; b < heurdata->nblocks; b++ )
    2081 {
    2082 SCIP_SOL* blocksol;
    2083 SCIP_VAR** blockvars;
    2084 SCIP_Real* blocksolvals;
    2085 int nblockvars;
    2086
    2087 /* get solution of block variables (without slack variables) */
    2088 blocksol = SCIPgetBestSol(blockproblem[b]->blockscip);
    2089 blockvars = SCIPgetOrigVars(blockproblem[b]->blockscip);
    2090 nblockvars = blockproblem[b]->nblockvars;
    2091
    2092 SCIP_CALL( SCIPallocBufferArray(scip, &blocksolvals, nblockvars) );
    2093 SCIP_CALL( SCIPgetSolVals(blockproblem[b]->blockscip, blocksol, nblockvars, blockvars, blocksolvals) );
    2094
    2095 for( c = 0; c < nblockvars; c++ )
    2096 {
    2097 SCIP_VAR* origvar;
    2098
    2099 origvar = SCIPfindVar(scip, SCIPvarGetName(blockvars[c]));
    2100 SCIP_CALL( SCIPsetSolVal(scip, newsol, origvar, blocksolvals[c]) );
    2101 }
    2102
    2103 SCIPfreeBufferArray(scip, &blocksolvals);
    2104 }
    2105
    2106 /* if reoptimization is activated, fix partition and reoptimize with original objective function */
    2107 if( heurdata->reoptimize )
    2108 {
    2109 SCIP_SOL* improvedsol = NULL;
    2110 SCIP_CALL( reoptimize(scip, heur, newsol, blockproblem, heurdata->nblocks, heurdata->reoptlimits, &improvedsol, &success) );
    2111 assert(improvedsol != NULL || success == FALSE);
    2112
    2113 if( success )
    2114 {
    2115 SCIP_CALL( SCIPtrySolFree(scip, &improvedsol, TRUE, FALSE, TRUE, TRUE, TRUE, &success) );
    2116 if( success )
    2117 {
    2118 SCIPdebugMsg(scip, "Reoptimizing solution successful\n");
    2119 *result = SCIP_FOUNDSOL;
    2120 }
    2121 }
    2122 }
    2123
    2124 /* if reoptimization is turned off or reoptimization found no solution, try initial solution */
    2125 if( *result != SCIP_FOUNDSOL )
    2126 {
    2127 SCIPdebugMsg(scip, "Solution has value: %.2f\n", SCIPgetSolOrigObj(scip, newsol));
    2128 SCIP_CALL( SCIPtrySolFree(scip, &newsol, TRUE, FALSE, TRUE, TRUE, TRUE, &success) );
    2129 if( success )
    2130 {
    2131 SCIPdebugMsg(scip, "Solution copy successful\n");
    2132 *result = SCIP_FOUNDSOL;
    2133 }
    2134 }
    2135 else
    2136 {
    2137 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
    2138 }
    2139
    2140 goto TERMINATE;
    2141 }
    2142 /* current partition is not feasible:
    2143 * - update partition
    2144 * - update penalty parameters lambda
    2145 * - reuse last solution
    2146 */
    2147 else
    2148 {
    2149 int* nviolatedblocksrhs; /* number of blocks which violate rhs for each linking constraint */
    2150 int* nviolatedblockslhs; /* number of blocks which violate lhs for each linking constraint */
    2151 SCIP_Bool update = FALSE;
    2152
    2153 SCIP_CALL( SCIPallocBufferArray(scip, &nviolatedblocksrhs, heurdata->nlinking) );
    2154 SCIP_CALL( SCIPallocBufferArray(scip, &nviolatedblockslhs, heurdata->nlinking) );
    2155 BMSclearMemoryArray(nviolatedblocksrhs, heurdata->nlinking);
    2156 BMSclearMemoryArray(nviolatedblockslhs, heurdata->nlinking);
    2157
    2158 SCIPdebugMsg(scip, "update partition\n");
    2159 SCIP_CALL( updatePartition(scip, linkings, blockproblem, &nviolatedblocksrhs, &nviolatedblockslhs,
    2160 heurdata->nlinking, nblocks, k, &update) );
    2161
    2162 /* terminate if partition is not updated */
    2163 if( !update )
    2164 {
    2165 SCIPfreeBufferArray(scip, &nviolatedblockslhs);
    2166 SCIPfreeBufferArray(scip, &nviolatedblocksrhs);
    2167 goto TERMINATE;
    2168 }
    2169
    2170 /* in order to change objective function */
    2171 for( b = 0; b < heurdata->nblocks; b++ )
    2172 {
    2173 SCIP_CALL( SCIPfreeTransform(blockproblem[b]->blockscip) );
    2174 }
    2175
    2176 SCIPdebugMsg(scip, "update lambda\n");
    2177 SCIP_CALL( updateLambda(scip, heurdata, linkings, blockproblem, nviolatedblocksrhs, nviolatedblockslhs, heurdata->nlinking) );
    2178
    2179 if( heurdata->reuse )
    2180 {
    2181 /* reuse old solution in each block if available */
    2182 SCIP_CALL( reuseSolution(linkings, blockproblem, nblocks) );
    2183 }
    2184
    2185 SCIPfreeBufferArray(scip, &nviolatedblockslhs);
    2186 SCIPfreeBufferArray(scip, &nviolatedblocksrhs);
    2187 }
    2188 }
    2189 SCIPdebugMsg(scip, "maximum number of iterations reached\n");
    2190
    2191 /* ------------------------------------------------------------------------ */
    2192 /* free memory */
    2193TERMINATE:
    2194 if( linkings != NULL )
    2195 {
    2196 for( c = heurdata->nlinking - 1; c >= 0; c-- )
    2197 {
    2198 if( linkings[c]->currentlhs != NULL )
    2199 SCIPfreeBufferArray(scip, &(linkings[c])->currentlhs);
    2200
    2201 if( linkings[c]->currentrhs != NULL )
    2202 SCIPfreeBufferArray(scip, &(linkings[c])->currentrhs);
    2203 }
    2204
    2205 for( c = heurdata->nlinking - 1; c >= 0; c-- )
    2206 {
    2207 linkings[c]->linkingcons = NULL;
    2208 SCIPfreeBufferArray(scip, &(linkings[c])->maxactivity);
    2209 SCIPfreeBufferArray(scip, &(linkings[c])->minactivity);
    2210 SCIPfreeBufferArray(scip, &(linkings[c])->blocknumbers);
    2211 SCIPfreeBufferArray(scip, &(linkings[c])->slacks);
    2212 SCIPfreeBufferArray(scip, &(linkings[c])->blockconss);
    2213 SCIPfreeBlockMemory(scip, &(linkings[c])); /*lint !e866*/
    2214 }
    2215 SCIPfreeBufferArray(scip, &linkings);
    2216 }
    2217
    2218 if( blockproblem != NULL )
    2219 {
    2220 for( b = nblocks - 1; b >= 0; b-- )
    2221 {
    2222 SCIPfreeBufferArray(scip, &(blockproblem[b])->origobj);
    2223 SCIPfreeBufferArray(scip, &(blockproblem[b])->slackvars);
    2224 SCIPfreeBufferArray(scip, &(blockproblem[b])->linkingindices);
    2225 SCIPfreeBufferArray(scip, &(blockproblem[b])->linkingconss);
    2226 SCIP_CALL( SCIPfree(&blockproblem[b]->blockscip) );
    2227 SCIPfreeBlockMemory(scip, &(blockproblem[b])); /*lint !e866*/
    2228 }
    2229 SCIPfreeBufferArray(scip, &blockproblem);
    2230 }
    2231
    2232 if( assigneddecomp != NULL )
    2233 SCIPdecompFree(&assigneddecomp, SCIPblkmem(scip));
    2234
    2235 if( sortedconslabels != NULL )
    2236 SCIPfreeBufferArray(scip, &sortedconslabels);
    2237
    2238 if( sortedvarlabels != NULL )
    2239 SCIPfreeBufferArray(scip, &sortedvarlabels);
    2240
    2241 if( sortedconss != NULL )
    2242 SCIPfreeBufferArray(scip, &sortedconss);
    2243
    2244 if( sortedvars != NULL )
    2245 SCIPfreeBufferArray(scip, &sortedvars);
    2246
    2247 SCIPdebugMsg(scip, "Leave DPS heuristic\n");
    2248
    2249 return SCIP_OKAY;
    2250}
    2251
    2252
    2253/*
    2254 * primal heuristic specific interface methods
    2255 */
    2256
    2257/** creates the dps primal heuristic and includes it in SCIP */
    2259 SCIP* scip /**< SCIP data structure */
    2260 )
    2261{
    2262 SCIP_HEURDATA* heurdata;
    2263 SCIP_HEUR* heur;
    2264
    2265 /* create dps primal heuristic data */
    2266 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    2267
    2268 heur = NULL;
    2269
    2270 /* include primal heuristic */
    2273 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDps, heurdata) );
    2274
    2275 assert(heur != NULL);
    2276
    2277 /* primal heuristic is safe to use in exact solving mode */
    2278 SCIPheurMarkExact(heur);
    2279
    2280 /* set non fundamental callbacks via setter functions */
    2281 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDps) );
    2282 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDps) );
    2283
    2284 /* add dps primal heuristic parameters */
    2285 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxiterations",
    2286 "maximal number of iterations", &heurdata->maxit, FALSE, DEFAULT_MAXIT, 1, INT_MAX, NULL, NULL) );
    2287
    2288 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxlinkscore",
    2289 "maximal linking score of used decomposition (equivalent to percentage of linking constraints)",
    2290 &heurdata->maxlinkscore, FALSE, 1.0, 0.0, 1.0, NULL, NULL) );
    2291
    2292 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/penalty",
    2293 "multiplier for absolute increase of penalty parameters (0: no increase)",
    2294 &heurdata->penalty, FALSE, DEFAULT_PENALTY, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    2295
    2296 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reoptimize",
    2297 "should the problem get reoptimized with the original objective function?", &heurdata->reoptimize, FALSE, FALSE, NULL, NULL) );
    2298
    2299 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reuse",
    2300 "should solutions get reused in subproblems?", &heurdata->reuse, FALSE, FALSE, NULL, NULL) );
    2301
    2302 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reoptlimits",
    2303 "should strict limits for reoptimization be set?", &heurdata->reoptlimits, FALSE, TRUE, NULL, NULL) );
    2304
    2305 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/timing",
    2306 "should the heuristic run before or after the processing of the node? (0: before, 1: after, 2: both)",
    2307 &heurdata->timing, FALSE, 0, 0, 2, NULL, NULL) );
    2308
    2309 return SCIP_OKAY;
    2310}
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #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 SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
    SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    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 SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:3292
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_RETCODE SCIPcomputeDecompConsLabels(SCIP *scip, SCIP_DECOMP *decomp, SCIP_CONS **conss, int nconss)
    Definition: scip_dcmp.c:345
    void SCIPgetDecomps(SCIP *scip, SCIP_DECOMP ***decomps, int *ndecomps, SCIP_Bool original)
    Definition: scip_dcmp.c:263
    SCIP_RETCODE SCIPdecompSetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
    Definition: dcmp.c:124
    int SCIPdecompGetNBlocks(SCIP_DECOMP *decomp)
    Definition: dcmp.c:279
    SCIP_RETCODE SCIPdecompSetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
    Definition: dcmp.c:173
    SCIP_RETCODE SCIPdecompCreate(SCIP_DECOMP **decomp, BMS_BLKMEM *blkmem, int nblocks, SCIP_Bool original, SCIP_Bool benderslabels)
    Definition: dcmp.c:57
    SCIP_RETCODE SCIPcomputeDecompStats(SCIP *scip, SCIP_DECOMP *decomp, SCIP_Bool uselimits)
    Definition: scip_dcmp.c:1136
    char * SCIPdecompPrintStats(SCIP_DECOMP *decomp, char *strbuf)
    Definition: dcmp.c:455
    void SCIPdecompGetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
    Definition: dcmp.c:198
    SCIP_RETCODE SCIPdecompGetConssSize(SCIP_DECOMP *decomp, int *consssize, int nlabels)
    Definition: dcmp.c:349
    void SCIPdecompFree(SCIP_DECOMP **decomp, BMS_BLKMEM *blkmem)
    Definition: dcmp.c:99
    int SCIPdecompGetNBorderVars(SCIP_DECOMP *decomp)
    Definition: dcmp.c:379
    void SCIPdecompGetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
    Definition: dcmp.c:149
    SCIP_RETCODE SCIPdecompGetVarsSize(SCIP_DECOMP *decomp, int *varssize, int nlabels)
    Definition: dcmp.c:316
    SCIP_Bool SCIPdecompUseBendersLabels(SCIP_DECOMP *decomp)
    Definition: dcmp.c:269
    int SCIPdecompGetNBorderConss(SCIP_DECOMP *decomp)
    Definition: dcmp.c:394
    SCIP_Bool SCIPdecompIsOriginal(SCIP_DECOMP *decomp)
    Definition: dcmp.c:246
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    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
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
    Definition: scip_prob.c:119
    SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
    Definition: scip_prob.c:3189
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    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 SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
    Definition: scip_param.c:269
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    SCIP_RETCODE SCIPincludeHeurDps(SCIP *scip)
    Definition: heur_dps.c:2258
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
    Definition: scip_cons.c:2621
    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 SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
    Definition: scip_cons.c:2577
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    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 SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:293
    SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:333
    SCIP_RETCODE SCIPenableExactSolving(SCIP *scip, SCIP_Bool enable)
    Definition: scip_exact.c:151
    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
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPaddSolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool *stored)
    Definition: scip_sol.c:3909
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:831
    SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1846
    SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1662
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2931
    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_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3548
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetPrimalbound(SCIP *scip)
    SCIP_Real SCIPgetDualbound(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 SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(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_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5697
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5875
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
    Definition: var.c:23878
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
    Definition: scip_var.c:184
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
    void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)
    void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
    void SCIPsortIntIntReal(int *intarray1, int *intarray2, SCIP_Real *realarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE updateLambda(SCIP *scip, SCIP_HEURDATA *heurdata, LINKING **linkings, BLOCKPROBLEM **blockproblem, int *nviolatedblocksrhs, int *nviolatedblockslhs, int nlinking)
    Definition: heur_dps.c:1328
    static SCIP_DECL_HEURCOPY(heurCopyDps)
    Definition: heur_dps.c:1724
    static SCIP_RETCODE assignLinking(SCIP *scip, SCIP_DECOMP *newdecomp, SCIP_VAR **vars, SCIP_CONS **conss, int *varlabels, int *conslabels, int nvars, int nconss, int nlinkvars)
    Definition: heur_dps.c:144
    static SCIP_RETCODE roundPartition(SCIP *scip, LINKING *linking, BLOCKPROBLEM **blockproblem, SCIP_Bool roundbyrhs)
    Definition: heur_dps.c:719
    #define HEUR_TIMING
    Definition: heur_dps.c:70
    #define HEUR_FREQOFS
    Definition: heur_dps.c:68
    static SCIP_RETCODE updatePartition(SCIP *scip, LINKING **linkings, BLOCKPROBLEM **blockproblem, int **nviolatedblocksrhs, int **nviolatedblockslhs, int nlinking, int nblocks, int iteration, SCIP_Bool *oneupdate)
    Definition: heur_dps.c:1237
    #define HEUR_DESC
    Definition: heur_dps.c:64
    static SCIP_RETCODE createSubscip(SCIP *scip, SCIP **subscip)
    Definition: heur_dps.c:218
    #define DEFAULT_MAXIT
    Definition: heur_dps.c:73
    static SCIP_RETCODE initCurrent(SCIP *scip, LINKING **linkings, BLOCKPROBLEM **blockproblem, SCIP_HEURTIMING heurtiming, int nlinking, SCIP_Bool *success)
    Definition: heur_dps.c:880
    #define HEUR_DISPCHAR
    Definition: heur_dps.c:65
    #define HEUR_MAXDEPTH
    Definition: heur_dps.c:69
    #define HEUR_PRIORITY
    Definition: heur_dps.c:66
    static SCIP_DECL_EVENTEXEC(eventExecDps)
    Definition: heur_dps.c:1698
    static SCIP_RETCODE reuseSolution(LINKING **linkings, BLOCKPROBLEM **blockproblem, int nblocks)
    Definition: heur_dps.c:1394
    #define HEUR_NAME
    Definition: heur_dps.c:63
    static SCIP_RETCODE createBlockproblem(SCIP *scip, BLOCKPROBLEM *blockproblem, LINKING **linkings, SCIP_CONS **conss, SCIP_VAR **vars, int nconss, int nvars, SCIP_CONS **linkingconss, int nlinking, int blocknumber, SCIP_Bool *success)
    Definition: heur_dps.c:355
    static SCIP_RETCODE reoptimize(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol, BLOCKPROBLEM **blockproblem, int nblocks, SCIP_Bool limits, SCIP_SOL **newsol, SCIP_Bool *success)
    Definition: heur_dps.c:1514
    #define DEFAULT_PENALTY
    Definition: heur_dps.c:74
    #define EVENTHDLR_DESC
    Definition: heur_dps.c:78
    static SCIP_RETCODE createAndSplitProblem(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_DECOMP *decomp, BLOCKPROBLEM **blockproblem, LINKING **linkings, SCIP_VAR **vars, SCIP_CONS **conss, SCIP_Bool *success)
    Definition: heur_dps.c:666
    #define HEUR_FREQ
    Definition: heur_dps.c:67
    #define HEUR_USESSUBSCIP
    Definition: heur_dps.c:71
    static SCIP_DECL_HEUREXEC(heurExecDps)
    Definition: heur_dps.c:1757
    static SCIP_RETCODE calculateShift(SCIP *scip, BLOCKPROBLEM **blockproblem, LINKING *linking, SCIP_Real **shift, int *nviolatedblocksrhs, int *nviolatedblockslhs, SCIP_Bool *update)
    Definition: heur_dps.c:1074
    #define EVENTHDLR_NAME
    Definition: heur_dps.c:77
    static SCIP_RETCODE copyToSubscip(SCIP *scip, SCIP *subscip, const char *name, SCIP_VAR **vars, SCIP_CONS **conss, SCIP_HASHMAP *varsmap, SCIP_HASHMAP *conssmap, int nvars, int nconss, SCIP_Bool *success)
    Definition: heur_dps.c:276
    static SCIP_DECL_HEURFREE(heurFreeDps)
    Definition: heur_dps.c:1738
    dynamic partition search
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    SCIP_Real SCIPconsGetLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    Definition: misc_linear.c:112
    SCIP_RETCODE SCIPgetConsVals(SCIP *scip, SCIP_CONS *cons, SCIP_Real *vals, int varssize, SCIP_Bool *success)
    Definition: misc_linear.c:253
    SCIP_Real SCIPconsGetRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    Definition: misc_linear.c:48
    public methods for decompositions
    public methods for primal heuristics
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    public methods for constraint handler plugins and constraints
    public methods for decompositions
    public methods for exact solving
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for memory management
    public methods for message handling
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
    default SCIP plugins
    SCIP * blockscip
    Definition: heur_dps.c:103
    int nlinking
    Definition: heur_dps.c:107
    int * linkingindices
    Definition: heur_dps.c:106
    int nblockvars
    Definition: heur_dps.c:108
    SCIP_CONS ** linkingconss
    Definition: heur_dps.c:105
    int nslackvars
    Definition: heur_dps.c:109
    SCIP_VAR ** slackvars
    Definition: heur_dps.c:104
    SCIP_Real * origobj
    Definition: heur_dps.c:110
    SCIP_CONS * linkingcons
    Definition: heur_dps.c:117
    int nslacksperblock
    Definition: heur_dps.c:127
    SCIP_Bool haslhs
    Definition: heur_dps.c:130
    SCIP_Real * maxactivity
    Definition: heur_dps.c:121
    SCIP_Bool hasrhs
    Definition: heur_dps.c:129
    SCIP_Real * currentrhs
    Definition: heur_dps.c:122
    SCIP_VAR ** slacks
    Definition: heur_dps.c:119
    SCIP_Real * minactivity
    Definition: heur_dps.c:120
    int * blocknumbers
    Definition: heur_dps.c:124
    SCIP_Real * currentlhs
    Definition: heur_dps.c:123
    int nslacks
    Definition: heur_dps.c:126
    int lastviolations
    Definition: heur_dps.c:128
    int nblocks
    Definition: heur_dps.c:125
    SCIP_CONS ** blockconss
    Definition: heur_dps.c:118
    #define SCIP_DECOMP_LINKVAR
    Definition: type_dcmp.h:44
    #define SCIP_DECOMP_LINKCONS
    Definition: type_dcmp.h:45
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_LPSOLVED
    Definition: type_event.h:102
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ 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_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_UNBOUNDED
    Definition: type_stat.h:45
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    unsigned int SCIP_HEURTIMING
    Definition: type_timing.h:103
    #define SCIP_HEURTIMING_AFTERNODE
    Definition: type_timing.h:98
    #define SCIP_HEURTIMING_BEFORENODE
    Definition: type_timing.h:80
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57