Scippy

SCIP

Solving Constraint Integer Programs

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