SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_indicatordiving.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_indicatordiving.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief LP diving heuristic that fixes indicator variables controlling semicontinuous variables
28 * @author Katrin Halbig
29 * @author Alexander Hoen
30 *
31 * A diving heuristic iteratively rounds some fractional variables or variables determined by constraint handlers,
32 * and resolves the LP relaxation. Thereby simulating a depth-first-search in the tree.
33 *
34 * Indicatordiving focuses on indicator variables, which control semicontinuous variables.
35 * If the semicontinuous variable is unbounded, the indicator constraint is not part of the LP and,
36 * therefore, the indicator variable is not set to an useful value in the LP solution.
37 *
38 * For these indicator variables the score depends on the LP value and the bounds of the corresponding semicontinuous variable.
39 * If parameter usevarbounds=TRUE, also varbound constraints modeling semicontinuous variables are considered.
40 * For all other variables the Farkas score (scaled) is returned.
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
45#include "scip/cons_indicator.h"
46#include "scip/cons_varbound.h"
48#include "scip/heuristics.h"
49#include "scip/pub_cons.h"
50#include "scip/pub_heur.h"
51#include "scip/pub_message.h"
52#include "scip/pub_misc.h"
53#include "scip/pub_var.h"
54#include "scip/scip_cons.h"
55#include "scip/scip_heur.h"
56#include "scip/scip_mem.h"
57#include "scip/scip_numerics.h"
58#include "scip/scip_param.h"
59#include "scip/scip_probing.h"
60#include "scip/scip_sol.h"
61#include "scip/scip_tree.h"
62#include "scip/scip_prob.h"
63#include "scip/scip_message.h"
64
65#define HEUR_NAME "indicatordiving"
66#define HEUR_DESC "LP diving heuristic that fixes indicator variables controlling semicontinuous variables"
67#define HEUR_DISPCHAR 'I'
68#define HEUR_PRIORITY -150000
69#define HEUR_FREQ 0
70#define HEUR_FREQOFS 0
71#define HEUR_MAXDEPTH -1
72#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
73#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
74#define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY /**< bit mask that represents all supported dive types */
75#define DIVESET_ISPUBLIC FALSE /**< is this dive set publicly available (ie., can be used by other primal heuristics?) */
76
77
78/*
79 * Default parameter settings
80 */
81
82#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
83#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
84#define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
85#define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
86#define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
87 * where diving is performed (0.0: no limit) */
88#define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
89 * where diving is performed (0.0: no limit) */
90#define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
91#define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
92#define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
93#define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
94#define DEFAULT_LPSOLVEFREQ 30 /**< LP solve frequency for diving heuristics */
95#define DEFAULT_ONLYLPBRANCHCANDS FALSE /**< should only LP branching candidates be considered instead of the slower but
96 * more general constraint handler diving variable selection? */
97#define DEFAULT_RANDSEED 11 /**< initial seed for random number generation */
98
99/*
100 * Heuristic specific parameters
101 */
102#define DEFAULT_ROUNDINGFRAC 0.5 /**< default setting for parameter roundingfrac */
103#define DEFAULT_ROUNDINGMODE 0 /**< default setting for parameter roundingmode */
104#define DEFAULT_SEMICONTSCOREMODE 0 /**< default setting for parameter semicontscoremode */
105#define DEFAULT_USEVARBOUNDS TRUE /**< default setting for parameter usevarbounds */
106#define DEFAULT_RUNWITHOUTSCINDS FALSE /**< default setting for parameter runwithoutscinds */
107
114
115/** data structure to store information of a semicontinuous variable
116 *
117 * For a variable x (not stored in the struct), this stores the data of nbnds implications
118 * bvars[i] = 0 -> x = vals[i]
119 * bvars[i] = 1 -> lbs[i] <= x <= ubs[i]
120 * where bvars[i] are binary variables.
121 */
123{
124 SCIP_Real* vals0; /**< values of the variable when the corresponding bvars[i] = 0 */
125 SCIP_Real* lbs1; /**< global lower bounds of the variable when the corresponding bvars[i] = 1 */
126 SCIP_Real* ubs1; /**< global upper bounds of the variable when the corresponding bvars[i] = 1 */
127 SCIP_VAR** bvars; /**< the binary variables on which the variable domain depends */
128 int nbnds; /**< number of suitable on/off bounds the var has */
129 int bndssize; /**< size of the arrays */
130};
131typedef struct SCVarData SCVARDATA;
132
133
134/** locally defined heuristic data */
135struct SCIP_HeurData
136{
137 SCIP_SOL* sol; /**< working solution */
138 SCIP_CONSHDLR* indicatorconshdlr; /**< indicator constraint handler */
139 SCIP_CONSHDLR* varboundconshdlr; /**< varbound constraint handler */
140 SCIP_HASHMAP* scvars; /**< hashmap to store semicontinuous variables */
141 SCIP_HASHMAP* indicatormap; /**< hashmap to store indicator constraints of binary variables */
142 SCIP_HASHMAP* varboundmap; /**< hashmap to store varbound constraints of binary variables */
143 SCIP_Real roundingfrac; /**< in violation case all fractional below this value are fixed to constant */
144 int roundingmode; /**< decides which roundingmode is selected (0: conservative (default), 1: aggressive) */
145 int semicontscoremode; /**< which values of semi-continuous variables should get a high score? (0: low (default), 1: middle, 2: high) */
146 SCIP_Bool usevarbounds; /**< should varbound constraints be considered? */
147 SCIP_Bool runwithoutscinds; /**< should heur run if there are no indicator constraints modeling semicont. vars? */
148 SCIP_Bool gotoindconss; /**< can we skip the candidate var until indicator conss handler determines the candidate var? */
149 SCIP_Bool containsviolindconss;/**< contains current solution violated indicator constraints? (only unbounded) */
150 SCIP_Bool newnode; /**< are we at a new probing node? */
151 int probingdepth; /**< current probing depth */
152};
153
154/*
155 * Local methods
156 */
157
158/** checks if constraint is violated but not fixed, i.e., it will be a diving candidate variable */
159static
161 SCIP* scip, /**< SCIP data structure */
162 SCIP_SOL* sol, /**< pointer to solution */
163 SCIP_CONS* cons /**< pointer to indicator constraint */
164 )
165{
166 SCIP_VAR* binvar;
167 SCIP_Real solval;
168
170
171 if( !SCIPisViolatedIndicator(scip, cons, sol) )
172 return FALSE;
173
174 binvar = SCIPgetBinaryVarIndicator(cons);
175 solval = SCIPgetSolVal(scip, sol, binvar);
176
177 return (SCIPisFeasIntegral(scip, solval) && SCIPvarGetLbLocal(binvar) < SCIPvarGetUbLocal(binvar) - 0.5);
178}
179
180/** releases all data from given hashmap filled with SCVarData and the hashmap itself */
181static
183 SCIP* scip, /**< SCIP data structure */
184 SCIP_HASHMAP* hashmap /**< hashmap to be freed */
185 )
186{
187 SCIP_HASHMAPENTRY* entry;
188 SCVARDATA* data;
189 int c;
190
191 if( hashmap != NULL )
192 {
193 for( c = 0; c < SCIPhashmapGetNEntries( hashmap ); c++ )
194 {
195 entry = SCIPhashmapGetEntry( hashmap, c);
196 if( entry != NULL )
197 {
198 data = (SCVARDATA*) SCIPhashmapEntryGetImage(entry);
204 }
205 }
206 SCIPhashmapFree(&hashmap);
207 assert(hashmap == NULL);
208 }
209
210 return SCIP_OKAY;
211}
212
213/** checks if variable is indicator variable and stores corresponding indicator constraint; additionally, if we are at a
214 * new probing node, it checks whether there are violated but not fixed indicator constraints
215 */
216static
218 SCIP* scip, /**< SCIP data structure */
219 SCIP_VAR* cand, /**< candidate variable */
220 SCIP_HASHMAP* map, /**< pointer to hashmap containing indicator conss */
221 SCIP_CONS** cons, /**< pointer to store indicator constraint */
222 SCIP_Bool* isindicator, /**< pointer to store whether candidate variable is indicator variable */
223 SCIP_Bool* containsviolindconss,/**< pointer to store whether there are violated and not fixed (unbounded) indicator constraints */
224 SCIP_Bool newnode, /**< are we at a new probing node? */
225 SCIP_SOL* sol, /**< pointer to solution */
226 SCIP_CONSHDLR* conshdlr /**< constraint handler */
227 )
228{
229 assert(scip != NULL);
230 assert(cand != NULL);
231 assert(map != NULL);
232 assert(cons != NULL);
233 assert(isindicator != NULL);
234 assert(sol != NULL);
235
236 *cons = NULL;
237 *isindicator = FALSE;
238
239 *cons = (SCIP_CONS*) SCIPhashmapGetImage(map, cand);
240 if( *cons != NULL )
241 *isindicator = TRUE;
242
243 /* since we are at a new probing node, check if there are violated and not fixed indicator constraints */
244 if( newnode )
245 {
246 SCIP_CONS** indicatorconss;
247 int nconss;
248 int c;
249
250 indicatorconss = SCIPconshdlrGetConss(conshdlr);
251 nconss = SCIPconshdlrGetNActiveConss(conshdlr);
252 *containsviolindconss = FALSE;
253
254 for( c = 0; c < nconss; c++ )
255 {
256 *containsviolindconss = *containsviolindconss || isViolatedAndNotFixed(scip, sol, indicatorconss[c]);
257
258 if( *containsviolindconss )
259 break;
260 }
261 }
262}
263
264/** checks if variable is binary variable of varbound constraint and stores corresponding varbound constraint */
265static
267 SCIP* scip, /**< SCIP data structure */
268 SCIP_VAR* cand, /**< candidate variable */
269 SCIP_HASHMAP* map, /**< pointer to hashmap containing varbound conss */
270 SCIP_CONS** cons, /**< pointer to store varbound constraint */
271 SCIP_Bool* isvarbound /**< pointer to store whether candidate variable is indicator variable */
272 )
273{
274 assert(scip != NULL);
275 assert(cand != NULL);
276 assert(map != NULL);
277 assert(cons != NULL);
278 assert(isvarbound != NULL);
279
280 *cons = NULL;
281 *isvarbound = FALSE;
282
284 return;
285
286 *cons = (SCIP_CONS*) SCIPhashmapGetImage(map, cand);
287 if( *cons != NULL )
288 *isvarbound = TRUE;
289}
290
291/** adds an indicator to the data of a semicontinuous variable */
292static
294 SCIP* scip, /**< SCIP data structure */
295 SCVARDATA* scvdata, /**< semicontinuous variable data */
296 SCIP_VAR* indicator, /**< indicator to be added */
297 SCIP_Real val0, /**< value of the variable when indicator == 0 */
298 SCIP_Real lb1, /**< lower bound of the variable when indicator == 1 */
299 SCIP_Real ub1 /**< upper bound of the variable when indicator == 1 */
300 )
301{
302 int newsize;
303 int i;
304 SCIP_Bool found;
305 int pos;
306
307 assert(scvdata != NULL);
308 assert(indicator != NULL);
309
310 /* find the position where to insert */
311 if( scvdata->bvars == NULL )
312 {
313 assert(scvdata->nbnds == 0 && scvdata->bndssize == 0);
314 found = FALSE;
315 pos = 0;
316 }
317 else
318 {
319 found = SCIPsortedvecFindPtr((void**)scvdata->bvars, SCIPvarComp, (void*)indicator, scvdata->nbnds, &pos);
320 }
321
322 if( found )
323 return SCIP_OKAY;
324
325 /* ensure sizes */
326 if( scvdata->nbnds + 1 > scvdata->bndssize )
327 {
328 newsize = SCIPcalcMemGrowSize(scip, scvdata->nbnds + 1);
329 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scvdata->bvars, scvdata->bndssize, newsize) );
330 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scvdata->vals0, scvdata->bndssize, newsize) );
331 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scvdata->lbs1, scvdata->bndssize, newsize) );
332 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scvdata->ubs1, scvdata->bndssize, newsize) );
333 scvdata->bndssize = newsize;
334 }
335 assert(scvdata->nbnds + 1 <= scvdata->bndssize);
336 assert(scvdata->bvars != NULL);
337
338 /* move entries if needed */
339 for( i = scvdata->nbnds; i > pos; --i )
340 {
341 /* coverity[var_deref_op] */
342 scvdata->bvars[i] = scvdata->bvars[i-1];
343 scvdata->vals0[i] = scvdata->vals0[i-1];
344 scvdata->lbs1[i] = scvdata->lbs1[i-1];
345 scvdata->ubs1[i] = scvdata->ubs1[i-1];
346 }
347
348 scvdata->bvars[pos] = indicator;
349 scvdata->vals0[pos] = val0;
350 scvdata->lbs1[pos] = lb1;
351 scvdata->ubs1[pos] = ub1;
352 ++scvdata->nbnds;
353
354 return SCIP_OKAY;
355}
356
357/** checks if a variable is semicontinuous and stores it data in the hashmap scvars
358 *
359 * A variable x is semicontinuous if its bounds depend on at least one binary variable called the indicator,
360 * and indicator == 0 => x == x^0 for some real constant x^0.
361 */
362static
364 SCIP* scip, /**< SCIP data structure */
365 SCIP_VAR* var, /**< the variable to check */
366 SCIP_HASHMAP* scvars, /**< semicontinuous variable information */
367 SCIP_Real constant, /**< value which should be equal to the constant */
368 SCIP_Bool* result /**< buffer to store whether var is semicontinuous */
369 )
370{
371 SCIP_Real lb0;
372 SCIP_Real ub0;
373 SCIP_Real lb1;
374 SCIP_Real ub1;
375 SCIP_Real glb;
376 SCIP_Real gub;
377 SCIP_Bool exists;
378 int c;
379 int pos;
380 SCIP_VAR** vlbvars;
381 SCIP_VAR** vubvars;
382 SCIP_Real* vlbcoefs;
383 SCIP_Real* vubcoefs;
384 SCIP_Real* vlbconstants;
385 SCIP_Real* vubconstants;
386 int nvlbs;
387 int nvubs;
388 SCVARDATA* scvdata;
389 SCIP_VAR* bvar;
390
391 assert(scip != NULL);
392 assert(var != NULL);
393 assert(scvars != NULL);
394 assert(result != NULL);
395
396 scvdata = (SCVARDATA*) SCIPhashmapGetImage(scvars, (void*)var);
397 if( scvdata != NULL )
398 {
399 *result = TRUE;
400 return SCIP_OKAY;
401 }
402
403 vlbvars = SCIPvarGetVlbVars(var);
404 vubvars = SCIPvarGetVubVars(var);
405 vlbcoefs = SCIPvarGetVlbCoefs(var);
406 vubcoefs = SCIPvarGetVubCoefs(var);
407 vlbconstants = SCIPvarGetVlbConstants(var);
408 vubconstants = SCIPvarGetVubConstants(var);
409 nvlbs = SCIPvarGetNVlbs(var);
410 nvubs = SCIPvarGetNVubs(var);
411 glb = SCIPvarGetLbGlobal(var);
412 gub = SCIPvarGetUbGlobal(var);
413
414 pos = -1;
415
416 *result = FALSE;
417
418 /* Scan through lower bounds; for each binary vlbvar save the corresponding lb0 and lb1.
419 * Then check if there is an upper bound with this vlbvar and save ub0 and ub1.
420 * If the found bounds imply that the var value is fixed to some val0 when vlbvar = 0,
421 * save vlbvar and val0 to scvdata.
422 */
423 for( c = 0; c < nvlbs; ++c )
424 {
425 if( SCIPvarGetType(vlbvars[c]) != SCIP_VARTYPE_BINARY || SCIPvarIsImpliedIntegral(vlbvars[c]) )
426 continue;
427
428 bvar = vlbvars[c];
429
430 lb0 = MAX(vlbconstants[c], glb);
431 lb1 = MAX(vlbconstants[c] + vlbcoefs[c], glb);
432
433 /* look for bvar in vubvars */
434 if( vubvars != NULL )
435 exists = SCIPsortedvecFindPtr((void**)vubvars, SCIPvarComp, bvar, nvubs, &pos);
436 else
437 exists = FALSE;
438
439 if( exists )
440 {
441 /* save the upper bounds */
442 ub0 = MIN(vubconstants[pos], gub);
443 ub1 = MIN(vubconstants[pos] + vubcoefs[pos], gub);
444 }
445 else
446 {
447 /* if there is no upper bound with vubvar = bvar, use global var bounds */
448 ub0 = gub;
449 ub1 = gub;
450 }
451
452 /* the 'off' domain of a semicontinuous var should reduce to a single point (constant) and be different from the 'on' domain */
453 if( SCIPisEQ(scip, lb0, constant) && (!SCIPisEQ(scip, lb0, lb1) || !SCIPisEQ(scip, ub0, ub1)) )
454 {
455 if( scvdata == NULL )
456 {
458 }
459 SCIP_CALL( addSCVarIndicator(scip, scvdata, bvar, lb0, lb1, ub1) );
460 }
461 }
462
463 /* look for vubvars that have not been processed yet */
464 assert(vubvars != NULL || nvubs == 0);
465 for( c = 0; c < nvubs; ++c )
466 {
467 /* coverity[var_deref_op] */
468 if( SCIPvarGetType(vubvars[c]) != SCIP_VARTYPE_BINARY || SCIPvarIsImpliedIntegral(vubvars[c]) ) /*lint !e613*/
469 continue;
470
471 bvar = vubvars[c]; /*lint !e613*/
472
473 /* skip vars that are in vlbvars */
474 if( vlbvars != NULL && SCIPsortedvecFindPtr((void**)vlbvars, SCIPvarComp, bvar, nvlbs, &pos) )
475 continue;
476
477 lb0 = glb;
478 lb1 = glb;
479 ub0 = MIN(vubconstants[c], gub);
480 ub1 = MIN(vubconstants[c] + vubcoefs[c], gub);
481
482 /* the 'off' domain of a semicontinuous var should reduce to a single point (constant) and be different from the 'on' domain */
483 if( SCIPisEQ(scip, lb0, constant) && (!SCIPisEQ(scip, lb0, lb1) || !SCIPisEQ(scip, ub0, ub1)) )
484 {
485 if( scvdata == NULL )
486 {
488 }
489
490 SCIP_CALL( addSCVarIndicator(scip, scvdata, bvar, lb0, lb1, ub1) );
491 }
492 }
493
494 if( scvdata != NULL )
495 {
496#ifdef SCIP_DEBUG
497 SCIPdebugMsg(scip, "var <%s> has global bounds [%f, %f] and the following on/off bounds:\n", SCIPvarGetName(var), glb, gub);
498 for( c = 0; c < scvdata->nbnds; ++c )
499 {
500 SCIPdebugMsg(scip, " c = %d, bvar <%s>: val0 = %f\n", c, SCIPvarGetName(scvdata->bvars[c]), scvdata->vals0[c]);
501 }
502#endif
503 SCIP_CALL( SCIPhashmapInsert(scvars, var, scvdata) );
504 *result = TRUE;
505 }
506
507 return SCIP_OKAY;
508}
509
510/** checks if there are unfixed indicator variables modeling semicont. vars */
511static
513 SCIP* scip, /**< SCIP data structure */
514 SCIP_CONSHDLR* conshdlr, /**< indicator constraint handler */
515 SCIP_HASHMAP* scvars, /**< semicontinuous variable information */
516 SCIP_Bool* hasunfixedscindconss /**< pointer to store if there are unfixed indicator variables modeling semicont. vars */
517 )
518{
519 SCIP_CONS** indicatorconss;
520 SCIP_VAR** consvars;
521 SCIP_Real* consvals;
522 int nconss;
523 int i;
524
525 *hasunfixedscindconss = FALSE;
526 indicatorconss = SCIPconshdlrGetConss(conshdlr);
527 nconss = SCIPconshdlrGetNConss(conshdlr);
528 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
529 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
530
531 for( i = 0; i < nconss; i++ )
532 {
533 SCIP_VAR *binvar;
534 SCIP_VAR* semicontinuousvar;
535 SCIP_CONS* lincons;
536 SCIP_Real rhs;
537 int nconsvars;
538 SCIP_Bool success;
539 int v;
540
541 binvar = SCIPgetBinaryVarIndicator(indicatorconss[i]);
542
543 /* check if indicator variable is unfixed */
544 if( SCIPvarGetLbLocal(binvar) < SCIPvarGetUbLocal(binvar) - 0.5 )
545 {
546 lincons = SCIPgetLinearConsIndicator(indicatorconss[i]);
547 rhs = SCIPconsGetRhs(scip, lincons, &success);
548 SCIP_CALL( SCIPgetConsNVars(scip, lincons, &nconsvars, &success) );
549
550 /* check if constraint contains only two variables with finite rhs */
551 /* TODO: allow also indicators for lower bounds */
552 if( nconsvars == 2 && !SCIPisInfinity(scip, rhs) )
553 {
554 SCIP_CALL( SCIPgetConsVars(scip, lincons, consvars, nconsvars, &success) );
555 SCIP_CALL( SCIPgetConsVals(scip, lincons, consvals, nconsvars, &success) );
556
557 for( v = 0; v < nconsvars ; v++ )
558 {
559 if( consvars[v] == SCIPgetSlackVarIndicator(indicatorconss[i]) ) /* note that we have exact two variables */
560 continue;
561
562 semicontinuousvar = consvars[v];
563 SCIP_CALL( varIsSemicontinuous(scip, semicontinuousvar, scvars, rhs, &success) );
564
565 /* check if semicontinuous variable */
566 if( success )
567 {
568 *hasunfixedscindconss = TRUE;
569 break;
570 }
571 }
572 if( *hasunfixedscindconss )
573 break;
574 }
575 }
576 }
577 SCIPfreeBufferArray(scip, &consvals);
578 SCIPfreeBufferArray(scip, &consvars);
579 return SCIP_OKAY;
580}
581
582/** creates and initializes hashmaps
583 *
584 * indicatormap: binary var -> indicator constraint
585 * varboundmap: binary var -> varbound constraint
586 *
587 * Currently exactly one constraint is assigned to a binary variable (per hashmap),
588 * but a binary variable can also control more than one constraint.
589 * TODO: Allow more than one corresponding indicator/varbound constraint per binary variable.
590 */
591static
593 SCIP* scip, /**< SCIP data structure */
594 SCIP_CONSHDLR* indicatorconshdlr, /**< indicator constraint handler */
595 SCIP_CONSHDLR* varboundconshdlr, /**< varbound constraint handler */
596 SCIP_Bool usevarbounds, /**< should varbound constraints be considered? */
597 SCIP_HASHMAP** indicatormap, /**< hashmap to store indicator constraints of binary variables */
598 SCIP_HASHMAP** varboundmap /**< hashmap to store varbound constraints of binary variables */
599 )
600{
601 SCIP_CONS** conss;
602 int nconss;
603 int i;
604
605 SCIP_STRINGEQ( SCIPconshdlrGetName(indicatorconshdlr), "indicator", SCIP_INVALIDCALL );
606 SCIP_STRINGEQ( SCIPconshdlrGetName(varboundconshdlr), "varbound", SCIP_INVALIDCALL );
607
608 /* indicator constraints */
609 nconss = SCIPconshdlrGetNConss(indicatorconshdlr);
610 conss = SCIPconshdlrGetConss(indicatorconshdlr);
611 SCIP_CALL( SCIPhashmapCreate(indicatormap, SCIPblkmem(scip), nconss) );
612 for( i = 0; i < nconss; i++ )
613 {
614 if( !SCIPhashmapExists(*indicatormap, SCIPgetBinaryVarIndicator(conss[i])) )
615 {
616 SCIP_CALL( SCIPhashmapInsert(*indicatormap, SCIPgetBinaryVarIndicator(conss[i]), conss[i]) );
617 }
618 }
619
620 /* varbound constraints */
621 if( usevarbounds )
622 {
623 nconss = SCIPconshdlrGetNConss(varboundconshdlr);
624 conss = SCIPconshdlrGetConss(varboundconshdlr);
625 SCIP_CALL( SCIPhashmapCreate(varboundmap, SCIPblkmem(scip), nconss) );
626 for( i = 0; i < nconss; i++ )
627 {
628 if( !SCIPhashmapExists(*varboundmap, SCIPgetVbdvarVarbound(scip, conss[i])) )
629 {
630 SCIP_CALL( SCIPhashmapInsert(*varboundmap, SCIPgetVbdvarVarbound(scip, conss[i]), conss[i]) );
631 }
632 }
633 }
634 return SCIP_OKAY;
635}
636
637#define MIN_RAND 1e-06
638#define MAX_RAND 1e-05
639
640/** calculate score and preferred rounding direction for the candidate variable */
641static
643 SCIP* scip, /**< SCIP data structure */
644 SCIP_DIVESET* diveset, /**< diving settings */
645 SCIP_VAR* cand, /**< candidate variable */
646 SCIP_Real candsfrac, /**< fractional part of solution value of candidate variable */
647 SCIP_Bool* roundup, /**< pointer to store whether the preferred rounding direction is upwards */
648 SCIP_Real* score /**< pointer for diving score value */
649 )
650{
651 SCIP_RANDNUMGEN* randnumgen;
653
654 randnumgen = SCIPdivesetGetRandnumgen(diveset);
655 assert(randnumgen != NULL);
656
657 obj = SCIPvarGetObj(cand);
658
659 /* dive towards the pseudosolution, at the same time approximate the contribution to
660 * a potential Farkas-proof (infeasibility proof) by y^TA_i = c_i.
661 */
662 if( SCIPisNegative(scip, obj) )
663 *roundup = TRUE;
664 else if( SCIPisPositive(scip, obj) )
665 *roundup = FALSE;
666 else
667 {
668 if( SCIPisEQ(scip, candsfrac, 0.5) )
669 *roundup = !SCIPrandomGetInt(randnumgen, 0, 1);
670 else
671 *roundup = (candsfrac > 0.5);
672 }
673
674 /* larger score is better */
675 *score = REALABS(obj) + SCIPrandomGetReal(randnumgen, MIN_RAND, MAX_RAND);
676
677 /* prefer decisions on binary variables */
679 *score = -1.0 / *score;
680}
681
682
683/*
684 * Callback methods
685 */
686
687/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
688static
689SCIP_DECL_HEURCOPY(heurCopyIndicatordiving)
690{ /*lint --e{715}*/
691 assert(scip != NULL);
692 assert(heur != NULL);
693
695
696 /* call inclusion method of primal heuristic */
698
699 return SCIP_OKAY;
700}
701
702
703/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
704static
705SCIP_DECL_HEURFREE(heurFreeIndicatordiving)
706{ /*lint --e{715}*/
708
709 assert(heur != NULL);
710 assert(scip != NULL);
711
713
714 /* free heuristic data */
716 assert(heurdata != NULL);
717
719 SCIPheurSetData(heur, NULL);
720
721 return SCIP_OKAY;
722}
723
724
725/** initialization method of primal heuristic (called after problem was transformed) */
726static
727SCIP_DECL_HEURINIT(heurInitIndicatordiving)
728{ /*lint --e{715}*/
730
731 assert(heur != NULL);
732 assert(scip != NULL);
733
735
736 /* get heuristic data */
738 assert(heurdata != NULL);
739
740 /* create working data */
741 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
743
744 heurdata->indicatorconshdlr = SCIPfindConshdlr(scip, "indicator");
745 heurdata->varboundconshdlr = SCIPfindConshdlr(scip, "varbound");
746
747 return SCIP_OKAY;
748}
749
750
751/** deinitialization method of primal heuristic (called before transformed problem is freed) */
752static
753SCIP_DECL_HEUREXIT(heurExitIndicatordiving)
754{ /*lint --e{715}*/
756
757 assert(heur != NULL);
758 assert(scip != NULL);
759
761
762 /* get heuristic data */
764 assert(heurdata != NULL);
765
766 /* free working data */
769
770 return SCIP_OKAY;
771}
772
773
774/** execution method of primal heuristic */
775static
776SCIP_DECL_HEUREXEC(heurExecIndicatordiving)
777{ /*lint --e{715}*/
780 SCIP_Bool hasunfixedscindconss; /* are there unfixed indicator variables modeling a semicont. variable? */
781
783 assert(heurdata != NULL);
784
785 assert(SCIPheurGetNDivesets(heur) > 0);
787 diveset = SCIPheurGetDivesets(heur)[0];
788 assert(diveset != NULL);
789
790 assert(result != NULL);
792
793 /* check if there are unfixed indicator variables modeling semicont. vars */
794 SCIP_CALL( hasUnfixedSCIndicator(scip, heurdata->indicatorconshdlr, heurdata->scvars, &hasunfixedscindconss) );
795
796 /* skip heuristic if problem doesn't contain unfixed indicator variables,
797 * or if there are no varbound constraints which should be considered
798 */
799 if( !hasunfixedscindconss && (!heurdata->runwithoutscinds || !heurdata->usevarbounds || SCIPconshdlrGetNConss(heurdata->varboundconshdlr) == 0) )
800 return SCIP_OKAY;
801
802 SCIPdebugMsg(scip, "call heurExecIndicatordiving at depth %d \n", SCIPgetDepth(scip));
803
804 /* create and initialize hashmaps */
805 SCIP_CALL( createMaps(scip, heurdata->indicatorconshdlr, heurdata->varboundconshdlr, heurdata->usevarbounds, &heurdata->indicatormap, &heurdata->varboundmap) );
806
807 /* (re-)set flags */
808 heurdata->gotoindconss = FALSE;
809 heurdata->containsviolindconss = FALSE;
810 heurdata->newnode = TRUE;
811 heurdata->probingdepth = -1;
812
813 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
814
815 /* free hashmaps since constraints can get removed/modified till the next call */
816 if( heurdata->usevarbounds )
817 SCIPhashmapFree(&heurdata->varboundmap);
818 SCIPhashmapFree(&heurdata->indicatormap);
819
820 SCIPdebugMsg(scip, "leave heurExecIndicatordiving\n");
821
822 return SCIP_OKAY;
823}
824
825
826/** calculate score and preferred rounding direction for the candidate variable */
827static
828SCIP_DECL_DIVESETGETSCORE(divesetGetScoreIndicatordiving)
829{ /*lint --e{715}*/
830 SCIP_HEUR* heur;
832 SCIP_RANDNUMGEN* randnumgen;
833 SCIP_VAR** consvars;
834 SCIP_CONS* indicatorcons;
835 SCIP_CONS* varboundcons;
836 SCIP_CONS* lincons;
837 SCIP_VAR* nonoptionvar; /* second variable in linear cons which is not the option variable (indicator: slackvar, varbound: binary var) */
838 SCIP_VAR* semicontinuousvar;
839 SCIP_Real lpsolsemicontinuous;
840 SCVARDATA* scdata;
841 SCIP_Real* consvals;
842 SCIP_Real side;
843 int nconsvars;
844 int idxbvars; /* index of bounding variable in hashmap scdata */
845 SCIP_Bool isindicatorvar;
846 SCIP_Bool isvbdvar; /* variable bounding variable in varbound */
847 SCIP_Bool issemicont; /* indicates whether variable has (maybe) required semicont. properties */
848 SCIP_Bool fixconstant; /* should we fix the semicontinuous variable to its constant? */
849 SCIP_Bool success;
850 int v;
851 int b;
852
853 varboundcons = NULL;
854 semicontinuousvar = NULL;
855 scdata = NULL;
856 lpsolsemicontinuous = 0.0;
857 idxbvars = -1;
858 isvbdvar = FALSE;
859 issemicont = TRUE;
860
862 assert(heur != NULL);
864 assert(heurdata != NULL);
865
866 randnumgen = SCIPdivesetGetRandnumgen(diveset);
867 assert(randnumgen != NULL);
868
869 /* check if we are at a new probing node; since diving heuristics backtrack at most one probing node, we are at a new
870 * node iff the probing depth increased */
871 if( heurdata->probingdepth < SCIPgetProbingDepth(scip) )
872 heurdata->newnode = TRUE;
873 else
874 {
875 assert(heurdata->probingdepth == SCIPgetProbingDepth(scip));
876 heurdata->newnode = FALSE;
877 }
878 heurdata->probingdepth = SCIPgetProbingDepth(scip);
879
880 /* skip if current candidate can not be determined by the indicator constraint handler and violated indicator
881 * constraints still exists */
882 if( !(SCIPisFeasIntegral(scip, candsol) && SCIPvarGetLbLocal(cand) < SCIPvarGetUbLocal(cand) - 0.5)
883 && heurdata->gotoindconss )
884 {
885 *score = SCIP_REAL_MIN;
886 *roundup = FALSE;
887 return SCIP_OKAY;
888 }
889 else
890 heurdata->gotoindconss = FALSE;
891
892 /* check if candidate variable is indicator variable */
893 checkAndGetIndicator(scip, cand, heurdata->indicatormap, &indicatorcons, &isindicatorvar,
894 &heurdata->containsviolindconss, heurdata->newnode, heurdata->sol, heurdata->indicatorconshdlr);
895
896 /* skip candidate in next calls since we have violated indicator constraints but current candidate is not determined
897 * by the indicator constraint handler */
898 if( heurdata->containsviolindconss &&
899 !((SCIPisFeasIntegral(scip, candsol) && SCIPvarGetLbLocal(cand) < SCIPvarGetUbLocal(cand) - 0.5) && isindicatorvar) )
900 {
901 heurdata->gotoindconss = TRUE;
902 *score = SCIP_REAL_MIN;
903 *roundup = FALSE;
904 return SCIP_OKAY;
905 }
906
907 /* check if candidate variable is bounding variable */
908 if( heurdata->usevarbounds && !isindicatorvar )
909 {
910 checkAndGetVarbound(scip, cand, heurdata->varboundmap, &varboundcons, &isvbdvar);
911 }
912
913 /* Return
914 * - if candidate variable is neither a indicator variable nor a variable bounding variable
915 * - or if candidate variable is not an indicator variable but there will be indicator variables as candidates
916 * - or if candidate variable is not an indicator variable and varbound constraints are not considered.
917 */
918 if( !isindicatorvar && (!isvbdvar || heurdata->containsviolindconss || !heurdata->usevarbounds) )
919 {
920 *score = SCIP_REAL_MIN;
921 *roundup = FALSE;
922
923 if( !heurdata->containsviolindconss && !isvbdvar )
924 {
925 getScoreOfFarkasDiving(scip, diveset, cand, candsfrac, roundup, score);
926 *score = (*score / (100 + fabs(*score))) * 100 - 200; /* scale to [-300,-100] */
927 }
928 return SCIP_OKAY;
929 }
930
931 SCIPdebugMsg(scip, "cand: %s, candsol: %.2f, candobjcoeff: %f\n", SCIPvarGetName(cand), candsol, SCIPvarGetObj(cand));
932
933 if( isindicatorvar ) /* prefer indicator constraint */
934 {
935 SCIP_Real rhs;
936
937 lincons = SCIPgetLinearConsIndicator(indicatorcons);
938 nonoptionvar = SCIPgetSlackVarIndicator(indicatorcons);
939 rhs = SCIPconsGetRhs(scip, lincons, &success);
940 issemicont = SCIPisInfinity(scip, -SCIPconsGetLhs(scip, lincons, &success)); /* TODO: allow also indicators for lower bounds */
941 side = rhs;
942 }
943 else
944 {
945 SCIP_Real rhs;
946 SCIP_Real lhs;
947
948 assert(isvbdvar);
949
950 lincons = varboundcons;
951 nonoptionvar = SCIPgetVbdvarVarbound(scip, varboundcons);
952 rhs = SCIPconsGetRhs(scip, lincons, &success);
953 lhs = SCIPconsGetLhs(scip, lincons, &success);
954 side = SCIPisInfinity(scip, rhs) ? lhs : rhs;
955 assert(!SCIPisInfinity(scip, side));
956 }
957 SCIPdebugPrintCons(scip, lincons, NULL);
958
959 SCIP_CALL( SCIPgetConsNVars(scip, lincons, &nconsvars, &success) );
960
961 if( nconsvars != 2 || !issemicont )
962 {
963 getScoreOfFarkasDiving(scip, diveset, cand, candsfrac, roundup, score);
964 *score = (*score / (100 + fabs(*score))) * 100 - 200; /* scale to [-300,-100] */
965 return SCIP_OKAY;
966 }
967
968 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
969 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
970 SCIP_CALL( SCIPgetConsVars(scip, lincons, consvars, nconsvars, &success) );
971 SCIP_CALL( SCIPgetConsVals(scip, lincons, consvals, nconsvars, &success) );
972
973 issemicont = FALSE;
974 for( v = 0; v < nconsvars ; v++ )
975 {
976 if( consvars[v] == nonoptionvar ) /* note that we have exact two variables */
977 continue;
978
979 semicontinuousvar = consvars[v];
980 lpsolsemicontinuous = SCIPvarGetLPSol( semicontinuousvar );
981 SCIPdebugMsg(scip, "%s lp sol %f %f\n", SCIPvarGetName( semicontinuousvar ), lpsolsemicontinuous,
982 consvals[v] );
983 SCIP_CALL( varIsSemicontinuous(scip, semicontinuousvar, heurdata->scvars, side, &success) );
984
985 /* only allow semicontinuous variables */
986 if( success )
987 {
988 assert(SCIPhashmapExists(heurdata->scvars, (void*) semicontinuousvar));
989 scdata = (SCVARDATA*) SCIPhashmapGetImage(heurdata->scvars, (void*) semicontinuousvar);
990 assert(scdata != NULL);
991
992 for( b = 0; b < scdata->nbnds; b++ )
993 {
994 if( (scdata->bvars[b] == cand || (SCIPvarIsNegated(cand) && scdata->bvars[0] == SCIPvarGetNegationVar(cand)))
995 && SCIPisEQ(scip, side, scdata->vals0[b]) )
996 {
997 /* TODO: handle also more general variables;
998 * currently we handle only variables with domain vals0 < lb1 <= ub1 */
999 if( SCIPisGE(scip, lpsolsemicontinuous, scdata->vals0[b]) && SCIPisLE(scip, lpsolsemicontinuous, scdata->ubs1[b]) )
1000 {
1001 issemicont = TRUE;
1002 idxbvars = b;
1003 break;
1004 }
1005 }
1006 }
1007 }
1008 }
1009
1010 /* only continue if semicontinuous variable */
1011 if( !issemicont )
1012 {
1013 getScoreOfFarkasDiving(scip, diveset, cand, candsfrac, roundup, score);
1014 *score = (*score / (100 + fabs(*score))) * 100 - 200; /* scale to [-300,-100] */
1015 SCIPfreeBufferArray(scip, &consvals);
1016 SCIPfreeBufferArray(scip, &consvars);
1017 return SCIP_OKAY;
1018 }
1019 assert(idxbvars >= 0);
1020 assert(scdata != NULL);
1021
1022 /* Case: Variable is in range [lb1,ub1] */
1023 if( SCIPisGE(scip, lpsolsemicontinuous, scdata->lbs1[idxbvars]) && SCIPisLE(scip, lpsolsemicontinuous, scdata->ubs1[idxbvars]))
1024 {
1025 *score = SCIPrandomGetReal(randnumgen, -1.0, 0.0);
1026 fixconstant = FALSE;
1027 }
1028 /* Case: Variable is equal to constant */
1029 else if( SCIPisEQ(scip, lpsolsemicontinuous, scdata->vals0[idxbvars]) )
1030 {
1031 *score = SCIPrandomGetReal(randnumgen, -1.0, 0.0);
1032 fixconstant = TRUE;
1033 }
1034 /* Case: Variable is between constant and lb1 */
1035 else
1036 {
1037 SCIP_Real shiftedlpsolsemicontinuous = lpsolsemicontinuous;
1038 SCIP_Real shiftedlbs1 = scdata->lbs1[idxbvars];
1039
1040 assert(SCIPisGT(scip, lpsolsemicontinuous, scdata->vals0[idxbvars]) && SCIPisLT(scip, lpsolsemicontinuous, scdata->lbs1[idxbvars]));
1041
1042 /* handle case if constant of semicont. var is not zero -> shift values */
1043 if( !SCIPisZero(scip, scdata->vals0[idxbvars]) )
1044 {
1045 shiftedlpsolsemicontinuous -= scdata->vals0[idxbvars];
1046 shiftedlbs1 -= scdata->vals0[idxbvars];
1047 }
1048
1049 *score = 100 * (shiftedlbs1 - shiftedlpsolsemicontinuous) / shiftedlbs1;
1050 assert(*score>0);
1051
1052 switch( (INDICATORDIVINGROUNDINGMODE)heurdata->roundingmode )
1053 {
1055 fixconstant = (*score > (1 - heurdata->roundingfrac) * 100);
1056 break;
1058 fixconstant = (*score <= (1 - heurdata->roundingfrac) * 100);
1059 break;
1060 default:
1061 return SCIP_INVALIDDATA;
1062 }
1063
1064 switch( heurdata->semicontscoremode )
1065 {
1066 case 0:
1067 break;
1068 case 1:
1069 if( shiftedlpsolsemicontinuous < shiftedlbs1 * heurdata->roundingfrac )
1070 *score = 100 * (shiftedlpsolsemicontinuous / (heurdata->roundingfrac * shiftedlbs1));
1071 else
1072 *score = 100 * (-shiftedlpsolsemicontinuous / ((1 - heurdata->roundingfrac) * shiftedlbs1) + (1 / (1 - heurdata->roundingfrac)) );
1073 break;
1074 case 2:
1075 *score = 100 - *score;
1076 break;
1077 default:
1078 return SCIP_INVALIDDATA;
1079 }
1080 assert(*score>0);
1081 }
1082
1083 /* Set roundup depending on whether we have an indicator constraint or a varbound constraint:
1084 * - indicator constraint: roundup == fix to constant
1085 * - varbound constraint: roundup == push to range
1086 */
1087 *roundup = isindicatorvar ? fixconstant : !fixconstant; /*lint !e644*/
1088
1089 /* free memory */
1090 SCIPfreeBufferArray(scip, &consvals);
1091 SCIPfreeBufferArray(scip, &consvars);
1092
1093 return SCIP_OKAY;
1094}
1095
1096
1097/** callback to check preconditions for diving, e.g., if an incumbent solution is available */
1098static
1099SCIP_DECL_DIVESETAVAILABLE(divesetAvailableIndicatordiving)
1100{
1101 /* Skip if problem doesn't contain indicator constraints.
1102 * If varbound constraints should be considered, skip only if there are also no varbound constraints.
1103 */
1104 *available = SCIPconshdlrGetNActiveConss(SCIPfindConshdlr(scip, "indicator")) == 0;
1105
1106 if( !*available )
1107 {
1108 SCIP_HEUR* heur;
1110
1112 assert(heur != NULL);
1113 heurdata = SCIPheurGetData(heur);
1114 assert(heurdata != NULL);
1115
1116 if( heurdata->runwithoutscinds && heurdata->usevarbounds )
1117 {
1118 *available = SCIPconshdlrGetNActiveConss(SCIPfindConshdlr(scip, "varbound")) == 0;
1119 }
1120 }
1121
1122 return SCIP_OKAY;
1123}
1124
1125/*
1126 * heuristic specific interface methods
1127 */
1128
1129/** creates the indicatordiving heuristic and includes it in SCIP */
1131 SCIP* scip /**< SCIP data structure */
1132 )
1133{
1135 SCIP_HEUR* heur;
1136
1137 /* create indicatordiving primal heuristic data */
1139
1140 heur = NULL;
1141
1142 /* include primal heuristic */
1145 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecIndicatordiving, heurdata) );
1146
1147 assert(heur != NULL);
1148
1149 /* primal heuristic is safe to use in exact solving mode */
1150 SCIPheurMarkExact(heur);
1151
1152 /* set non fundamental callbacks via setter functions */
1153 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyIndicatordiving) );
1154 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeIndicatordiving) );
1155 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitIndicatordiving) );
1156 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitIndicatordiving) );
1157
1158 /* create a diveset (this will automatically install some additional parameters for the heuristic)*/
1162 DIVESET_ISPUBLIC, DIVESET_DIVETYPES, divesetGetScoreIndicatordiving, divesetAvailableIndicatordiving) );
1163
1164 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/roundingfrac",
1165 "in violation case all fractional below this value are fixed to constant",
1166 &heurdata->roundingfrac, FALSE, DEFAULT_ROUNDINGFRAC, 0.0, 1.0, NULL, NULL) );
1167
1168 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/roundingmode",
1169 "decides which roundingmode is selected (0: conservative, 1: aggressive)",
1170 &heurdata->roundingmode, FALSE, DEFAULT_ROUNDINGMODE, 0, 1, NULL, NULL) );
1171
1172 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/semicontscoremode",
1173 "which values of semi-continuous variables should get a high score? (0: low, 1: middle, 2: high)",
1174 &heurdata->semicontscoremode, FALSE, DEFAULT_SEMICONTSCOREMODE, 0, 2, NULL, NULL) );
1175
1176 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usevarbounds",
1177 "should varbound constraints be considered?",
1178 &heurdata->usevarbounds, FALSE, DEFAULT_USEVARBOUNDS, NULL, NULL) );
1179
1180 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/runwithoutscinds",
1181 "should heur run if there are no indicator constraints modeling semicont. vars?",
1182 &heurdata->runwithoutscinds, FALSE, DEFAULT_RUNWITHOUTSCINDS, NULL, NULL) );
1183
1184 return SCIP_OKAY;
1185}
SCIP_VAR ** b
constraint handler for indicator constraints
#define DEFAULT_RANDSEED
Constraint handler for variable bound constraints .
#define NULL
Definition def.h:257
#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_REAL_MIN
Definition def.h:168
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
SCIP_Bool SCIPisViolatedIndicator(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition misc.c:3613
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
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
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
#define SCIPdebugMsg
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 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 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 SCIPincludeHeurIndicatordiving(SCIP *scip)
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4782
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4739
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition scip_cons.c:2621
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition scip_cons.c:2577
SCIP_RETCODE SCIPcreateDiveset(SCIP *scip, SCIP_DIVESET **diveset, SCIP_HEUR *heur, const char *name, SCIP_Real minreldepth, SCIP_Real maxreldepth, SCIP_Real maxlpiterquot, SCIP_Real maxdiveubquot, SCIP_Real maxdiveavgquot, SCIP_Real maxdiveubquotnosol, SCIP_Real maxdiveavgquotnosol, SCIP_Real lpresolvedomchgquot, int lpsolvefreq, int maxlpiterofs, unsigned int initialseed, SCIP_Bool backtrack, SCIP_Bool onlylpbranchcands, SCIP_Bool ispublic, SCIP_Bool specificsos1score, SCIP_DECL_DIVESETGETSCORE((*divesetgetscore)),)
Definition scip_heur.c:323
SCIP_RANDNUMGEN * SCIPdivesetGetRandnumgen(SCIP_DIVESET *diveset)
Definition heur.c:720
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
int SCIPheurGetNDivesets(SCIP_HEUR *heur)
Definition heur.c:1675
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition heur.c:1457
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:215
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition heur.c:1467
SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
Definition heur.c:1665
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition heur.c:1378
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
#define SCIPallocClearBlockMemory(scip, ptr)
Definition scip_mem.h:91
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
int SCIPgetProbingDepth(SCIP *scip)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition var.c:24514
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition var.c:24536
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition var.c:24546
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:24556
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24696
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:23910
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition var.c:24526
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition var.c:24588
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition var.c:24568
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition var.c:24578
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition misc.c:10245
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition misc.c:10223
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_HEUR * SCIPdivesetGetHeur(SCIP_DIVESET *diveset)
Definition heur.c:416
#define DEFAULT_ONLYLPBRANCHCANDS
#define DEFAULT_MAXDIVEUBQUOT
#define DEFAULT_LPRESOLVEDOMCHGQUOT
#define HEUR_TIMING
return SCIP_OKAY
#define DEFAULT_MAXLPITERQUOT
#define HEUR_FREQOFS
#define HEUR_DESC
#define DEFAULT_MAXDIVEAVGQUOT
#define DEFAULT_LPSOLVEFREQ
#define DEFAULT_BACKTRACK
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define DEFAULT_MAXRELDEPTH
#define DEFAULT_MAXLPITEROFS
SCIPfreeSol(scip, &heurdata->sol))
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
#define HEUR_NAME
#define DIVESET_DIVETYPES
#define DIVESET_ISPUBLIC
#define HEUR_FREQ
#define DEFAULT_MINRELDEPTH
#define HEUR_USESSUBSCIP
static SCIP_DIVESET * diveset
SCIPcreateSol(scip, &heurdata->sol, heur))
SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, lpiterlimit, -1, -1.0, SCIP_DIVECONTEXT_ADAPTIVE))
#define MAX_RAND
#define MIN_RAND
static SCIP_RETCODE releaseSCHashmap(SCIP *scip, SCIP_HASHMAP *hashmap)
struct SCVarData SCVARDATA
#define DEFAULT_ROUNDINGMODE
static void checkAndGetIndicator(SCIP *scip, SCIP_VAR *cand, SCIP_HASHMAP *map, SCIP_CONS **cons, SCIP_Bool *isindicator, SCIP_Bool *containsviolindconss, SCIP_Bool newnode, SCIP_SOL *sol, SCIP_CONSHDLR *conshdlr)
static SCIP_RETCODE createMaps(SCIP *scip, SCIP_CONSHDLR *indicatorconshdlr, SCIP_CONSHDLR *varboundconshdlr, SCIP_Bool usevarbounds, SCIP_HASHMAP **indicatormap, SCIP_HASHMAP **varboundmap)
#define DEFAULT_USEVARBOUNDS
enum IndicatorDivingRoundingMode INDICATORDIVINGROUNDINGMODE
static SCIP_RETCODE hasUnfixedSCIndicator(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_HASHMAP *scvars, SCIP_Bool *hasunfixedscindconss)
static void getScoreOfFarkasDiving(SCIP *scip, SCIP_DIVESET *diveset, SCIP_VAR *cand, SCIP_Real candsfrac, SCIP_Bool *roundup, SCIP_Real *score)
#define DEFAULT_SEMICONTSCOREMODE
#define DEFAULT_ROUNDINGFRAC
static SCIP_RETCODE varIsSemicontinuous(SCIP *scip, SCIP_VAR *var, SCIP_HASHMAP *scvars, SCIP_Real constant, SCIP_Bool *result)
static void checkAndGetVarbound(SCIP *scip, SCIP_VAR *cand, SCIP_HASHMAP *map, SCIP_CONS **cons, SCIP_Bool *isvarbound)
static SCIP_RETCODE addSCVarIndicator(SCIP *scip, SCVARDATA *scvdata, SCIP_VAR *indicator, SCIP_Real val0, SCIP_Real lb1, SCIP_Real ub1)
static SCIP_Bool isViolatedAndNotFixed(SCIP *scip, SCIP_SOL *sol, SCIP_CONS *cons)
#define DEFAULT_RUNWITHOUTSCINDS
IndicatorDivingRoundingMode
@ ROUNDING_CONSERVATIVE
@ ROUNDING_AGGRESSIVE
LP diving heuristic that fixes indicator variables controlling semicontinuous variables.
int c
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_VAR * var
SCIP_Bool roundup
methods commonly used by primal heuristics
SCIP_Real SCIPconsGetLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPgetConsVals(SCIP *scip, SCIP_CONS *cons, SCIP_Real *vals, int varssize, SCIP_Bool *success)
SCIP_Real SCIPconsGetRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition misc_linear.c:48
public methods for managing constraints
public methods for primal heuristics
public methods for message output
#define SCIPdebugPrintCons(x, y, z)
public data structures and miscellaneous methods
public methods for problem variables
public methods for constraint handler plugins and constraints
public methods for primal heuristic plugins and divesets
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for the branch-and-bound tree
SCIP_Real * vals0
SCIP_VAR ** bvars
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_DIVESETAVAILABLE(x)
Definition type_heur.h:199
#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_HEURINIT(x)
Definition type_heur.h:113
struct SCIP_Diveset SCIP_DIVESET
Definition type_heur.h:78
#define SCIP_DECL_HEUREXIT(x)
Definition type_heur.h:121
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_DIVESETGETSCORE(x)
Definition type_heur.h:184
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
@ SCIP_DIVECONTEXT_SINGLE
Definition type_heur.h:69
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_HashMapEntry SCIP_HASHMAPENTRY
Definition type_misc.h:100
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_INVALIDDATA
@ 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
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64