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