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