Scippy

SCIP

Solving Constraint Integer Programs

heur_intshifting.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_intshifting.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief LP rounding heuristic that tries to recover from intermediate infeasibilities, shifts integer variables, and
28 * solves a final LP to calculate feasible values for continuous variables
29 * @author Tobias Achterberg
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
36#include "scip/pub_heur.h"
37#include "scip/pub_lp.h"
38#include "scip/pub_message.h"
39#include "scip/pub_misc.h"
40#include "scip/pub_var.h"
41#include "scip/scip_branch.h"
42#include "scip/scip_exact.h"
43#include "scip/scip_general.h"
44#include "scip/scip_heur.h"
45#include "scip/scip_lp.h"
46#include "scip/scip_mem.h"
47#include "scip/scip_message.h"
48#include "scip/scip_numerics.h"
49#include "scip/scip_prob.h"
51#include "scip/scip_sol.h"
53#include <string.h>
54
55#define HEUR_NAME "intshifting"
56#define HEUR_DESC "LP rounding heuristic with infeasibility recovering and final LP solving"
57#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ROUNDING
58#define HEUR_PRIORITY -10000
59#define HEUR_FREQ 10
60#define HEUR_FREQOFS 0
61#define HEUR_MAXDEPTH -1
62#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
63#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
64
65#define MAXSHIFTINGS 50 /**< maximal number of non improving shiftings */
66#define WEIGHTFACTOR 1.1
67#define DEFAULT_RANDSEED 17
68
69/* locally defined heuristic data */
70struct SCIP_HeurData
71{
72 SCIP_SOL* sol; /**< working solution */
73 SCIP_Longint lastlp; /**< last LP number where the heuristic was applied */
74 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
75};
76
77
78/*
79 * local methods
80 */
81
82/** update row violation arrays after a row's activity value changed */
83static
85 SCIP* scip, /**< SCIP data structure */
86 SCIP_ROW* row, /**< LP row */
87 SCIP_ROW** violrows, /**< array with currently violated rows */
88 int* violrowpos, /**< position of LP rows in violrows array */
89 int* nviolrows, /**< pointer to the number of currently violated rows */
90 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
91 int* nfracsinrow, /**< array with number of fractional variables for every row */
92 SCIP_Real oldminactivity, /**< old minimal activity value of LP row */
93 SCIP_Real oldmaxactivity, /**< old maximal activity value of LP row */
94 SCIP_Real newminactivity, /**< new minimal activity value of LP row */
95 SCIP_Real newmaxactivity /**< new maximal activity value of LP row */
96 )
97{
98 SCIP_Real lhs;
99 SCIP_Real rhs;
100 SCIP_Bool oldviol;
101 SCIP_Bool newviol;
102
103 assert(violrows != NULL);
104 assert(violrowpos != NULL);
105 assert(nviolrows != NULL);
106
107 lhs = SCIProwGetLhs(row);
108 rhs = SCIProwGetRhs(row);
109
110 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
111 if( ! (SCIPisInfinity(scip, oldmaxactivity) || SCIPisInfinity(scip, -oldmaxactivity)
112 || SCIPisInfinity(scip, oldminactivity) || SCIPisInfinity(scip, -oldminactivity)) )
113 {
114 oldviol = (SCIPisFeasLT(scip, oldmaxactivity, lhs) || SCIPisFeasGT(scip, oldminactivity, rhs));
115 }
116 else
117 {
118 oldviol = (SCIPisInfinity(scip, -oldmaxactivity) && !SCIPisInfinity(scip, -lhs)) ||
119 (SCIPisInfinity(scip, oldminactivity) && !SCIPisInfinity(scip, rhs));
120 }
121
122 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
123 if( ! (SCIPisInfinity(scip, newmaxactivity) || SCIPisInfinity(scip, -newmaxactivity)
124 || SCIPisInfinity(scip, newminactivity) || SCIPisInfinity(scip, -newminactivity)) )
125 {
126 newviol = (SCIPisFeasLT(scip, newmaxactivity, lhs) || SCIPisFeasGT(scip, newminactivity, rhs));
127 }
128 else
129 {
130 newviol = (SCIPisInfinity(scip, -newmaxactivity) && !SCIPisInfinity(scip, -lhs)) ||
131 (SCIPisInfinity(scip, newminactivity) && !SCIPisInfinity(scip, rhs));
132 }
133
134 if( oldviol != newviol )
135 {
136 int rowpos;
137 int violpos;
138
139 rowpos = SCIProwGetLPPos(row);
140 assert(rowpos >= 0);
141
142 if( oldviol )
143 {
144 /* the row violation was repaired: remove row from violrows array, decrease violation count */
145 violpos = violrowpos[rowpos];
146 assert(0 <= violpos && violpos < *nviolrows);
147 assert(violrows[violpos] == row);
148 violrowpos[rowpos] = -1;
149 /* first, move the row to the end of the subset of violated rows with fractional variables */
150 if( nfracsinrow[rowpos] > 0 )
151 {
152 violrows[violpos] = violrows[*nviolrows-1];
153 assert(violpos < *nviolfracrows);
154
155 /* replace with last violated row containing fractional variables */
156 if( violpos != *nviolfracrows - 1 )
157 {
158 violrows[violpos] = violrows[*nviolfracrows - 1];
159 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
160 violpos = *nviolfracrows - 1;
161 }
162 (*nviolfracrows)--;
163 }
164
165 assert(violpos >= *nviolfracrows);
166
167 /* swap row at the end of the violated array to the position of this row and decrease the counter */
168 if( violpos != *nviolrows - 1 )
169 {
170 violrows[violpos] = violrows[*nviolrows - 1];
171 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
172 }
173 (*nviolrows)--;
174 }
175 else
176 {
177 /* the row is now violated: add row to violrows array, increase violation count */
178 assert(violrowpos[rowpos] == -1);
179 violrows[*nviolrows] = row;
180 violrowpos[rowpos] = *nviolrows;
181 (*nviolrows)++;
182
183 /* if the row contains fractional variables, swap with the last violated row that has no fractional variables
184 * at position *nviolfracrows
185 */
186 if( nfracsinrow[rowpos] > 0 )
187 {
188 if( *nviolfracrows < *nviolrows - 1 )
189 {
190 assert(nfracsinrow[SCIProwGetLPPos(violrows[*nviolfracrows])] == 0);
191
192 violrows[*nviolrows - 1] = violrows[*nviolfracrows];
193 violrowpos[SCIProwGetLPPos(violrows[*nviolrows - 1])] = *nviolrows - 1;
194
195 violrows[*nviolfracrows] = row;
196 violrowpos[rowpos] = *nviolfracrows;
197 }
198 (*nviolfracrows)++;
199 }
200 }
201 }
202}
203
204/** update row activities after a variable's solution value changed */
205static
207 SCIP* scip, /**< SCIP data structure */
208 SCIP_Real* minactivities, /**< LP row minimal activities */
209 SCIP_Real* maxactivities, /**< LP row maximal activities */
210 SCIP_ROW** violrows, /**< array with currently violated rows */
211 int* violrowpos, /**< position of LP rows in violrows array */
212 int* nviolrows, /**< pointer to the number of currently violated rows */
213 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
214 int* nfracsinrow, /**< array with number of fractional variables for every row */
215 int nlprows, /**< number of rows in current LP */
216 SCIP_VAR* var, /**< variable that has been changed */
217 SCIP_Real oldsolval, /**< old solution value of variable */
218 SCIP_Real newsolval /**< new solution value of variable */
219 )
220{
221 SCIP_COL* col;
222 SCIP_ROW** colrows;
223 SCIP_Real* colvals;
224 SCIP_Real delta;
225 int ncolrows;
226 int r;
227
228 assert(minactivities != NULL);
229 assert(maxactivities != NULL);
230 assert(nviolrows != NULL);
231 assert(0 <= *nviolrows && *nviolrows <= nlprows);
233
234 delta = newsolval - oldsolval;
235 col = SCIPvarGetCol(var);
236 colrows = SCIPcolGetRows(col);
237 colvals = SCIPcolGetVals(col);
238 ncolrows = SCIPcolGetNLPNonz(col);
239 assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
240
241 for( r = 0; r < ncolrows; ++r )
242 {
243 SCIP_ROW* row;
244 int rowpos;
245
246 row = colrows[r];
247 rowpos = SCIProwGetLPPos(row);
248 assert(-1 <= rowpos && rowpos < nlprows);
249
250 if( rowpos >= 0 && !SCIProwIsLocal(row) )
251 {
252 SCIP_Real oldminactivity;
253 SCIP_Real oldmaxactivity;
254 SCIP_Real newminactivity;
255 SCIP_Real newmaxactivity;
256
257 assert(SCIProwIsInLP(row));
258
259 /* update row activities */
260 oldminactivity = minactivities[rowpos];
261 oldmaxactivity = maxactivities[rowpos];
262
263 if( !SCIPisInfinity(scip, -oldminactivity) )
264 {
265 newminactivity = oldminactivity + delta * colvals[r];
266 minactivities[rowpos] = newminactivity;
267 }
268 else
269 newminactivity = -SCIPinfinity(scip);
270 if( !SCIPisInfinity(scip, oldmaxactivity) )
271 {
272 newmaxactivity = oldmaxactivity + delta * colvals[r];
273 maxactivities[rowpos] = newmaxactivity;
274 }
275 else
276 newmaxactivity = SCIPinfinity(scip);
277
278 /* update row violation arrays */
279 updateViolations(scip, row, violrows, violrowpos, nviolrows, nviolfracrows, nfracsinrow, oldminactivity, oldmaxactivity,
280 newminactivity, newmaxactivity);
281 }
282 }
283
284 return SCIP_OKAY;
285}
286
287/** returns an integer variable, that pushes activity of the row in the given direction with minimal negative impact on
288 * other rows;
289 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
290 * prefer fractional integers over other variables in order to become integral during the process;
291 * shifting in a direction is forbidden, if this forces the objective value over the upper bound, or if the variable
292 * was already shifted in the opposite direction
293 */
294static
296 SCIP* scip, /**< SCIP data structure */
297 SCIP_SOL* sol, /**< primal solution */
298 SCIP_ROW* row, /**< LP row */
299 SCIP_Real rowactivity, /**< activity of LP row */
300 int direction, /**< should the activity be increased (+1) or decreased (-1)? */
301 SCIP_Real* nincreases, /**< array with weighted number of increasings per variables */
302 SCIP_Real* ndecreases, /**< array with weighted number of decreasings per variables */
303 SCIP_Real increaseweight, /**< current weight of increase/decrease updates */
304 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
305 SCIP_Real* oldsolval, /**< pointer to store old solution value of shifting variable */
306 SCIP_Real* newsolval /**< pointer to store new (shifted) solution value of shifting variable */
307 )
308{
309 SCIP_COL** rowcols;
310 SCIP_Real* rowvals;
311 int nrowcols;
312 SCIP_Real activitydelta;
313 SCIP_Real bestshiftscore;
314 SCIP_Real bestdeltaobj;
315 int c;
316
317 assert(direction == +1 || direction == -1);
318 assert(nincreases != NULL);
319 assert(ndecreases != NULL);
320 assert(shiftvar != NULL);
321 assert(oldsolval != NULL);
322 assert(newsolval != NULL);
323
324 /* get row entries */
325 rowcols = SCIProwGetCols(row);
326 rowvals = SCIProwGetVals(row);
327 nrowcols = SCIProwGetNLPNonz(row);
328
329 /* calculate how much the activity must be shifted in order to become feasible */
330 activitydelta = (direction == +1 ? SCIProwGetLhs(row) - rowactivity : SCIProwGetRhs(row) - rowactivity);
331 assert((direction == +1 && SCIPisPositive(scip, activitydelta))
332 || (direction == -1 && SCIPisNegative(scip, activitydelta)));
333
334 /* select shifting variable */
335 bestshiftscore = SCIP_REAL_MAX;
336 bestdeltaobj = SCIPinfinity(scip);
337 *shiftvar = NULL;
338 *newsolval = 0.0;
339 *oldsolval = 0.0;
340 for( c = 0; c < nrowcols; ++c )
341 {
342 SCIP_COL* col;
343 SCIP_VAR* var;
344 SCIP_Real val;
345 SCIP_Real solval;
346 SCIP_Real shiftval;
347 SCIP_Real shiftscore;
348 SCIP_Bool isfrac;
349 SCIP_Bool increase;
350 int probindex;
351
352 col = rowcols[c];
353 var = SCIPcolGetVar(col);
354 val = rowvals[c];
355 assert(!SCIPisZero(scip, val));
356 solval = SCIPgetSolVal(scip, sol, var);
357
358 /* only accept integer variables */
360 continue;
361
362 isfrac = !SCIPisFeasIntegral(scip, solval);
363 increase = (direction * val > 0.0);
364 probindex = SCIPvarGetProbindex(var);
365
366 /* calculate the score of the shifting (prefer smaller values) */
367 if( isfrac )
368 shiftscore = increase ? -1.0 / (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + 1.0) :
370 else
371 {
372 if( increase )
373 shiftscore = ndecreases[probindex]/increaseweight;
374 else
375 shiftscore = nincreases[probindex]/increaseweight;
376 shiftscore += 1.0;
377 }
378
379 if( shiftscore <= bestshiftscore )
380 {
381 SCIP_Real deltaobj;
382
383 if( !increase )
384 {
385 /* shifting down */
386 assert(direction * val < 0.0);
387 if( isfrac )
388 shiftval = SCIPfeasFloor(scip, solval);
389 else
390 {
391 SCIP_Real lb;
392
393 assert(activitydelta/val < 0.0);
394 shiftval = solval + activitydelta/val;
395 assert(shiftval <= solval); /* may be equal due to numerical digit erasement in the subtraction */
396 shiftval = SCIPfeasFloor(scip, shiftval);
397 lb = SCIPvarGetLbGlobal(var);
398 shiftval = MAX(shiftval, lb);
399 }
400 }
401 else
402 {
403 /* shifting up */
404 assert(direction * val > 0.0);
405 if( isfrac )
406 shiftval = SCIPfeasCeil(scip, solval);
407 else
408 {
409 SCIP_Real ub;
410
411 assert(activitydelta/val > 0.0);
412 shiftval = solval + activitydelta/val;
413 assert(shiftval >= solval); /* may be equal due to numerical digit erasement in the subtraction */
414 shiftval = SCIPfeasCeil(scip, shiftval);
415 ub = SCIPvarGetUbGlobal(var);
416 shiftval = MIN(shiftval, ub);
417 }
418 }
419
420 if( SCIPisEQ(scip, shiftval, solval) )
421 continue;
422
423 deltaobj = SCIPvarGetObj(var) * (shiftval - solval);
424 if( (shiftscore < bestshiftscore || deltaobj < bestdeltaobj)
425 && !SCIPisHugeValue(scip, REALABS(shiftval)) ) /* ignore candidates for which shiftval is too large */
426 {
427 bestshiftscore = shiftscore;
428 bestdeltaobj = deltaobj;
429 *shiftvar = var;
430 *oldsolval = solval;
431 *newsolval = shiftval;
432 }
433 }
434 }
435
436 return SCIP_OKAY;
437}
438
439/** returns a fractional variable, that has most impact on rows in opposite direction, i.e. that is most crucial to
440 * fix in the other direction;
441 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
442 * shifting in a direction is forbidden, if this forces the objective value over the upper bound
443 */
444static
446 SCIP* scip, /**< SCIP data structure */
447 SCIP_SOL* sol, /**< primal solution */
448 SCIP_Real minobj, /**< minimal objective value possible after shifting remaining fractional vars */
449 SCIP_VAR** lpcands, /**< fractional variables in LP */
450 int nlpcands, /**< number of fractional variables in LP */
451 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
452 SCIP_Real* oldsolval, /**< old (fractional) solution value of shifting variable */
453 SCIP_Real* newsolval /**< new (shifted) solution value of shifting variable */
454 )
455{
456 SCIP_VAR* var;
457 SCIP_Real solval;
458 SCIP_Real shiftval;
459 SCIP_Real obj;
460 SCIP_Real deltaobj;
461 SCIP_Real bestdeltaobj;
462 int maxnlocks;
463 int nlocks;
464 int v;
465
466 assert(shiftvar != NULL);
467 assert(oldsolval != NULL);
468 assert(newsolval != NULL);
469
470 /* select shifting variable */
471 maxnlocks = -1;
472 bestdeltaobj = SCIPinfinity(scip);
473 *shiftvar = NULL;
474 for( v = 0; v < nlpcands; ++v )
475 {
476 var = lpcands[v];
478
479 solval = SCIPgetSolVal(scip, sol, var);
480 if( !SCIPisFeasIntegral(scip, solval) )
481 {
482 obj = SCIPvarGetObj(var);
483
484 /* shifting down */
486 if( nlocks >= maxnlocks )
487 {
488 shiftval = SCIPfeasFloor(scip, solval);
489 deltaobj = obj * (shiftval - solval);
490 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
491 {
492 maxnlocks = nlocks;
493 bestdeltaobj = deltaobj;
494 *shiftvar = var;
495 *oldsolval = solval;
496 *newsolval = shiftval;
497 }
498 }
499
500 /* shifting up */
502 if( nlocks >= maxnlocks )
503 {
504 shiftval = SCIPfeasCeil(scip, solval);
505 deltaobj = obj * (shiftval - solval);
506 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
507 {
508 maxnlocks = nlocks;
509 bestdeltaobj = deltaobj;
510 *shiftvar = var;
511 *oldsolval = solval;
512 *newsolval = shiftval;
513 }
514 }
515 }
516 }
517
518 return SCIP_OKAY;
519}
520
521/** adds a given value to the fractionality counters of the rows in which the given variable appears */
522static
524 int* nfracsinrow, /**< array to store number of fractional variables per row */
525 SCIP_ROW** violrows, /**< array with currently violated rows */
526 int* violrowpos, /**< position of LP rows in violrows array */
527 int* nviolfracrows, /**< pointer to store the number of violated rows with fractional variables */
528 int nviolrows, /**< the number of currently violated rows (stays unchanged in this method) */
529 int nlprows, /**< number of rows in LP */
530 SCIP_VAR* var, /**< variable for which the counting should be updated */
531 int incval /**< value that should be added to the corresponding array entries */
532 )
533{
534 SCIP_COL* col;
535 SCIP_ROW** rows;
536 int nrows;
537 int r;
538
539 assert(incval != 0);
540 assert(nviolrows >= *nviolfracrows);
541
542 col = SCIPvarGetCol(var);
543 rows = SCIPcolGetRows(col);
544 nrows = SCIPcolGetNLPNonz(col);
545 for( r = 0; r < nrows; ++r )
546 {
547 int rowlppos;
548 int theviolrowpos;
549 SCIP_ROW* row;
550
551 row = rows[r];
552 assert(NULL != row);
553 rowlppos = SCIProwGetLPPos(row);
554 assert(0 <= rowlppos && rowlppos < nlprows);
555 assert(!SCIProwIsLocal(row) || violrowpos[rowlppos] == -1);
556
557 if( SCIProwIsLocal(row) )
558 continue;
559
560 nfracsinrow[rowlppos] += incval;
561 assert(nfracsinrow[rowlppos] >= 0);
562
563 theviolrowpos = violrowpos[rowlppos];
564
565 /* swap positions in violrows array if fractionality has changed to 0 */
566 if( theviolrowpos >= 0 )
567 {
568 /* first case: the number of fractional variables has become zero: swap row in violrows array to the
569 * second part, containing only violated rows without fractional variables
570 */
571 if( nfracsinrow[rowlppos] == 0 )
572 {
573 assert(theviolrowpos <= *nviolfracrows - 1);
574
575 /* nothing to do if row is already at the end of the first part, otherwise, swap it to the last position
576 * and decrease the counter */
577 if( theviolrowpos < *nviolfracrows - 1 )
578 {
579 violrows[theviolrowpos] = violrows[*nviolfracrows - 1];
580 violrows[*nviolfracrows - 1] = row;
581
582 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
583 violrowpos[rowlppos] = *nviolfracrows - 1;
584 }
585 (*nviolfracrows)--;
586 }
587 /* second interesting case: the number of fractional variables was zero before, swap it with the first
588 * violated row without fractional variables
589 */
590 else if( nfracsinrow[rowlppos] == incval )
591 {
592 assert(theviolrowpos >= *nviolfracrows);
593
594 /* nothing to do if the row is exactly located at index *nviolfracrows */
595 if( theviolrowpos > *nviolfracrows )
596 {
597 violrows[theviolrowpos] = violrows[*nviolfracrows];
598 violrows[*nviolfracrows] = row;
599
600 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
601 violrowpos[rowlppos] = *nviolfracrows;
602 }
603 (*nviolfracrows)++;
604 }
605 }
606 }
607}
608
609
610/*
611 * Callback methods
612 */
613
614/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
615static
616SCIP_DECL_HEURCOPY(heurCopyIntshifting)
617{ /*lint --e{715}*/
618 assert(scip != NULL);
619 assert(heur != NULL);
620 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
621
622 /* call inclusion method of primal heuristic */
624
625 return SCIP_OKAY;
626}
627
628
629/** initialization method of primal heuristic (called after problem was transformed) */
630static
631SCIP_DECL_HEURINIT(heurInitIntshifting) /*lint --e{715}*/
632{ /*lint --e{715}*/
633 SCIP_HEURDATA* heurdata;
634
635 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
636 assert(SCIPheurGetData(heur) == NULL);
637
638 /* create heuristic data */
639 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
640 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
641 heurdata->lastlp = -1;
642 SCIPheurSetData(heur, heurdata);
643
644 /* create random number generator */
645 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
647
648 return SCIP_OKAY;
649}
650
651/** deinitialization method of primal heuristic (called before transformed problem is freed) */
652static
653SCIP_DECL_HEUREXIT(heurExitIntshifting) /*lint --e{715}*/
654{ /*lint --e{715}*/
655 SCIP_HEURDATA* heurdata;
656
657 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
658
659 /* free heuristic data */
660 heurdata = SCIPheurGetData(heur);
661 assert(heurdata != NULL);
662 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
663
664 /* free random number generator */
665 SCIPfreeRandom(scip, &heurdata->randnumgen);
666
667 SCIPfreeBlockMemory(scip, &heurdata);
668 SCIPheurSetData(heur, NULL);
669
670 return SCIP_OKAY;
671}
672
673/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
674static
675SCIP_DECL_HEURINITSOL(heurInitsolIntshifting)
676{
677 SCIP_HEURDATA* heurdata;
678
679 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
680
681 heurdata = SCIPheurGetData(heur);
682 assert(heurdata != NULL);
683 heurdata->lastlp = -1;
684
685 return SCIP_OKAY;
686}
687
688
689/** execution method of primal heuristic */
690static
691SCIP_DECL_HEUREXEC(heurExecIntshifting) /*lint --e{715}*/
692{ /*lint --e{715}*/
693 SCIP_HEURDATA* heurdata;
694 SCIP_SOL* sol;
695 SCIP_VAR** lpcands;
696 SCIP_Real* lpcandssol;
697 SCIP_ROW** lprows;
698 SCIP_Real* minactivities;
699 SCIP_Real* maxactivities;
700 SCIP_ROW** violrows;
701 SCIP_Real* nincreases;
702 SCIP_Real* ndecreases;
703 int* violrowpos;
704 int* nfracsinrow;
705 SCIP_Real increaseweight;
706 SCIP_Real obj;
707 SCIP_Real bestshiftval;
708 SCIP_Real minobj;
709 int nvars;
710 int nfrac;
711 int nlpcands;
712 int nlprows;
713 int nviolrows;
714 int nviolfracrows;
715 int nprevviolrows;
716 int minnviolrows;
717 int nnonimprovingshifts;
718 int c;
719 int r;
720 SCIP_Longint nlps;
721 SCIP_Longint ncalls;
722 SCIP_Longint nsolsfound;
724
725 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
726 assert(scip != NULL);
727 assert(result != NULL);
728 assert(SCIPhasCurrentNodeLP(scip));
729
730 *result = SCIP_DIDNOTRUN;
731
732 /* do not call heuristic of node was already detected to be infeasible */
733 if( nodeinfeasible )
734 return SCIP_OKAY;
735
736 /* don't call heuristic, if no continuous variables are present
737 * -> in this case, it is equivalent to shifting heuristic
738 */
739 if( SCIPgetNContVars(scip) == 0 )
740 return SCIP_OKAY;
741
742 /* only call heuristic, if an optimal LP solution is at hand */
744 return SCIP_OKAY;
745
746 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
748 return SCIP_OKAY;
749
750 /* get heuristic data */
751 heurdata = SCIPheurGetData(heur);
752 assert(heurdata != NULL);
753
754 /* don't call heuristic, if we have already processed the current LP solution */
755 nlps = SCIPgetNLPs(scip);
756 if( nlps == heurdata->lastlp )
757 return SCIP_OKAY;
758 heurdata->lastlp = nlps;
759
760 /* don't call heuristic, if it was not successful enough in the past */
761 ncalls = SCIPheurGetNCalls(heur);
762 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + SCIPheurGetNSolsFound(heur);
764 if( nnodes % (ncalls/(nsolsfound+1)+1) != 0 ) /*?????????? ncalls/100 */
765 return SCIP_OKAY;
766
767 /* get fractional variables, that should be integral */
768 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, NULL) );
769
770 /* only call heuristic, if LP solution is fractional */
771 if( nlpcands == 0 )
772 return SCIP_OKAY;
773
774 *result = SCIP_DIDNOTFIND;
775
776 /* get LP rows */
777 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
778
779 SCIPdebugMsg(scip, "executing intshifting heuristic: %d LP rows, %d LP candidates\n", nlprows, nlpcands);
780
781 /* get memory for activities, violated rows, and row violation positions */
782 nvars = SCIPgetNVars(scip);
783 nfrac = nlpcands;
784 SCIP_CALL( SCIPallocBufferArray(scip, &minactivities, nlprows) );
785 SCIP_CALL( SCIPallocBufferArray(scip, &maxactivities, nlprows) );
786 SCIP_CALL( SCIPallocBufferArray(scip, &violrows, nlprows) );
787 SCIP_CALL( SCIPallocBufferArray(scip, &violrowpos, nlprows) );
788 SCIP_CALL( SCIPallocBufferArray(scip, &nfracsinrow, nlprows) );
789 SCIP_CALL( SCIPallocBufferArray(scip, &nincreases, nvars) );
790 SCIP_CALL( SCIPallocBufferArray(scip, &ndecreases, nvars) );
791 BMSclearMemoryArray(nfracsinrow, nlprows);
792 BMSclearMemoryArray(nincreases, nvars);
793 BMSclearMemoryArray(ndecreases, nvars);
794
795 /* get the minimal and maximal activity for all globally valid rows for continuous variables in their full range;
796 * these are the values of a*x' with x' being the LP solution for integer variables and the lower or upper bound
797 * for the continuous variables
798 */
799 nviolrows = 0;
800 for( r = 0; r < nlprows; ++r )
801 {
802 SCIP_ROW* row;
803
804 row = lprows[r];
805 assert(SCIProwGetLPPos(row) == r);
806
807 if( !SCIProwIsLocal(row) )
808 {
809 SCIP_COL** cols;
810 SCIP_Real* vals;
811 int nnonz;
812 SCIP_Bool mininf;
813 SCIP_Bool maxinf;
814
815 mininf = FALSE;
816 maxinf = FALSE;
817 minactivities[r] = 0.0;
818 maxactivities[r] = 0.0;
819 cols = SCIProwGetCols(row);
820 vals = SCIProwGetVals(row);
821 nnonz = SCIProwGetNNonz(row);
822 for( c = 0; c < nnonz && !(mininf && maxinf); ++c )
823 {
824 SCIP_VAR* var;
825
826 var = SCIPcolGetVar(cols[c]);
828 {
829 SCIP_Real act;
830
831 act = vals[c] * SCIPcolGetPrimsol(cols[c]);
832 minactivities[r] += act;
833 maxactivities[r] += act;
834 }
835 else if( vals[c] > 0.0 )
836 {
837 SCIP_Real lb;
838 SCIP_Real ub;
839
840 lb = SCIPvarGetLbGlobal(var);
841 ub = SCIPvarGetUbGlobal(var);
842 if( SCIPisInfinity(scip, -lb) )
843 mininf = TRUE;
844 else
845 minactivities[r] += vals[c] * lb;
846 if( SCIPisInfinity(scip, ub) )
847 maxinf = TRUE;
848 else
849 maxactivities[r] += vals[c] * ub;
850 }
851 else if( vals[c] < 0.0 )
852 {
853 SCIP_Real lb;
854 SCIP_Real ub;
855
856 lb = SCIPvarGetLbGlobal(var);
857 ub = SCIPvarGetUbGlobal(var);
858 if( SCIPisInfinity(scip, ub) )
859 mininf = TRUE;
860 else
861 minactivities[r] += vals[c] * ub;
862 if( SCIPisInfinity(scip, -lb) )
863 maxinf = TRUE;
864 else
865 maxactivities[r] += vals[c] * lb;
866 }
867
868 if( mininf )
869 minactivities[r] = -SCIPinfinity(scip);
870 if( maxinf )
871 maxactivities[r] = SCIPinfinity(scip);
872 }
873
874 if( SCIPisFeasLT(scip, maxactivities[r], SCIProwGetLhs(row))
875 || SCIPisFeasGT(scip, minactivities[r], SCIProwGetRhs(row)) )
876 {
877 violrows[nviolrows] = row;
878 violrowpos[r] = nviolrows;
879 nviolrows++;
880 }
881 else
882 violrowpos[r] = -1;
883 }
884 else
885 /* if row is a local row */
886 violrowpos[r] = -1;
887 }
888
889 nviolfracrows = 0;
890 /* calc the current number of fractional variables in rows */
891 for( c = 0; c < nlpcands; ++c )
892 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, lpcands[c], +1);
893
894 /* get the working solution from heuristic's local data */
895 sol = heurdata->sol;
896 assert(sol != NULL);
897
898 /* copy the current LP solution to the working solution */
900
901 /* calculate the minimal objective value possible after rounding fractional variables */
902 minobj = SCIPgetSolTransObj(scip, sol);
903 assert(minobj < SCIPgetCutoffbound(scip));
904 for( c = 0; c < nlpcands; ++c )
905 {
906 obj = SCIPvarGetObj(lpcands[c]);
907 bestshiftval = obj > 0.0 ? SCIPfeasFloor(scip, lpcandssol[c]) : SCIPfeasCeil(scip, lpcandssol[c]);
908 minobj += obj * (bestshiftval - lpcandssol[c]);
909 }
910
911 /* try to shift remaining variables in order to become/stay feasible */
912 nnonimprovingshifts = 0;
913 minnviolrows = INT_MAX;
914 increaseweight = 1.0;
915 while( (nfrac > 0 || nviolrows > 0) && nnonimprovingshifts < MAXSHIFTINGS && !SCIPisStopped(scip) )
916 {
917 SCIP_VAR* shiftvar;
918 SCIP_Real oldsolval;
919 SCIP_Real newsolval;
920 SCIP_Bool oldsolvalisfrac;
921 int probindex;
922
923 SCIPdebugMsg(scip, "intshifting heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g), cutoff=%g\n",
924 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj),
926
927 nprevviolrows = nviolrows;
928
929 /* choose next variable to process:
930 * - if a violated row exists, shift a variable decreasing the violation, that has least impact on other rows
931 * - otherwise, shift a variable, that has strongest devastating impact on rows in opposite direction
932 */
933 shiftvar = NULL;
934 oldsolval = 0.0;
935 newsolval = 0.0;
936 if( nviolrows > 0 && (nfrac == 0 || nnonimprovingshifts < MAXSHIFTINGS-1) )
937 {
938 SCIP_ROW* row;
939 int rowidx;
940 int rowpos;
941 int direction;
942
943 assert(nviolfracrows == 0 || nfrac > 0);
944 /* violated rows containing fractional variables are preferred; if such a row exists, choose the last one from the list
945 * (at position nviolfracrows - 1) because removing this row will cause one swapping operation less than other rows
946 */
947 if( nviolfracrows > 0 )
948 rowidx = nviolfracrows - 1;
949 else
950 rowidx = SCIPrandomGetInt(heurdata->randnumgen, 0, nviolrows-1);
951
952 assert(0 <= rowidx && rowidx < nviolrows);
953 row = violrows[rowidx];
954 rowpos = SCIProwGetLPPos(row);
955 assert(0 <= rowpos && rowpos < nlprows);
956 assert(violrowpos[rowpos] == rowidx);
957 assert(nfracsinrow[rowpos] == 0 || rowidx == nviolfracrows - 1);
958
959 SCIPdebugMsg(scip, "intshifting heuristic: try to fix violated row <%s>: %g <= [%g,%g] <= %g\n",
960 SCIProwGetName(row), SCIProwGetLhs(row), minactivities[rowpos], maxactivities[rowpos], SCIProwGetRhs(row));
962
963 /* get direction in which activity must be shifted */
964 assert(SCIPisFeasLT(scip, maxactivities[rowpos], SCIProwGetLhs(row))
965 || SCIPisFeasGT(scip, minactivities[rowpos], SCIProwGetRhs(row)));
966 direction = SCIPisFeasLT(scip, maxactivities[rowpos], SCIProwGetLhs(row)) ? +1 : -1;
967
968 /* search an integer variable that can shift the activity in the necessary direction */
969 SCIP_CALL( selectShifting(scip, sol, row, direction == +1 ? maxactivities[rowpos] : minactivities[rowpos],
970 direction, nincreases, ndecreases, increaseweight, &shiftvar, &oldsolval, &newsolval) );
971 }
972
973 if( shiftvar == NULL && nfrac > 0 )
974 {
975 SCIPdebugMsg(scip, "intshifting heuristic: search rounding variable and try to stay feasible\n");
976 SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &shiftvar, &oldsolval, &newsolval) );
977 }
978
979 /* check, whether shifting was possible */
980 if( shiftvar == NULL || SCIPisEQ(scip, oldsolval, newsolval) )
981 {
982 SCIPdebugMsg(scip, "intshifting heuristic: -> didn't find a shifting variable\n");
983 break;
984 }
985
986 assert(SCIPvarGetType(shiftvar) != SCIP_VARTYPE_CONTINUOUS);
987
988 SCIPdebugMsg(scip, "intshifting heuristic: -> shift var <%s>[%g,%g], type=%d, oldval=%g, newval=%g, obj=%g\n",
989 SCIPvarGetName(shiftvar), SCIPvarGetLbGlobal(shiftvar), SCIPvarGetUbGlobal(shiftvar), SCIPvarGetType(shiftvar),
990 oldsolval, newsolval, SCIPvarGetObj(shiftvar));
991
992 /* update row activities of globally valid rows */
993 SCIP_CALL( updateActivities(scip, minactivities, maxactivities, violrows, violrowpos, &nviolrows, &nviolfracrows,
994 nfracsinrow, nlprows, shiftvar, oldsolval, newsolval) );
995
996 if( nviolrows >= nprevviolrows )
997 nnonimprovingshifts++;
998 else if( nviolrows < minnviolrows )
999 {
1000 minnviolrows = nviolrows;
1001 nnonimprovingshifts = 0;
1002 }
1003
1004 /* store new solution value and decrease fractionality counter */
1005 SCIP_CALL( SCIPsetSolVal(scip, sol, shiftvar, newsolval) );
1006
1007 /* update fractionality counter and minimal objective value possible after shifting remaining variables */
1008 oldsolvalisfrac = !SCIPisFeasIntegral(scip, oldsolval);
1009 obj = SCIPvarGetObj(shiftvar);
1010 if( oldsolvalisfrac )
1011 {
1012 assert(SCIPisFeasIntegral(scip, newsolval));
1013 nfrac--;
1014 nnonimprovingshifts = 0;
1015 minnviolrows = INT_MAX;
1016 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, shiftvar, -1);
1017
1018 /* the rounding was already calculated into the minobj -> update only if rounding in "wrong" direction */
1019 if( obj > 0.0 && newsolval > oldsolval )
1020 minobj += obj;
1021 else if( obj < 0.0 && newsolval < oldsolval )
1022 minobj -= obj;
1023 }
1024 else
1025 {
1026 /* update minimal possible objective value */
1027 minobj += obj * (newsolval - oldsolval);
1028 }
1029
1030 /* update increase/decrease arrays */
1031 if( !oldsolvalisfrac )
1032 {
1033 probindex = SCIPvarGetProbindex(shiftvar);
1034 assert(0 <= probindex && probindex < nvars);
1035 increaseweight *= WEIGHTFACTOR;
1036 if( newsolval < oldsolval )
1037 ndecreases[probindex] += increaseweight;
1038 else
1039 nincreases[probindex] += increaseweight;
1040 if( increaseweight >= 1e+09 )
1041 {
1042 int i;
1043
1044 for( i = 0; i < nvars; ++i )
1045 {
1046 nincreases[i] /= increaseweight;
1047 ndecreases[i] /= increaseweight;
1048 }
1049 increaseweight = 1.0;
1050 }
1051 }
1052
1053 SCIPdebugMsg(scip, "intshifting heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
1054 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj));
1055 }
1056
1057 /* check, if the new solution is potentially feasible and solve the LP to calculate values for the continuous
1058 * variables
1059 */
1060 if( nfrac == 0 && nviolrows == 0 )
1061 {
1062 SCIP_VAR** vars;
1063 SCIP_Bool lperror;
1064 int nintvars;
1065 int v;
1066#ifdef NDEBUG
1067 SCIP_RETCODE retstat;
1068#endif
1069
1070 SCIPdebugMsg(scip, "shifted solution is potentially feasible -> solve LP to fix continuous variables\n");
1071
1072 /* start diving to calculate the LP relaxation */
1074
1075 /* set the bounds of the variables: fixed for binaries and integers, global bounds for continuous */
1076 vars = SCIPgetVars(scip);
1078 assert(nintvars >= 0);
1079 for( v = 0; v < nvars; ++v )
1080 {
1081 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_COLUMN )
1082 {
1083 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], SCIPvarGetLbGlobal(vars[v])) );
1084 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], SCIPvarGetUbGlobal(vars[v])) );
1085 }
1086 }
1087 for( v = 0; v < nintvars; ++v ) /* apply this after global bounds to not cause an error with intermediate empty domains */
1088 {
1089 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_COLUMN )
1090 {
1091 SCIP_Real solval;
1092 solval = SCIPgetSolVal(scip, sol, vars[v]);
1093 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], solval) );
1094 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], solval) );
1095 }
1096 }
1097
1098 /* solve LP */
1099 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
1100
1101 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
1102 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1103 */
1104#ifdef NDEBUG
1105 retstat = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
1106 if( retstat != SCIP_OKAY )
1107 {
1108 SCIPwarningMessage(scip, "Error while solving LP in Intshifting heuristic; LP solve terminated with code <%d>\n",retstat);
1109 }
1110#else
1111 SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
1112#endif
1113
1114 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
1115 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
1116
1117 /* check if this is a feasible solution */
1118 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
1119 {
1120 SCIP_Bool stored;
1121
1122 /* copy the current LP solution to the working solution */
1123 SCIP_CALL( SCIPlinkLPSol(scip, sol) );
1124
1125 /* in exact mode we have to end diving prior to trying the solution */
1126 if( SCIPisExact(scip) )
1127 {
1128 SCIP_CALL( SCIPunlinkSol(scip, heurdata->sol) );
1130 }
1131
1132 /* check solution for feasibility, and add it to solution store if possible
1133 * neither integrality nor feasibility of LP rows has to be checked, because this is already
1134 * done in the intshifting heuristic itself and due to the LP resolve
1135 */
1136 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, FALSE, FALSE, &stored) );
1137
1138 if( stored )
1139 {
1140 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
1142 *result = SCIP_FOUNDSOL;
1143 }
1144 }
1145
1146 /* terminate the diving */
1147 if( SCIPinDive(scip) )
1148 {
1150 }
1151 }
1152
1153 /* free memory buffers */
1154 SCIPfreeBufferArray(scip, &ndecreases);
1155 SCIPfreeBufferArray(scip, &nincreases);
1156 SCIPfreeBufferArray(scip, &nfracsinrow);
1157 SCIPfreeBufferArray(scip, &violrowpos);
1158 SCIPfreeBufferArray(scip, &violrows);
1159 SCIPfreeBufferArray(scip, &maxactivities);
1160 SCIPfreeBufferArray(scip, &minactivities);
1161
1162 return SCIP_OKAY;
1163}
1164
1165
1166/*
1167 * heuristic specific interface methods
1168 */
1169
1170/** creates the intshifting heuristic with infeasibility recovering and includes it in SCIP */
1172 SCIP* scip /**< SCIP data structure */
1173 )
1174{
1175 SCIP_HEUR* heur;
1176
1177 /* include primal heuristic */
1180 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecIntshifting, NULL) );
1181
1182 assert(heur != NULL);
1183
1184 /* primal heuristic is safe to use in exact solving mode */
1185 SCIPheurMarkExact(heur);
1186
1187 /* set non-NULL pointers to callback methods */
1188 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyIntshifting) );
1189 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitIntshifting) );
1190 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitIntshifting) );
1191 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolIntshifting) );
1192
1193 return SCIP_OKAY;
1194}
SCIP_Real * r
Definition: circlepacking.c:59
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
#define nnodes
Definition: gastrans.c:74
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
int SCIPgetNContImplVars(SCIP *scip)
Definition: scip_prob.c:2522
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPincludeHeurIntshifting(SCIP *scip)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip_branch.c:402
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17425
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17555
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17545
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:17379
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:17534
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:167
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip_heur.c:122
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1603
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:215
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1613
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1593
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:231
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition: heur.c:1457
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1378
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2384
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2416
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition: scip_lp.c:2206
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip_lp.c:2643
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition: scip_lp.c:2255
SCIP_Bool SCIPinDive(SCIP *scip)
Definition: scip_lp.c:2740
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:87
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip_lp.c:576
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:174
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:253
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17686
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17607
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17632
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17696
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:17621
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17895
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17795
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2176
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17745
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17917
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17642
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:2349
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1506
SCIP_RETCODE SCIPtrySol(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:4012
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1295
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1892
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1571
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:2005
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip_sol.c:2132
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:23683
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10223
static SCIP_DECL_HEUREXIT(heurExitIntshifting)
static SCIP_RETCODE selectEssentialRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_VAR **lpcands, int nlpcands, SCIP_VAR **shiftvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
static void updateViolations(SCIP *scip, SCIP_ROW *row, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, SCIP_Real oldminactivity, SCIP_Real oldmaxactivity, SCIP_Real newminactivity, SCIP_Real newmaxactivity)
#define HEUR_TIMING
static void addFracCounter(int *nfracsinrow, SCIP_ROW **violrows, int *violrowpos, int *nviolfracrows, int nviolrows, int nlprows, SCIP_VAR *var, int incval)
#define HEUR_FREQOFS
#define HEUR_DESC
static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *minactivities, SCIP_Real *maxactivities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
static SCIP_DECL_HEUREXEC(heurExecIntshifting)
#define HEUR_NAME
static SCIP_DECL_HEURINIT(heurInitIntshifting)
#define DEFAULT_RANDSEED
static SCIP_DECL_HEURINITSOL(heurInitsolIntshifting)
#define HEUR_FREQ
static SCIP_RETCODE selectShifting(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *row, SCIP_Real rowactivity, int direction, SCIP_Real *nincreases, SCIP_Real *ndecreases, SCIP_Real increaseweight, SCIP_VAR **shiftvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
static SCIP_DECL_HEURCOPY(heurCopyIntshifting)
#define HEUR_USESSUBSCIP
#define WEIGHTFACTOR
#define MAXSHIFTINGS
LP rounding heuristic that tries to recover from intermediate infeasibilities, shifts integer variabl...
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
public methods for primal heuristics
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for problem variables
public methods for branching rule plugins and branching
public methods for exact solving
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 numerical tolerances
public methods for global and local (sub)problems
public methods for random numbers
public methods for solutions
public methods for querying solving statistics
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_FOUNDSOL
Definition: type_result.h:56
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141