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
1744
1745 /* call inclusion method of primal heuristic */
1747
1748 return SCIP_OKAY;
1749}
1750
1751
1752/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1753static
1755{ /*lint --e{715}*/
1757
1758 assert(heur != NULL);
1759 assert(scip != NULL);
1760
1761 heurdata = SCIPheurGetData(heur);
1762 assert(heurdata != NULL);
1763
1765 SCIPheurSetData(heur, NULL);
1766
1767 return SCIP_OKAY;
1768}
1769
1770/** execution method of primal heuristic */
1771static
1773{ /*lint --e{715}*/
1775 SCIP_DECOMP** alldecomps;
1776 SCIP_DECOMP* decomp = NULL;
1777 SCIP_HASHMAP* lbvarmap = NULL; /* variable map connecting transformed vars to their original lower bd */
1778 SCIP_CONSHDLR* conshdlr; /* constraint handler to check for indicator constraints */
1779 SCIP_VAR*** bw_contkernelvars = NULL;
1780 SCIP_VAR*** bw_contnonkernelvars = NULL;
1781 SCIP_VAR*** bw_kernelvars = NULL;
1782 SCIP_VAR*** bw_nonkernelvars = NULL;
1783 SCIP_VAR*** bw_intkernelvars = NULL;
1784 SCIP_VAR*** bw_intnonkernelvars = NULL;
1785 SCIP_VAR** vars = NULL;
1786 SCIP_VAR** contkernelvars = NULL;
1787 SCIP_VAR** contnonkernelvars = NULL;
1788 SCIP_VAR** kernelvars = NULL; /* just the bin kernel vars if problem includes bin AND int vars */
1789 SCIP_VAR** nonkernelvars = NULL; /* just the bin non kernel vars if problem includes bin AND int vars */
1790 SCIP_VAR** intkernelvars = NULL; /* used if problem includes binary AND integer variables */
1791 SCIP_VAR** intnonkernelvars = NULL; /* used if problem includes binary AND integer variables */
1792 SCIP_VAR** binintvars = NULL;
1793 SCIP_CONS** conss = NULL;
1794 SCIP_CONS** bucketconss = NULL;
1795 SCIP_Real gapfactor;
1796 SCIP_Real maxcontkernelsize;
1797 SCIP_Real maxcontnonkernelsize;
1798 SCIP_Real maxkernelsize;
1799 SCIP_Real maxnonkernelsize;
1800 SCIP_Real maxintkernelsize; /* used if problem includes binary AND integer variables */
1801 SCIP_Real maxintnonkernelsize;
1802 SCIP_Real memory;
1803 SCIP_Real bestlocval;
1804 SCIP_Real mipgap;
1805 SCIP_Real linkscore;
1806 SCIP_Real** bw_cont_redcost = NULL;
1807 SCIP_Real** bw_redcost = NULL;
1808 SCIP_Real** bw_int_redcost = NULL;
1809 SCIP_STATUS status;
1810 SCIP_Bool success;
1811 SCIP_Bool twolevel; /* clarifying if two level buckets are used */
1812 SCIP_Bool usebestsol;
1813 SCIP_SOL* bestcurrsol = NULL;
1814 BUCKETLIST* bucketlist = NULL;
1815 BUCKET* bucket;
1816 int* varlabels = NULL;
1817 int* conslabels = NULL;
1818 int* block2index = NULL;
1819 int* blocklabels = NULL;
1820 int* bw_ncontkernelvars = NULL;
1821 int* bw_ncontnonkernelvars = NULL;
1822 int* bw_nkernelvars = NULL;
1823 int* bw_nnonkernelvars = NULL;
1824 int* bw_nintkernelvars = NULL;
1825 int* bw_nintnonkernelvars = NULL;
1826 int* bw_contkernelcount = NULL;
1827 int* bw_contnonkernelcount = NULL;
1828 int* bw_kernelcount = NULL;
1829 int* bw_nonkernelcount = NULL;
1830 int* bw_intkernelcount = NULL;
1831 int* bw_intnonkernelcount = NULL;
1832 SCIP_Longint nodesleft;
1834 int gapcall;
1835 int blklbl_offset;
1836 int nblocks;
1837 int ndecomps;
1838 int nvars;
1839 int ncontkernelvars;
1840 int ncontnonkernelvars;
1841 int nkernelvars;
1842 int nnonkernelvars;
1843 int nintkernelvars;
1844 int nintnonkernelvars;
1845 int nbinvars;
1846 int nintvars;
1847 int nbinintvars;
1848 int nbuckets;
1849 int nconss;
1850 int nbestbucket;
1851 int nusedratios;
1852 int nblocklabels;
1853 int iters;
1854 int b;
1855 int i;
1856 int j;
1857 int k;
1858 int l;
1859 int m;
1860 int n;
1861
1862 assert(scip != NULL);
1863 assert(heur != NULL);
1864 assert(result != NULL);
1865
1866 heurdata = SCIPheurGetData(heur);
1867 assert(heurdata != NULL);
1868
1870
1871 bestlocval = SCIPinfinity(scip);
1872 twolevel = FALSE;
1873 success = TRUE;
1874
1875 gapfactor = 1.0;
1876 gapcall = 0;
1877 blklbl_offset = 0;
1878 ndecomps = 0;
1879 ncontkernelvars = 0;
1880 ncontnonkernelvars = 0;
1881 nkernelvars = 0;
1882 nnonkernelvars = 0;
1883 nintkernelvars = 0;
1884 nintnonkernelvars = 0;
1885 nbestbucket = -1;
1886 iters = 0;
1887 nblocklabels = 0;
1888
1889#ifdef DKS_WRITE_PROBLEMS
1890 SCIP_CALL( SCIPwriteOrigProblem(scip, "orig_problem.lp", NULL, FALSE) );
1891 SCIP_CALL( SCIPwriteTransProblem(scip, "trans_problem.lp", NULL, FALSE) );
1892#endif
1893
1894 /* exit DKS whenever indicator constraints are present as they can not handle fixed variables */
1895 conshdlr = SCIPfindConshdlr(scip, "indicator");
1896 if( conshdlr != NULL && SCIPconshdlrGetNConss(conshdlr) > 0 )
1897 return SCIP_OKAY;
1898
1899 /* exit DKS whenever there is not even an LP solution */
1901 return SCIP_OKAY;
1902
1903 /* do not run heuristic if it was not successful in previous calls */
1904 if( heurdata->uselesscall )
1905 return SCIP_OKAY;
1906
1907 heurdata->ncalls++;
1908
1909 /* extract variables, constraints and number of constraints */
1910 if( heurdata->usetransprob )
1911 {
1912 SCIP_VAR* tempvar = NULL; /* the transformed variable to each original variable */
1913
1914 /* Extract the decompositions of the transformed problem */
1915 SCIPgetDecomps(scip, &alldecomps, &ndecomps, FALSE);
1916
1917 /* get all transformed binary, integer, and continuous variables */
1922
1923 /* create and initialize the hashmap for the original lower bounds */
1925 for( i = 0; i < nvars; i++ )
1926 {
1927 SCIP_Real scalar;
1928 SCIP_Real constant;
1929 tempvar = vars[i];
1930
1931 SCIP_CALL( SCIPvarGetOrigvarSum(&tempvar, &scalar, &constant) );
1932
1933 if( tempvar != NULL )
1935 }
1936
1937 /* initialize the constraints of the transformed problem */
1938 nconss = SCIPgetNConss(scip);
1939 conss = SCIPgetConss(scip);
1940 }
1941 else
1942 {
1943 /* extract the decompositions of the original problem */
1944 SCIPgetDecomps(scip, &alldecomps, &ndecomps, TRUE);
1945
1946 /* get all original binary, integer, and continuous variables */
1951
1952 /* it is necessary to take the original constraints here, otherwise they can not be used later on */
1953 nconss = SCIPgetNOrigConss(scip);
1954 conss = SCIPgetOrigConss(scip);
1955 }
1956
1957 nbinintvars = nbinvars + nintvars;
1958
1959 if( ndecomps > 0 && heurdata->usedecomp )
1960 {
1961 /* take the first decomposition */
1962 decomp = alldecomps[0];
1963 SCIPdebugMsg(scip, "First original decomposition is selected\n");
1964 assert(decomp != NULL);
1965
1966 nblocks = SCIPdecompGetNBlocks(decomp);
1967 }
1968 else
1969 {
1970 SCIPdebugMsg(scip, "No decompositions available or wanted, going ahead without decomp\n");
1971 ndecomps = 0; /* set to 0 for later unnecessary ifs */
1972 nblocks = 0; /* 0 means no decomp in use */
1973 }
1974
1975 /* if problem has no constraints or no variables, terminate */
1976 if( nvars == 0 || nconss == 0 )
1977 {
1978 SCIPdebugMsg(scip, "problem has no constraints or variables\n");
1979 goto TERMINATE;
1980 }
1981
1982 /* verify if the heuristic should be used only for problems with binary and no continuous variables */
1983 if( heurdata->runbinprobsonly )
1984 {
1985 if( nbinvars == 0 || nbinintvars < nvars )
1986 {
1987 SCIPdebugMsg(scip, "do not run dks if continuous variables or only integer variables are present\n");
1988 goto TERMINATE;
1989 }
1990 }
1991
1992 /* estimate required memory and terminate if not enough memory is available */
1993 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memory) );
1994 if( (SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip)) / 1048576.0 >= memory )
1995 {
1996 SCIPdebugMsg(scip, "The estimated memory usage is too large.\n");
1997 goto TERMINATE;
1998 }
1999
2000 SCIP_CALL( SCIPallocBufferArray(scip, &varlabels, nvars) );
2001 SCIP_CALL( SCIPallocBufferArray(scip, &conslabels, nconss) );
2002
2003 if( ndecomps > 0 && heurdata->usedecomp )
2004 {
2005 /* extract the varlabels to identify linking variables */
2006 SCIPdecompGetVarsLabels(decomp, vars, varlabels, nvars);
2007 SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
2008
2009 /* prepare the distinct finding of blocklabels */
2010 SCIP_CALL( SCIPallocBufferArray(scip, &blocklabels, nblocks) );
2011
2012 /* check if linking score of the instance is sufficiently low to get called */
2013 SCIP_CALL( getLinkingScoreAndBlocklabels(blocklabels, varlabels, conslabels, &linkscore, &nblocklabels,
2014 nblocks, nvars, nconss) );
2015 if( linkscore > heurdata->maxlinkscore )
2016 {
2017 SCIPdebugMsg(scip, "decomposition has not required linking score\n");
2018 goto TERMINATE;
2019 }
2020
2021 if( nblocklabels > 0 )
2022 {
2023 SCIPsortInt(blocklabels, nblocklabels);
2024
2025 /* if it exists the blocklabel 0, we have to add an offset of 1 to store the linking variables at 0 */
2026 if( blocklabels[0] == 0 )
2027 blklbl_offset = 1;
2028
2029 /* fill the mapping of blocklabels to blockindices */
2030 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, blocklabels[nblocklabels - 1] + 1 + blklbl_offset) );
2031 }
2032 else
2033 {
2034 assert(nblocks == 0);
2035 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, 1) );
2036 }
2037
2038 block2index[0] = 0; /* SCIP_DECOMP_LINKVAR = -1, but are saved at index 0 */
2039 for( b = 0; b < nblocklabels; b++ )
2040 block2index[blocklabels[b] + blklbl_offset] = b + 1;
2041 }
2042 else
2043 {
2044 /* initialize dummy varlabels to avoid further distinctions in the following code*/
2045 int v;
2046
2047 for( v = 0; v < nvars; v++ )
2048 varlabels[v] = 0;
2049
2050 /* fill the mapping of blocklabels 0 to blockindices 0; nblocks = 0 in this case */
2051 assert(nblocks == 0);
2052 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &block2index, 1) );
2053 block2index[0] = 0;
2054 }
2055
2056 /* if necessary store the current best solution for later use */
2057 usebestsol = heurdata->usebestsol;
2058 if( heurdata->usebestsol )
2059 {
2060 if( SCIPgetNSols(scip) > 1 )
2061 bestcurrsol = SCIPgetBestSol(scip);
2062 else
2063 usebestsol = FALSE;
2064 }
2065
2066 /* initialize a kernel variable counter and a non kernel variable counter for each block + linking block (="+ 1") */
2067 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_ncontkernelvars, nblocks + 1) );
2068 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_ncontnonkernelvars, nblocks + 1) );
2069 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nkernelvars, nblocks + 1) );
2070 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nnonkernelvars, nblocks + 1) );
2071
2072 /* if there are either integer variables or binary variables only, just consider these */
2073 if( nbinvars == 0 || nintvars == 0 || !heurdata->usetwolevel )
2074 {
2075 SCIP_CALL( countKernelVariables(scip, vars, bestcurrsol, lbvarmap,
2076 twolevel, usebestsol, heurdata->usetransprob, heurdata->translbkernel,
2077 bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars, NULL, NULL,
2078 &ncontkernelvars, &ncontnonkernelvars, &nkernelvars, &nnonkernelvars, NULL, NULL,
2079 block2index, varlabels, blklbl_offset, nvars) );
2080
2081 SCIPdebugMsg(scip, "%d initial kernel variables\n", nkernelvars);
2082
2083 /* if every variable is zero or its lower bound in the lp solution, terminate */
2084 if( nkernelvars == 0 )
2085 {
2086 SCIPdebugMsg(scip, "No suitable variables for dks found. Leaving heuristic. \n");
2087 goto TERMINATE;
2088 }
2089 else if( nkernelvars > nnonkernelvars )
2090 /* @possible todo: if kernel vars >> nonkernel vars or >x% of all integer/binary variables => adjust */
2091 SCIPdebugMsg(scip, "There are more kernel variables than not in the kernel\n");
2092 }
2093 else
2094 {
2095 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nintkernelvars, nblocks + 1) );
2096 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nintnonkernelvars, nblocks + 1) );
2097
2098 /* assumption before kernel variable count: we use 2-level buckets */
2099 twolevel = TRUE;
2100
2101 SCIP_CALL( countKernelVariables(scip, vars, bestcurrsol, lbvarmap,
2102 twolevel, usebestsol, heurdata->usetransprob, heurdata->translbkernel,
2103 bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars, bw_nintkernelvars,
2104 bw_nintnonkernelvars, &ncontkernelvars, &ncontnonkernelvars, &nkernelvars, &nnonkernelvars,
2105 &nintkernelvars, &nintnonkernelvars, block2index, varlabels, blklbl_offset, nvars) );
2106
2107 SCIPdebugMsg(scip, "%d initial bin kernel vars\n%d initial int kernel vars\n", nkernelvars, nintkernelvars);
2108
2109 if( nkernelvars == 0 )
2110 {
2111 if( nintkernelvars == 0 )
2112 {
2113 SCIPdebugMsg(scip, "No suitable variables for the construction of a kernel. Leaving heuristic. \n");
2114 goto TERMINATE; /* @possible todo: if continuous variables are also considered, possibly continue here */
2115 }
2116 else
2117 {
2118 /* bin vars are all zero in lp sol -> 1-level buckets with int first and bin vars in kernel afterwards */
2119 nkernelvars = nintkernelvars;
2120 nnonkernelvars += nintnonkernelvars;
2121 nintkernelvars = 0;
2122 nintnonkernelvars = 0;
2123
2124 /* update the blockwise figures describing kernel sizes */
2125 for( b = 0; b < nblocks + 1; b++ )
2126 {
2127 bw_nkernelvars[b] = bw_nintkernelvars[b];
2128 bw_nnonkernelvars[b] += bw_nintnonkernelvars[b];
2129 bw_nintnonkernelvars[b] = 0;
2130 }
2131
2132 twolevel = FALSE;
2133 }
2134 }
2135 else if( nintkernelvars == 0 )
2136 {
2137 /* int vars are all zero in lp sol -> 1-level buckets with bin first and int vars in the kernel afterwards */
2138 nnonkernelvars += nintnonkernelvars;
2139 nintnonkernelvars = 0;
2140
2141 /* update the blockwise figures describing kernel sizes */
2142 for( b = 0; b < nblocks + 1; b++ )
2143 {
2144 bw_nnonkernelvars[b] += bw_nintnonkernelvars[b];
2145 bw_nintnonkernelvars[b] = 0;
2146 }
2147
2148 twolevel = FALSE;
2149 }
2150 else if( nkernelvars > nnonkernelvars || nintkernelvars > nintnonkernelvars )
2151 /* @potential todo: if kernel vars >> nonkernel vars or >x% of all integer/binary variables => adjust */
2152 SCIPdebugMsg(scip, "There are more kernel variables than not in the kernel\n");
2153 }
2154
2155 /* kernel initialization for all blocks + the linking block (= "+ 1") */
2156 SCIP_CALL( SCIPallocBufferArray(scip, &bw_contkernelvars, nblocks + 1) );
2157 SCIP_CALL( SCIPallocBufferArray(scip, &bw_contnonkernelvars, nblocks + 1) );
2158 SCIP_CALL( SCIPallocBufferArray(scip, &bw_kernelvars, nblocks + 1) );
2159 SCIP_CALL( SCIPallocBufferArray(scip, &bw_nonkernelvars, nblocks + 1) );
2160
2161 if( twolevel )
2162 {
2163 SCIP_CALL( SCIPallocBufferArray(scip, &bw_intkernelvars, nblocks + 1 ) );
2164 SCIP_CALL( SCIPallocBufferArray(scip, &bw_intnonkernelvars, nblocks + 1) );
2165 }
2166
2167 /* initialize kernel and non kernel variables for each block */
2168 for( b = 0; b < nblocks + 1; b++ )
2169 {
2170 int contblocksize = bw_ncontkernelvars[b] + bw_ncontnonkernelvars[b];
2171 int blocksize = bw_nkernelvars[b] + bw_nnonkernelvars[b];
2172
2173 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_contkernelvars[b]), contblocksize) );
2174 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_contnonkernelvars[b]), contblocksize) );
2175 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_kernelvars[b]), blocksize) );
2176 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_nonkernelvars[b]), blocksize) );
2177
2178 if( twolevel )
2179 {
2180 int intblocksize;
2181
2182 assert(bw_nintkernelvars != NULL);
2183 assert(bw_nintnonkernelvars != NULL);
2184
2185 intblocksize = bw_nintkernelvars[b] + bw_nintnonkernelvars[b];
2186
2187 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_intkernelvars[b]), intblocksize) );
2188 SCIP_CALL( SCIPallocBufferArray(scip, &(bw_intnonkernelvars[b]), intblocksize) );
2189 }
2190 }
2191
2192 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontkernelvars) < (ncontkernelvars + ncontnonkernelvars) )
2193 maxcontkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontkernelvars);
2194 else
2195 maxcontkernelsize = ncontkernelvars + ncontnonkernelvars;
2196
2197 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontnonkernelvars) < (ncontkernelvars + ncontnonkernelvars) )
2198 maxcontnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * ncontnonkernelvars);
2199 else
2200 maxcontnonkernelsize = ncontkernelvars + ncontnonkernelvars;
2201
2202 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nkernelvars) < (nkernelvars + nnonkernelvars) )
2203 maxkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nkernelvars);
2204 else
2205 maxkernelsize = nkernelvars + nnonkernelvars;
2206
2207 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nnonkernelvars) < (nkernelvars + nnonkernelvars) )
2208 maxnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nnonkernelvars);
2209 else
2210 maxnonkernelsize = nkernelvars + nnonkernelvars;
2211
2212 /* initialize the kernel and non kernel variable arrays (just binary (non/)kernel variables if 2-level buckets) */
2213 SCIP_CALL( SCIPallocBufferArray(scip, &contkernelvars, maxcontkernelsize) );
2214 SCIP_CALL( SCIPallocBufferArray(scip, &contnonkernelvars, maxcontnonkernelsize) );
2215 SCIP_CALL( SCIPallocBufferArray(scip, &kernelvars, maxkernelsize) );
2216 SCIP_CALL( SCIPallocBufferArray(scip, &nonkernelvars, maxnonkernelsize) );
2217
2218 /* include all binary AND integer variables as a separate array */
2220
2221 /* extract (potential) init kernel vars (value > 0) and not kernel vars for all blocks + the linking one (= "+ 1") */
2222 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_contkernelcount, nblocks + 1) );
2223 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_contnonkernelcount, nblocks + 1) );
2224 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_kernelcount, nblocks + 1) );
2225 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_nonkernelcount, nblocks + 1) );
2226
2227 maxintkernelsize = 0;
2228
2229 /* 2-level buckets are necessary */
2230 if( twolevel )
2231 {
2232 /* additionally determine maximal integer kernel size */
2233 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintkernelvars) < (nintkernelvars + nintnonkernelvars) )
2234 maxintkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintkernelvars);
2235 else
2236 maxintkernelsize = nintkernelvars + nintnonkernelvars;
2237
2238 if( (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintnonkernelvars) < (nintkernelvars + nintnonkernelvars) )
2239 maxintnonkernelsize = (int)SCIPfloor(scip, heurdata->kernelsizefactor * nintnonkernelvars);
2240 else
2241 maxintnonkernelsize = nintkernelvars + nintnonkernelvars;
2242
2243 /* additionally initialize the integer kernel and the non integer kernel variable arrays */
2244 SCIP_CALL( SCIPallocBufferArray(scip, &intkernelvars, maxintkernelsize) );
2245 SCIP_CALL( SCIPallocBufferArray(scip, &intnonkernelvars, maxintnonkernelsize) );
2246
2247 /* allocate memory for counting the pure integer variables for all blocks + the linking block (= "+ 1") */
2248 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_intkernelcount, nblocks + 1) );
2249 SCIP_CALL( SCIPallocClearBufferArray(scip, &bw_intnonkernelcount, nblocks + 1) );
2250
2251 /* filling of the kernels with the variables */
2252 SCIP_CALL( fillKernels(scip, vars, binintvars,
2253 bw_contkernelvars, bw_contnonkernelvars, bw_kernelvars, bw_nonkernelvars,
2254 bw_intkernelvars, bw_intnonkernelvars, bestcurrsol, lbvarmap, twolevel, usebestsol,
2255 heurdata->usetransprob, heurdata->translbkernel, bw_contkernelcount,
2256 bw_contnonkernelcount, bw_kernelcount, bw_nonkernelcount, bw_intkernelcount,
2257 bw_intnonkernelcount, bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars,
2258 bw_nintkernelvars, bw_nintnonkernelvars, block2index, varlabels, blklbl_offset, nvars, nbinintvars) );
2259 }
2260 else
2261 {
2262 /* filling of the kernels with the variables */
2263 SCIP_CALL( fillKernels(scip, vars, binintvars,
2264 bw_contkernelvars, bw_contnonkernelvars, bw_kernelvars, bw_nonkernelvars, NULL, NULL,
2265 bestcurrsol, lbvarmap, twolevel, usebestsol, heurdata->usetransprob,
2266 heurdata->translbkernel, bw_contkernelcount, bw_contnonkernelcount, bw_kernelcount,
2267 bw_nonkernelcount, NULL, NULL, bw_ncontkernelvars, bw_ncontnonkernelvars, bw_nkernelvars, bw_nnonkernelvars,
2268 NULL, NULL, block2index, varlabels, blklbl_offset, nvars, nbinintvars) );
2269 }
2270
2271 /* sorting of bucket variables according to the reduced costs in non-decreasing order */
2272 if( heurdata->redcostsort || heurdata->redcostlogsort )
2273 {
2274 SCIP_CALL( reducedCostSort(scip, bw_contnonkernelvars, bw_nonkernelvars, bw_intnonkernelvars,
2275 &bw_cont_redcost, &bw_redcost, &bw_int_redcost, bw_ncontnonkernelvars, bw_nnonkernelvars,
2276 bw_nintnonkernelvars, twolevel, nblocks) );
2277 }
2278
2279 /* initialization of the buckets */
2280 /* determine the amount of buckets needed */
2281 /* continuous variables are not included when calculating the number of buckets, since they are easier to handle */
2282 nusedratios = 0;
2283 if( twolevel )
2284 {
2285 SCIP_Real intratio;
2286 SCIP_Real binratio;
2287
2288 nbuckets = 0;
2289 for( b = 0; b < nblocks + 1; b++ )
2290 {
2291 /* calculate the upper gauss bracket of the ratio of the integer (binary) kernel and non kernel variables */
2292 if( bw_nintnonkernelvars[b] > 0 && bw_nintkernelvars[b] > 0 )
2293 intratio = SCIPceil(scip, bw_nintnonkernelvars[b] / (SCIP_Real)bw_nintkernelvars[b]);
2294 else
2295 intratio = SCIPinfinity(scip);
2296
2297 if( bw_nnonkernelvars[b] > 0 && bw_nkernelvars[b] > 0 )
2298 binratio = SCIPceil(scip, bw_nnonkernelvars[b] / (SCIP_Real)bw_nkernelvars[b]);
2299 else
2300 binratio = SCIPinfinity(scip);
2301
2302 if( !SCIPisInfinity(scip, intratio) )
2303 {
2304 nbuckets += (int)intratio;
2305 nusedratios++;
2306 }
2307 if( !SCIPisInfinity(scip, binratio) )
2308 {
2309 nbuckets += (int)binratio;
2310 nusedratios++;
2311 }
2312 }
2313 }
2314 else
2315 {
2316 /* take the rounded down average bucket ratio of all blocks*/
2317 nbuckets = 0;
2318 for( b = 0; b < nblocks + 1; b++ )
2319 {
2320 if( bw_nnonkernelvars[b] > 0 && bw_nkernelvars[b] > 0 )
2321 {
2322 nbuckets += (int)SCIPceil(scip, (SCIP_Real)bw_nnonkernelvars[b] / (SCIP_Real)bw_nkernelvars[b]);
2323 nusedratios++;
2324 }
2325 }
2326 }
2327 /* taking the average ratio as final one for all blocks */
2328 if( nusedratios > 0 )
2329 nbuckets = (int)SCIPceil(scip, (SCIP_Real)nbuckets / (SCIP_Real)nusedratios);
2330 else
2331 nbuckets = 0;
2332
2333 /* determine the amount of iterations over the buckets/ amount of investigated buckets */
2334 iters = MIN(nbuckets, heurdata->maxbucks) + 1;
2335
2336 /* create an extra array for the bucket constraints for hashmap creation in createBucketlistAndBuckets() */
2337 SCIP_CALL( SCIPduplicateBufferArray(scip, &bucketconss, conss, nconss) );
2338
2339 /* create the bucketlist and initialize as much buckets as investigated later on with a subscip for every bucket */
2340 SCIP_CALL( createBucketlistAndBuckets(scip, heurdata->usetransprob, iters - 1, &bucketlist, &success) );
2341 if( !success )
2342 goto TERMINATE;
2343
2344 /* fill every bucket with its variables, nothing to do for the first ('kernel') bucket -> k = 1 */
2345 if( iters > 1 )
2346 {
2347 SCIP_CALL( fillBuckets(scip, &bucketlist,
2348 bw_contnonkernelvars, bw_nonkernelvars, bw_intnonkernelvars,
2349 bw_ncontnonkernelvars, bw_nnonkernelvars, bw_nintnonkernelvars,
2350 bw_cont_redcost, bw_redcost, bw_int_redcost,
2351 twolevel, heurdata->redcostlogsort, iters - 1, nblocks) );
2352 }
2353
2354 /* build the kernelvariables out of each blocks kernel variables */
2355 j = 0;
2356 n = 0;
2357 m = 0;
2358 for( b = 0; b < nblocks + 1; b++ )
2359 {
2360 for( l = 0; l < bw_ncontkernelvars[b]; l++ )
2361 contkernelvars[j++] = bw_contkernelvars[b][l];
2362
2363 for( l = 0; l < bw_nkernelvars[b]; l++ )
2364 kernelvars[n++] = bw_kernelvars[b][l];
2365
2366 if( twolevel )
2367 {
2368 for( l = 0; l < bw_nintkernelvars[b]; l++ )
2369 intkernelvars[m++] = bw_intkernelvars[b][l];
2370 }
2371 }
2372 assert(j == ncontkernelvars);
2373 assert(n == nkernelvars);
2374 if( twolevel )
2375 assert(m == nintkernelvars);
2376
2377 /* loop over all buckets, solve the small MIP defined by the bucket, adjust kernel */
2378 mipgap = 0.0;
2379 nodesleft = heurdata->maxnodes;
2380 nnodes = 0;
2381 for( k = 0; k < iters; k++ )
2382 {
2383 SCIP_Bool found;
2384 SCIP_Bool infeasible;
2385 SCIP_Bool fixed;
2386 SCIP_Real lb;
2387 SCIP_Real ub;
2388 SCIP_Real timeused;
2389 SCIP_Real totaltimelimit;
2390 SCIP_Real subtimelimit;
2391 SCIP_VAR *var;
2392
2393 bucket = &bucketlist->buckets[k];
2394
2395 /* do not compute the current bucket if the number of free bin/int variables exceeds some percentage */
2396 if( SCIPisGT(scip, (SCIP_Real)(nkernelvars + nintkernelvars + bucket->nbucketvars + bucket->nintbucketvars),
2397 heurdata->maxbuckfrac * nbinintvars) )
2398 continue;
2399
2400 /* fix all integer and binary variables to zero that are neither in the kernel nor in the current bucket */
2401 for( i = 0; i < nvars ; i++ )
2402 {
2403 found = FALSE;
2404 infeasible = TRUE;
2405 fixed = FALSE;
2406
2407 var = vars[i];
2408
2409 if( var == NULL )
2410 SCIPdebugMsg(scip, "Variable is null!\n");
2411
2413 SCIPdebugMsg(scip, "Hit a cont variable");
2414
2415 /* search for the current variable in the kernel and in the current bucket */
2416 SCIP_CALL( searchKernelAndBucket(bucket, contkernelvars, ncontkernelvars, kernelvars, nkernelvars,
2417 intkernelvars, nintkernelvars, var, &found) );
2418
2419 if( found == TRUE )
2420 continue;
2421
2422 if( var == NULL )
2423 goto TERMINATE;
2424
2425 /* variable not in kernel or bucket -> deactivate by fixing to bound or zero */
2427
2428 var = bucket->scip2sub[SCIPvarGetProbindex(var)];
2429 if( var != NULL )
2430 {
2431 lb = SCIPvarGetLbLocal(vars[i]);
2432 ub = SCIPvarGetUbLocal(vars[i]);
2433
2434 /* fix to lb if finite, else to zero if ub nonnegative, else to ub */
2435 if( !SCIPisInfinity(scip, -lb) )
2436 {
2437 SCIP_CALL( SCIPfixVar(bucket->subscip, var, lb, &infeasible, &fixed) );
2438 }
2439 else if( ub >= 0.0 )
2440 {
2441 SCIP_CALL( SCIPfixVar(bucket->subscip, var, 0.0, &infeasible, &fixed) );
2442 }
2443 else
2444 {
2445 SCIP_CALL( SCIPfixVar(bucket->subscip, var, ub, &infeasible, &fixed) );
2446 }
2447 assert(!infeasible);
2448 assert(fixed);
2449 }
2450 }
2451
2452 /* construct a constraint that ensures the use of the bucketvariables */
2453 if( heurdata->addUseConss && bucket->bucketvars != NULL )
2454 SCIP_CALL( addUseConstraint(bucket) );
2455
2456 /* add objective cutoff if desired */
2457 if( heurdata->objcutoff )
2458 {
2460
2461 if( !SCIPisInfinity(scip, cutoff) )
2463 }
2464
2465#ifdef DKS_WRITE_PROBLEMS
2466 if( bucket->number < 0 )
2467 {
2468 char name[SCIP_MAXSTRLEN];
2469 /* write the current bucket problem */
2470 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "subscip_bucket_%d.lp", bucket->number);
2471 SCIP_CALL( SCIPwriteOrigProblem(bucket->subscip, name, NULL, FALSE) );
2472 }
2473#endif
2474 /* update the time limit */
2475 timeused = SCIPgetTotalTime(scip);
2476 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &totaltimelimit) );
2477 subtimelimit = totaltimelimit - timeused;
2478 if( subtimelimit > 1.0 )
2479 SCIP_CALL( SCIPsetRealParam(bucket->subscip, "limits/time", subtimelimit) );
2480 else
2481 goto TERMINATE;
2482
2483 /* update the remaining number of nodes */
2484 nodesleft -= nnodes;
2485
2486 /* get the node limit which results from evenly distributing the remaining nodes */
2487 if( nodesleft > 0 )
2488 {
2489 SCIP_Longint nodes_evenly_dist;
2490 nodes_evenly_dist = (SCIP_Longint)SCIPceil(scip, ((SCIP_Real)nodesleft) / ((SCIP_Real)(iters - k)));
2491 if( 1LL > nodes_evenly_dist )
2492 nnodes = 1LL;
2493 else
2494 nnodes = nodes_evenly_dist;
2495 }
2496 else
2497 {
2498 SCIPdebugMsg(scip, "Overall node limit reached.\n");
2499 goto TERMINATE;
2500 }
2501
2502 /* set the node limit parameter for the subscip */
2503 SCIP_CALL( SCIPsetLongintParam(bucket->subscip, "limits/nodes", nnodes) );
2504
2505 /* set the mipgap parameter for the subscip */
2506 SCIP_CALL( SCIPsetRealParam(bucket->subscip, "limits/gap", mipgap) );
2507
2508 /* solve the current subscip */
2509 SCIP_CALL_ABORT( SCIPsolve(bucket->subscip) );
2510 status = SCIPgetStatus(bucket->subscip);
2511
2512 /* compute the nodes used by the subscip */
2513 nnodes = SCIPgetNNodes(bucket->subscip);
2514
2515 if( bucket->number == 0 )
2517
2518 /* if the node limit was reached, increase the mip gap */
2519 /* gapcall = 1 signals node limit was reached before, -1 signals gap limit, 0 means no status was reached */
2520 if( status == SCIP_STATUS_NODELIMIT )
2521 {
2522 if( gapcall != 0 )
2523 gapfactor /= 2.0;
2524
2525 mipgap += (heurdata->buckmaxgap / iters) * gapfactor;
2526 gapcall = 1;
2527 }
2528 else if( status == SCIP_STATUS_GAPLIMIT )
2529 {
2530 if( gapcall != 0 )
2531 gapfactor /= 2.0;
2532
2533 mipgap -= (heurdata->buckmaxgap / iters) * gapfactor;
2534 gapcall = -1;
2535 }
2536
2537 /* check if the solution is better if one of the three cases occur:
2538 - solution is optimal
2539 - solution reached gaplimit
2540 - node limit is reached and there is one solution */
2541
2542 if( status == SCIP_STATUS_OPTIMAL || status == SCIP_STATUS_GAPLIMIT ||
2543 (status == SCIP_STATUS_NODELIMIT && SCIPgetNSols(bucket->subscip) > 0) )
2544 {
2545 SCIP_Real val;
2546 SCIP_SOL* sol;
2547
2548 sol = SCIPgetBestSol(bucket->subscip);
2549 val = SCIPgetSolOrigObj(bucket->subscip, sol);
2550
2551 /* if there is no solution yet or if the value of the current solution is better than the saved solution */
2552 if( SCIPisInfinity(scip, bestlocval) || val <= bestlocval )
2553 {
2554 bestlocval = val;
2555 nbestbucket = bucket->number;
2556
2557 if( heurdata->primalonly )
2558 break;
2559
2560 /* adjust the kernel(/-variables) */
2561 SCIP_CALL( adjustKernelVars(scip, bucket, &contkernelvars, &ncontkernelvars, (int)maxcontkernelsize,
2562 &kernelvars, &nkernelvars, (int)maxkernelsize, &intkernelvars, &nintkernelvars, (int)maxintkernelsize,
2563 twolevel) );
2564 }
2565 success = FALSE;
2566 }
2567 else if( status == SCIP_STATUS_NODELIMIT )
2568 SCIPdebugMsg(scip, "Bucket reached node limit. No optimal solution available.\n");
2569 else if( status == SCIP_STATUS_INFEASIBLE )
2570 SCIPdebugMsg(scip, "Bucket infeasible, starting over with next one\n");
2571 else
2572 {
2573 SCIPdebugMsg(scip, "Bucket solving status %d is not supported\n", status);
2574 goto TERMINATE;
2575 }
2576
2578
2579#ifdef DKS_KERNEL_INFO
2580 fclose(variable_info);
2581#endif
2582 }
2583
2584 /* if a solution of a bucket was found, save it to the scip */
2585 if( nbestbucket > -1 )
2586 {
2587 SCIP_SOL* newsol;
2588 SCIP_SOL* bestsol;
2589 BUCKET* bestbucket;
2590
2591 /* bucket with the best solution */
2592 bestbucket = &bucketlist->buckets[nbestbucket];
2593
2594 /* get the best solution */
2595 bestsol = SCIPgetBestSol(bestbucket->subscip);
2596 if( bestsol == NULL )
2597 {
2598 SCIPdebugMsg(scip, "Function SCIPgetBestSol() has returned a NULL pointer\n");
2600 goto TERMINATE;
2601 }
2602
2603 SCIPdebug( SCIP_CALL( SCIPprintSol(bestbucket->subscip, bestsol, NULL, FALSE) ) );
2604
2605 /* extract the values of all variables in the best solution of a bucket found */
2606 SCIP_CALL( SCIPtranslateSubSol(scip, bestbucket->subscip, bestsol, heur, bestbucket->scip2sub, &newsol) );
2607
2608 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, newsol, NULL, FALSE) ) );
2609 SCIPdebugMsg(scip, "Objective value %.2f\n", SCIPgetSolOrigObj(scip, newsol));
2610 SCIPdebugMsg(scip, "Objective value of subscip %.2f\n", SCIPgetSolOrigObj(bestbucket->subscip, bestsol));
2611
2612 /* check the feasibilty of the new created solution, save it if so and free it */
2613 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
2614
2615 if( !success )
2616 {
2617 SCIPdebugMsg(scip, "Solution copy failed\n");
2619 }
2620 else
2621 {
2622 SCIPdebugMsg(scip, "Solution copy successfull after %f sec\n", SCIPgetSolvingTime(scip));
2624 }
2625 }
2626 else
2627 {
2628 SCIPdebugMsg(scip, "no solution found\n");
2630 }
2631
2632 /* remember if the heuristic has not provided a solution */
2633 if( *result != SCIP_FOUNDSOL )
2634 heurdata->uselesscall = TRUE;
2635
2636TERMINATE:
2637 if( bucketconss != NULL )
2638 SCIPfreeBufferArray(scip, &bucketconss);
2639
2640 if( bw_intnonkernelcount != NULL )
2641 SCIPfreeBufferArray(scip, &bw_intnonkernelcount);
2642
2643 if( bw_intkernelcount != NULL )
2644 SCIPfreeBufferArray(scip, &bw_intkernelcount);
2645
2646 if( intnonkernelvars != NULL )
2647 SCIPfreeBufferArray(scip, &intnonkernelvars);
2648
2649 if( intkernelvars != NULL )
2650 SCIPfreeBufferArray(scip, &intkernelvars);
2651
2652 if( bw_nonkernelcount != NULL )
2653 SCIPfreeBufferArray(scip, &bw_nonkernelcount);
2654
2655 if( bw_kernelcount != NULL )
2656 SCIPfreeBufferArray(scip, &bw_kernelcount);
2657
2658 if( bw_contnonkernelcount != NULL )
2659 SCIPfreeBufferArray(scip, &bw_contnonkernelcount);
2660
2661 if( bw_contkernelcount != NULL )
2662 SCIPfreeBufferArray(scip, &bw_contkernelcount);
2663
2664 if( binintvars != NULL )
2665 SCIPfreeBufferArray(scip, &binintvars);
2666
2667 if( nonkernelvars != NULL )
2668 SCIPfreeBufferArray(scip, &nonkernelvars);
2669
2670 if( kernelvars != NULL )
2671 SCIPfreeBufferArray(scip, &kernelvars);
2672
2673 if( contnonkernelvars != NULL )
2674 SCIPfreeBufferArray(scip, &contnonkernelvars);
2675
2676 if( contkernelvars != NULL )
2677 SCIPfreeBufferArray(scip, &contkernelvars);
2678
2679 if( bw_intkernelvars != NULL )
2680 {
2681 for( b = nblocks; b >= 0; b-- )
2682 {
2683 if( bw_intnonkernelvars[b] != NULL )
2684 SCIPfreeBufferArray(scip, &(bw_intnonkernelvars[b]));
2685 if( bw_intkernelvars[b] != NULL )
2686 SCIPfreeBufferArray(scip, &(bw_intkernelvars[b]));
2687 }
2688 }
2689
2690 if( bw_kernelvars != NULL )
2691 {
2692 for( b = nblocks; b >= 0; b-- )
2693 {
2694 if( bw_nonkernelvars[b] != NULL )
2695 SCIPfreeBufferArray(scip, &(bw_nonkernelvars[b]));
2696 if( bw_kernelvars[b] != NULL )
2697 SCIPfreeBufferArray(scip, &(bw_kernelvars[b]));
2698 }
2699 }
2700
2701 if( bw_contkernelvars != NULL )
2702 {
2703 for( b = nblocks; b >= 0; b-- )
2704 {
2705 if( bw_contnonkernelvars[b] != NULL )
2706 SCIPfreeBufferArray(scip, &(bw_contnonkernelvars[b]));
2707 if( bw_contkernelvars[b] != NULL )
2708 SCIPfreeBufferArray(scip, &(bw_contkernelvars[b]));
2709 }
2710 }
2711
2712 if( bw_intnonkernelvars != NULL )
2713 SCIPfreeBufferArray(scip, &bw_intnonkernelvars);
2714
2715 if( bw_intkernelvars != NULL )
2716 SCIPfreeBufferArray(scip, &bw_intkernelvars);
2717
2718 if( bw_nonkernelvars != NULL )
2719 SCIPfreeBufferArray(scip, &bw_nonkernelvars);
2720
2721 if( bw_kernelvars != NULL )
2722 SCIPfreeBufferArray(scip, &bw_kernelvars);
2723
2724 if( bw_contnonkernelvars != NULL )
2725 SCIPfreeBufferArray(scip, &bw_contnonkernelvars);
2726
2727 if( bw_contkernelvars != NULL )
2728 SCIPfreeBufferArray(scip, &bw_contkernelvars);
2729
2730 if( bw_nintnonkernelvars != NULL )
2731 SCIPfreeBufferArray(scip, &bw_nintnonkernelvars);
2732
2733 if( bw_nintkernelvars != NULL )
2734 SCIPfreeBufferArray(scip, &bw_nintkernelvars);
2735
2736 if( bw_nnonkernelvars != NULL )
2737 SCIPfreeBufferArray(scip, &bw_nnonkernelvars);
2738
2739 if( bw_nkernelvars != NULL )
2740 SCIPfreeBufferArray(scip, &bw_nkernelvars);
2741
2742 if( bw_ncontnonkernelvars != NULL )
2743 SCIPfreeBufferArray(scip, &bw_ncontnonkernelvars);
2744
2745 if( bw_ncontkernelvars != NULL )
2746 SCIPfreeBufferArray(scip, &bw_ncontkernelvars);
2747
2748 if( block2index != NULL )
2749 {
2750 if( nblocklabels > 0 )
2751 {
2752 assert(blocklabels != NULL);
2753 SCIPfreeBlockMemoryArray(scip, &block2index, blocklabels[nblocklabels - 1] + 1 + blklbl_offset);
2754 }
2755 else
2756 SCIPfreeBlockMemoryArray(scip, &block2index, 1);
2757 }
2758
2759 if( blocklabels != NULL )
2760 SCIPfreeBufferArray(scip, &blocklabels);
2761
2762 if( conslabels != NULL )
2763 SCIPfreeBufferArray(scip, &conslabels);
2764
2765 if( varlabels != NULL )
2766 SCIPfreeBufferArray(scip, &varlabels);
2767
2768 SCIP_CALL( freeRedcostArrays(scip, &bw_cont_redcost, &bw_redcost, &bw_int_redcost, nblocks) );
2769
2770 if( lbvarmap != NULL )
2771 SCIPhashmapFree(&lbvarmap);
2772
2773 if( bucketlist != NULL )
2774 {
2775 for( k = bucketlist->nbuckets - 1; k >= 1; k-- )
2776 {
2777 SCIP_CALL( freeBucket(scip, &bucketlist->buckets[k]) );
2778 SCIP_CALL( freeBucketArrays(scip, &bucketlist->buckets[k], twolevel) );
2779 }
2780 SCIP_CALL( freeBucket(scip, &bucketlist->buckets[0]) );
2781 }
2782
2783 if( bucketlist != NULL )
2784 {
2785 SCIP_CALL( freeBucketlist(&bucketlist, iters) );
2786 }
2787
2788 SCIPdebugMsg(scip, "Leave dks heuristic\n");
2789
2790 return SCIP_OKAY;
2791}
2792
2793
2794/*
2795 * primal heuristic specific interface methods
2796 */
2797
2798/** creates the DKS primal heuristic and includes it in SCIP */
2800 SCIP* scip /**< SCIP data structure */
2801 )
2802{
2804 SCIP_HEUR* heur = NULL;
2805
2806 /* create dks primal heuristic data */
2808 assert(heurdata != NULL);
2809 heurdata->ncalls = 0;
2810 heurdata->uselesscall = FALSE;
2811
2812 /* include primal heuristic */
2816
2817 assert(heur != NULL);
2818
2819 /* set non fundamental callbacks via setter functions */
2820 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDKS) );
2821 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDKS) );
2822
2823 /* add dks primal heuristic parameters */
2824 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxbucks",
2825 "maximal number of buckets to be investigated",
2826 &heurdata->maxbucks, TRUE, DEFAULT_MAXBUCKS, 1, 100, NULL, NULL) );
2827
2828 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/kernelsizefactor",
2829 "factor with which the initial kernel size can grow max",
2830 &heurdata->kernelsizefactor, TRUE, DEFAULT_KERNELSIZEFACTOR, 1.0, 10.0, NULL, NULL) );
2831
2832 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/addUseConss",
2833 "should a constraint be added ensuring that bucket variables are used?",
2834 &heurdata->addUseConss, TRUE, DEFAULT_ADDUSECONSS, NULL, NULL) );
2835
2836 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/linkbucksize",
2837 "should the linking variables in the kernel influence the size of the buckets?",
2838 &heurdata->linkbucksize, TRUE, DEFAULT_LINKBUCKSIZE, NULL, NULL) );
2839
2840 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/translbkernel",
2841 "should a variable with different lower bound in transformed and original problem be in the kernel?",
2842 &heurdata->translbkernel, TRUE, DEFAULT_TRANSLBKERNEL, NULL, NULL) );
2843
2844 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/lesslockskernel",
2845 "should a variable with max one uplock and one downlock be in the kernel?",
2846 &heurdata->lesslockskernel, TRUE, DEFAULT_LESSLOCKSKERNEL, NULL, NULL) );
2847
2848 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usetransprob",
2849 "should dks use the transformed problem?",
2850 &heurdata->usetransprob, TRUE, DEFAULT_USETRANSPROB, NULL, NULL) );
2851
2852 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/buckmaxgap",
2853 "defines the maximum mipgap a bucket can be solved to",
2854 &heurdata->buckmaxgap, TRUE, DEFAULT_BUCKMAXGAP, 0.0, 1.0, NULL, NULL) );
2855
2856 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxlinkscore",
2857 "defines a bound to the linkscore of the decomp",
2858 &heurdata->maxlinkscore, TRUE, DEFAULT_MAXLINKSCORE, 0.0, 1.0, NULL, NULL) );
2859
2860 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxbuckfrac",
2861 "defines a maximal share of bin/int variables for a bucket to be respected",
2862 &heurdata->maxbuckfrac, TRUE, DEFAULT_MAXBUCKFRAC, 0.0, 1.0, NULL, NULL) );
2863
2864 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
2865 "maximum number of nodes to regard in all subproblems",
2866 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
2867
2868 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usetwolevel",
2869 "should a two level bucket structure be used if possible?",
2870 &heurdata->usetwolevel, FALSE, DEFAULT_USETWOLEVEL, NULL, NULL) );
2871
2872 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedecomp",
2873 "should a decomposition be used if given?",
2874 &heurdata->usedecomp, FALSE, DEFAULT_USEDECOMP, NULL, NULL) );
2875
2876 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usebestsol",
2877 "should the best solution instead of the LP solution be used?",
2878 &heurdata->usebestsol, FALSE, DEFAULT_USEBESTSOL, NULL, NULL) );
2879
2880 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/redcostsort",
2881 "should the bucket variables be sorted by reduced costs in the LP solution?",
2882 &heurdata->redcostsort, FALSE, DEFAULT_REDCOSTSORT, NULL, NULL) );
2883
2884 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/primalonly",
2885 "should the heuristic terminate after the first primal solution is found?",
2886 &heurdata->primalonly, FALSE, DEFAULT_PRIMALONLY, NULL, NULL) );
2887
2888 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/redcostlogsort",
2889 "should the bucket variables be sorted logarithmically by reduced costs in the LP solution?",
2890 &heurdata->redcostlogsort, FALSE, DEFAULT_REDCOSTLOGSORT, NULL, NULL) ) ;
2891
2892 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/objcutoff",
2893 "should the next solution at least satisfy the old objective?",
2894 &heurdata->objcutoff, FALSE, DEFAULT_OBJCUTOFF, NULL, NULL) );
2895
2896 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/runbinprobsonly",
2897 "should the heuristic be used only for binary problems or problems with integer and binary variables?",
2898 &heurdata->runbinprobsonly, FALSE, DEFAULT_RUNBINPROBSONLY, NULL, NULL) );
2899
2900 return SCIP_OKAY;
2901}
SCIP_VAR ** b
#define DEFAULT_MAXNODES
Constraint handler for linear constraints in their most general form, .
methods for debugging
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
#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:1168
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:1581
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:1398
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition scip_copy.c:2548
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition scip_copy.c:3293
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:2799
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4782
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
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:2986
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition scip_sol.c:2351
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
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:4114
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
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:18365
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24052
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23694
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24696
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:2608
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
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 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
@ SCIP_INVALIDCALL
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