SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_rounding.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_rounding.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief LP rounding heuristic that tries to recover from intermediate infeasibilities
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/heur_rounding.h"
35#include "scip/pub_heur.h"
36#include "scip/pub_lp.h"
37#include "scip/pub_message.h"
38#include "scip/pub_var.h"
39#include "scip/scip_branch.h"
40#include "scip/scip_heur.h"
41#include "scip/scip_lp.h"
42#include "scip/scip_mem.h"
43#include "scip/scip_message.h"
44#include "scip/scip_numerics.h"
45#include "scip/scip_param.h"
46#include "scip/scip_sol.h"
48
49
50#define HEUR_NAME "rounding"
51#define HEUR_DESC "LP rounding heuristic with infeasibility recovering"
52#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ROUNDING
53#define HEUR_PRIORITY -1000
54#define HEUR_FREQ 1
55#define HEUR_FREQOFS 0
56#define HEUR_MAXDEPTH -1
57#define HEUR_TIMING SCIP_HEURTIMING_DURINGLPLOOP
58#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
59
60#define DEFAULT_SUCCESSFACTOR 100 /**< number of calls per found solution that are considered as standard success,
61 * a higher factor causes the heuristic to be called more often
62 */
63#define DEFAULT_ONCEPERNODE FALSE /**< should the heuristic only be called once per node? */
64
65/* locally defined heuristic data */
66struct SCIP_HeurData
67{
68 SCIP_SOL* sol; /**< working solution */
69 SCIP_Longint lastlp; /**< last LP number where the heuristic was applied */
70 int successfactor; /**< number of calls per found solution that are considered as standard success,
71 * a higher factor causes the heuristic to be called more often
72 */
73 SCIP_Bool oncepernode; /**< should the heuristic only be called once per node? */
74};
75
76
77/*
78 * local methods
79 */
80
81/** update row violation arrays after a row's activity value changed */
82static
84 SCIP* scip, /**< SCIP data structure */
85 SCIP_ROW* row, /**< LP row */
86 SCIP_ROW** violrows, /**< array with currently violated rows */
87 int* violrowpos, /**< position of LP rows in violrows array */
88 int* nviolrows, /**< pointer to the number of currently violated rows */
89 SCIP_Real oldactivity, /**< old activity value of LP row */
90 SCIP_Real newactivity /**< new activity value of LP row */
91 )
92{
93 SCIP_Real lhs;
94 SCIP_Real rhs;
95 SCIP_Bool oldviol;
96 SCIP_Bool newviol;
97
101
102 lhs = SCIProwGetLhs(row);
103 rhs = SCIProwGetRhs(row);
104 oldviol = (SCIPisFeasLT(scip, oldactivity, lhs) || SCIPisFeasGT(scip, oldactivity, rhs));
105 newviol = (SCIPisFeasLT(scip, newactivity, lhs) || SCIPisFeasGT(scip, newactivity, rhs));
106 if( oldviol != newviol )
107 {
108 int rowpos;
109 int violpos;
110
111 rowpos = SCIProwGetLPPos(row);
112 assert(rowpos >= 0);
113
114 if( oldviol )
115 {
116 /* the row violation was repaired: remove row from violrows array, decrease violation count */
117 violpos = violrowpos[rowpos];
118 assert(0 <= violpos && violpos < *nviolrows);
119 assert(violrows[violpos] == row);
120 violrowpos[rowpos] = -1;
121 if( violpos != *nviolrows-1 )
122 {
123 violrows[violpos] = violrows[*nviolrows-1];
124 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
125 }
126 (*nviolrows)--;
127 }
128 else
129 {
130 /* the row is now violated: add row to violrows array, increase violation count */
131 assert(violrowpos[rowpos] == -1);
132 violrows[*nviolrows] = row;
133 violrowpos[rowpos] = *nviolrows;
134 (*nviolrows)++;
135 }
136 }
137}
138
139/** update row activities after a variable's solution value changed */
140static
142 SCIP* scip, /**< SCIP data structure */
143 SCIP_Real* activities, /**< LP row activities */
144 SCIP_ROW** violrows, /**< array with currently violated rows */
145 int* violrowpos, /**< position of LP rows in violrows array */
146 int* nviolrows, /**< pointer to the number of currently violated rows */
147 int nlprows, /**< number of rows in current LP */
148 SCIP_VAR* var, /**< variable that has been changed */
149 SCIP_Real oldsolval, /**< old solution value of variable */
150 SCIP_Real newsolval /**< new solution value of variable */
151 )
152{
153 SCIP_COL* col;
154 SCIP_ROW** colrows;
155 SCIP_Real* colvals;
156 SCIP_Real delta;
157 int ncolrows;
158 int r;
159
162 assert(0 <= *nviolrows && *nviolrows <= nlprows);
163
164 delta = newsolval - oldsolval;
165 col = SCIPvarGetCol(var);
166 colrows = SCIPcolGetRows(col);
167 colvals = SCIPcolGetVals(col);
168 ncolrows = SCIPcolGetNLPNonz(col);
169 assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
170
171 for( r = 0; r < ncolrows; ++r )
172 {
173 SCIP_ROW* row;
174 int rowpos;
175
176 row = colrows[r];
177 rowpos = SCIProwGetLPPos(row);
178 assert(-1 <= rowpos && rowpos < nlprows);
179
180 if( rowpos >= 0 && !SCIProwIsLocal(row) )
181 {
182 SCIP_Real oldactivity;
183 SCIP_Real newactivity;
184
185 assert(SCIProwIsInLP(row));
186
187 /* update row activity */
188 oldactivity = activities[rowpos];
189 if( !SCIPisInfinity(scip, -oldactivity) && !SCIPisInfinity(scip, oldactivity) )
190 {
191 newactivity = oldactivity + delta * colvals[r];
192 if( SCIPisInfinity(scip, newactivity) )
193 newactivity = SCIPinfinity(scip);
194 else if( SCIPisInfinity(scip, -newactivity) )
195 newactivity = -SCIPinfinity(scip);
196 activities[rowpos] = newactivity;
197
198 /* update row violation arrays */
199 updateViolations(scip, row, violrows, violrowpos, nviolrows, oldactivity, newactivity);
200 }
201 }
202 }
203
204 return SCIP_OKAY;
205}
206
207/** returns a variable, that pushes activity of the row in the given direction with minimal negative impact on other rows;
208 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
209 * rounding in a direction is forbidden, if this forces the objective value over the upper bound
210 */
211static
213 SCIP* scip, /**< SCIP data structure */
214 SCIP_SOL* sol, /**< primal solution */
215 SCIP_Real minobj, /**< minimal objective value possible after rounding remaining fractional vars */
216 SCIP_ROW* row, /**< LP row */
217 int direction, /**< should the activity be increased (+1) or decreased (-1)? */
218 SCIP_VAR** roundvar, /**< pointer to store the rounding variable, returns NULL if impossible */
219 SCIP_Real* oldsolval, /**< pointer to store old (fractional) solution value of rounding variable */
220 SCIP_Real* newsolval /**< pointer to store new (rounded) solution value of rounding variable */
221 )
222{
223 SCIP_COL* col;
224 SCIP_VAR* var;
225 SCIP_Real val;
226 SCIP_COL** rowcols;
227 SCIP_Real* rowvals;
228 SCIP_Real solval;
229 SCIP_Real roundval;
231 SCIP_Real deltaobj;
232 SCIP_Real bestdeltaobj;
233 int nrowcols;
234 int nlocks;
235 int minnlocks;
236 int c;
237
238 assert(direction == +1 || direction == -1);
239 assert(roundvar != NULL);
240 assert(oldsolval != NULL);
241 assert(newsolval != NULL);
242
243 /* get row entries */
244 rowcols = SCIProwGetCols(row);
245 rowvals = SCIProwGetVals(row);
246 nrowcols = SCIProwGetNLPNonz(row);
247
248 /* select rounding variable */
249 minnlocks = INT_MAX;
250 bestdeltaobj = SCIPinfinity(scip);
251 *roundvar = NULL;
252 for( c = 0; c < nrowcols; ++c )
253 {
254 col = rowcols[c];
255 var = SCIPcolGetVar(col);
256
258 {
259 solval = SCIPgetSolVal(scip, sol, var);
260
261 if( !SCIPisFeasIntegral(scip, solval) )
262 {
263 val = rowvals[c];
265
266 if( direction * val < 0.0 )
267 {
268 /* rounding down */
270 if( nlocks <= minnlocks )
271 {
272 roundval = SCIPfeasFloor(scip, solval);
273 deltaobj = obj * (roundval - solval);
274 if( (nlocks < minnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
275 {
276 minnlocks = nlocks;
277 bestdeltaobj = deltaobj;
278 *roundvar = var;
279 *oldsolval = solval;
280 *newsolval = roundval;
281 }
282 }
283 }
284 else
285 {
286 /* rounding up */
287 assert(direction * val > 0.0);
289 if( nlocks <= minnlocks )
290 {
291 roundval = SCIPfeasCeil(scip, solval);
292 deltaobj = obj * (roundval - solval);
293 if( (nlocks < minnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
294 {
295 minnlocks = nlocks;
296 bestdeltaobj = deltaobj;
297 *roundvar = var;
298 *oldsolval = solval;
299 *newsolval = roundval;
300 }
301 }
302 }
303 }
304 }
305 }
306
307 return SCIP_OKAY;
308}
309
310/** returns a variable, that increases the activity of the row */
311static
313 SCIP* scip, /**< SCIP data structure */
314 SCIP_SOL* sol, /**< primal solution */
315 SCIP_Real minobj, /**< minimal objective value possible after rounding remaining fractional vars */
316 SCIP_ROW* row, /**< LP row */
317 SCIP_VAR** roundvar, /**< pointer to store the rounding variable, returns NULL if impossible */
318 SCIP_Real* oldsolval, /**< old (fractional) solution value of rounding variable */
319 SCIP_Real* newsolval /**< new (rounded) solution value of rounding variable */
320 )
321{
322 return selectRounding(scip, sol, minobj, row, +1, roundvar, oldsolval, newsolval);
323}
324
325/** returns a variable, that decreases the activity of the row */
326static
328 SCIP* scip, /**< SCIP data structure */
329 SCIP_SOL* sol, /**< primal solution */
330 SCIP_Real minobj, /**< minimal objective value possible after rounding remaining fractional vars */
331 SCIP_ROW* row, /**< LP row */
332 SCIP_VAR** roundvar, /**< pointer to store the rounding variable, returns NULL if impossible */
333 SCIP_Real* oldsolval, /**< old (fractional) solution value of rounding variable */
334 SCIP_Real* newsolval /**< new (rounded) solution value of rounding variable */
335 )
336{
337 return selectRounding(scip, sol, minobj, row, -1, roundvar, oldsolval, newsolval);
338}
339
340/** returns a fractional variable, that has most impact on rows in opposite direction, i.e. that is most crucial to
341 * fix in the other direction;
342 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
343 * rounding in a direction is forbidden, if this forces the objective value over the upper bound
344 */
345static
347 SCIP* scip, /**< SCIP data structure */
348 SCIP_SOL* sol, /**< primal solution */
349 SCIP_Real minobj, /**< minimal objective value possible after rounding remaining fractional vars */
350 SCIP_VAR** lpcands, /**< fractional variables in LP */
351 int nlpcands, /**< number of fractional variables in LP */
352 SCIP_VAR** roundvar, /**< pointer to store the rounding variable, returns NULL if impossible */
353 SCIP_Real* oldsolval, /**< old (fractional) solution value of rounding variable */
354 SCIP_Real* newsolval /**< new (rounded) solution value of rounding variable */
355 )
356{
357 SCIP_VAR* var;
358 SCIP_Real solval;
359 SCIP_Real roundval;
361 SCIP_Real deltaobj;
362 SCIP_Real bestdeltaobj;
363 int maxnlocks;
364 int nlocks;
365 int v;
366
367 assert(roundvar != NULL);
368 assert(oldsolval != NULL);
369 assert(newsolval != NULL);
370
371 /* select rounding variable */
372 maxnlocks = -1;
373 bestdeltaobj = SCIPinfinity(scip);
374 *roundvar = NULL;
375 for( v = 0; v < nlpcands; ++v )
376 {
377 var = lpcands[v];
379
380 solval = SCIPgetSolVal(scip, sol, var);
381 if( !SCIPisFeasIntegral(scip, solval) )
382 {
384
385 /* rounding down */
387 if( nlocks >= maxnlocks )
388 {
389 roundval = SCIPfeasFloor(scip, solval);
390 deltaobj = obj * (roundval - solval);
391 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
392 {
393 maxnlocks = nlocks;
394 bestdeltaobj = deltaobj;
395 *roundvar = var;
396 *oldsolval = solval;
397 *newsolval = roundval;
398 }
399 }
400
401 /* rounding up */
403 if( nlocks >= maxnlocks )
404 {
405 roundval = SCIPfeasCeil(scip, solval);
406 deltaobj = obj * (roundval - solval);
407 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
408 {
409 maxnlocks = nlocks;
410 bestdeltaobj = deltaobj;
411 *roundvar = var;
412 *oldsolval = solval;
413 *newsolval = roundval;
414 }
415 }
416 }
417 }
418
419 return SCIP_OKAY;
420}
421
422
423/*
424 * Callback methods
425 */
426
427/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
428static
429SCIP_DECL_HEURCOPY(heurCopyRounding)
430{ /*lint --e{715}*/
431 assert(scip != NULL);
432 assert(heur != NULL);
433
435
436 /* call inclusion method of primal heuristic */
438
439 return SCIP_OKAY;
440}
441
442/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
443static
444SCIP_DECL_HEURFREE(heurFreeRounding) /*lint --e{715}*/
445{ /*lint --e{715}*/
447
448 assert(heur != NULL);
450
452
453 /* free heuristic data */
458
459 return SCIP_OKAY;
460}
461
462/** initialization method of primal heuristic (called after problem was transformed) */
463static
464SCIP_DECL_HEURINIT(heurInitRounding) /*lint --e{715}*/
465{ /*lint --e{715}*/
467
469
471 assert(heurdata != NULL);
472
473 /* create heuristic data */
475 heurdata->lastlp = -1;
476
477 return SCIP_OKAY;
478}
479
480/** deinitialization method of primal heuristic (called before transformed problem is freed) */
481static
482SCIP_DECL_HEUREXIT(heurExitRounding) /*lint --e{715}*/
483{ /*lint --e{715}*/
485
487
488 /* free heuristic data */
490 assert(heurdata != NULL);
492
493 return SCIP_OKAY;
494}
495
496/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
497static
498SCIP_DECL_HEURINITSOL(heurInitsolRounding)
499{
501
503
505 assert(heurdata != NULL);
506 heurdata->lastlp = -1;
507
508 /* change the heuristic's timingmask, if nit should be called only once per node */
509 if( heurdata->oncepernode )
511
512 return SCIP_OKAY;
513}
514
515/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
516static
517SCIP_DECL_HEUREXITSOL(heurExitsolRounding)
518{
519 /* reset the timing mask to its default value */
521
522 return SCIP_OKAY;
523}
524
525
526/** execution method of primal heuristic */
527static
528SCIP_DECL_HEUREXEC(heurExecRounding) /*lint --e{715}*/
529{ /*lint --e{715}*/
541 int nfrac;
545 int c;
546 int r;
551
552 assert(scip != NULL);
555
557
559
560 /* only call heuristic, if an optimal LP solution is at hand */
562 return SCIP_OKAY;
563
564 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
566 return SCIP_OKAY;
567
568 /* get heuristic data */
570 assert(heurdata != NULL);
571
572 /* don't call heuristic, if we have already processed the current LP solution */
574 if( nlps == heurdata->lastlp )
575 return SCIP_OKAY;
576 heurdata->lastlp = nlps;
577
578 /* don't call heuristic, if it was not successful enough in the past */
582 if( nnodes % ((ncalls/heurdata->successfactor)/(nsolsfound+1)+1) != 0 )
583 return SCIP_OKAY;
584
585 /* get fractional variables, that should be integral */
587
588 /* only call heuristic, if LP solution is fractional */
589 if( nlpcands == 0 )
590 return SCIP_OKAY;
591
593
594 /* get LP rows */
596
597 SCIPdebugMsg(scip, "executing rounding heuristic: %d LP rows, %d LP candidates\n", nlprows, nlpcands);
598
599 /* get memory for activities, violated rows, and row violation positions */
600 nfrac = nlpcands;
604
605 /* get the activities for all globally valid rows;
606 * the rows should be feasible, but due to numerical inaccuracies in the LP solver, they can be violated
607 */
608 nviolrows = 0;
609 for( r = 0; r < nlprows; ++r )
610 {
611 SCIP_ROW* row;
612
613 row = lprows[r];
614 assert(SCIProwGetLPPos(row) == r);
615
616 if( !SCIProwIsLocal(row) )
617 {
621 {
622 violrows[nviolrows] = row;
624 nviolrows++;
625 }
626 else
627 violrowpos[r] = -1;
628 }
629 }
630
631 /* get the working solution from heuristic's local data */
632 sol = heurdata->sol;
634
635 /* copy the current LP solution to the working solution */
637
638 /* calculate the minimal objective value possible after rounding fractional variables */
641 for( c = 0; c < nlpcands; ++c )
642 {
646 }
647
648 /* try to round remaining variables in order to become/stay feasible */
649 while( nfrac > 0 )
650 {
651 SCIP_VAR* roundvar;
652 SCIP_Real oldsolval;
653 SCIP_Real newsolval;
654
655 SCIPdebugMsg(scip, "rounding heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
657
658 /* minobj < SCIPgetCutoffbound(scip) should be true, otherwise the rounding variable selection
659 * should have returned NULL. Due to possible cancellation we use SCIPisLE. */
661
662 /* choose next variable to process:
663 * - if a violated row exists, round a variable decreasing the violation, that has least impact on other rows
664 * - otherwise, round a variable, that has strongest devastating impact on rows in opposite direction
665 */
666 if( nviolrows > 0 )
667 {
668 SCIP_ROW* row;
669 int rowpos;
670
671 row = violrows[nviolrows-1];
672 rowpos = SCIProwGetLPPos(row);
673 assert(0 <= rowpos && rowpos < nlprows);
674 assert(violrowpos[rowpos] == nviolrows-1);
675
676 SCIPdebugMsg(scip, "rounding heuristic: try to fix violated row <%s>: %g <= %g <= %g\n",
677 SCIProwGetName(row), SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row));
678 if( SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row)) )
679 {
680 /* lhs is violated: select a variable rounding, that increases the activity */
681 SCIP_CALL( selectIncreaseRounding(scip, sol, minobj, row, &roundvar, &oldsolval, &newsolval) );
682 }
683 else
684 {
686 /* rhs is violated: select a variable rounding, that decreases the activity */
687 SCIP_CALL( selectDecreaseRounding(scip, sol, minobj, row, &roundvar, &oldsolval, &newsolval) );
688 }
689 }
690 else
691 {
692 SCIPdebugMsg(scip, "rounding heuristic: search rounding variable and try to stay feasible\n");
693 SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &roundvar, &oldsolval, &newsolval) );
694 }
695
696 /* check, whether rounding was possible */
697 if( roundvar == NULL )
698 {
699 SCIPdebugMsg(scip, "rounding heuristic: -> didn't find a rounding variable\n");
700 break;
701 }
702
703 SCIPdebugMsg(scip, "rounding heuristic: -> round var <%s>, oldval=%g, newval=%g, obj=%g\n",
704 SCIPvarGetName(roundvar), oldsolval, newsolval, SCIPvarGetObj(roundvar));
705
706 /* update row activities of globally valid rows */
708 roundvar, oldsolval, newsolval) );
709
710 /* store new solution value and decrease fractionality counter */
711 SCIP_CALL( SCIPsetSolVal(scip, sol, roundvar, newsolval) );
712 nfrac--;
713
714 /* update minimal objective value possible after rounding remaining variables */
715 obj = SCIPvarGetObj(roundvar);
716 if( obj > 0.0 && newsolval > oldsolval )
717 minobj += obj;
718 else if( obj < 0.0 && newsolval < oldsolval )
719 minobj -= obj;
720
721 SCIPdebugMsg(scip, "rounding heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
723 }
724
725 /* check, if the new solution is feasible */
726 if( nfrac == 0 && nviolrows == 0 )
727 {
728 SCIP_Bool stored;
729
730 /* check solution for feasibility, and add it to solution store if possible
731 * neither integrality nor feasibility of LP rows has to be checked, because this is already
732 * done in the rounding heuristic itself; however, be better check feasibility of LP rows,
733 * because of numerical problems with activity updating
734 */
736
737 if( stored )
738 {
739#ifdef SCIP_DEBUG
740 SCIPdebugMsg(scip, "found feasible rounded solution:\n");
742#endif
744 }
745 }
746
747 /* free memory buffers */
751
752 return SCIP_OKAY;
753}
754
755
756/*
757 * heuristic specific interface methods
758 */
759
760/** creates the rounding heuristic with infeasibility recovering and includes it in SCIP */
762 SCIP* scip /**< SCIP data structure */
763 )
764{
766 SCIP_HEUR* heur;
767
768 /* create Rounding primal heuristic data */
770
771 /* include primal heuristic */
774 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRounding, heurdata) );
775
776 assert(heur != NULL);
777
778 /* primal heuristic is safe to use in exact solving mode */
779 SCIPheurMarkExact(heur);
780
781 /* set non-NULL pointers to callback methods */
782 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRounding) );
783 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRounding) );
784 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRounding) );
785 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitRounding) );
786 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolRounding) );
787 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolRounding) );
788
789 /* add rounding primal heuristic parameters */
790 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/successfactor",
791 "number of calls per found solution that are considered as standard success, a higher factor causes the heuristic to be called more often",
792 &heurdata->successfactor, TRUE, DEFAULT_SUCCESSFACTOR, -1, INT_MAX, NULL, NULL) );
793
794 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/oncepernode",
795 "should the heuristic only be called once per node?",
796 &heurdata->oncepernode, TRUE, DEFAULT_ONCEPERNODE, NULL, NULL) );
797
798 return SCIP_OKAY;
799}
#define NULL
Definition def.h:257
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#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 SCIP_CALL(x)
Definition def.h:364
#define nnodes
Definition gastrans.c:74
#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 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 SCIPincludeHeurRounding(SCIP *scip)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
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
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition lp.c:17534
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_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition heur.c:1603
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:231
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition heur.c:1613
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition heur.c:1507
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition heur.c:1593
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:247
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_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
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
const char * SCIProwGetName(SCIP_ROW *row)
Definition lp.c:17745
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:2068
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition lp.c:17642
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition scip_sol.c:2351
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:4017
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:2003
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition scip_sol.c:2134
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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 SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23715
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIP_Longint nsolsfound
SCIP_Longint ncalls
int c
int nlprows
heurdata lastlp
int nfrac
int nviolrows
SCIP_ROW ** lprows
static SCIP_SOL * sol
SCIP_Real * lpcandssol
int * violrowpos
int nlpcands
SCIP_Longint nlps
int r
SCIP_Real minobj
SCIP_Real obj
SCIP_VAR ** lpcands
SCIP_ROW ** violrows
SCIP_VAR * var
#define DEFAULT_ONCEPERNODE
static SCIP_RETCODE selectEssentialRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_VAR **lpcands, int nlpcands, SCIP_VAR **roundvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
SCIPheurSetData(heur, NULL)
#define DEFAULT_SUCCESSFACTOR
static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *activities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
static void updateViolations(SCIP *scip, SCIP_ROW *row, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, SCIP_Real oldactivity, SCIP_Real newactivity)
SCIPfreeSol(scip, &heurdata->sol))
static SCIP_RETCODE selectIncreaseRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_ROW *row, SCIP_VAR **roundvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
SCIP_Real bestroundval
static SCIP_RETCODE selectDecreaseRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_ROW *row, SCIP_VAR **roundvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
SCIP_Real * activities
static SCIP_RETCODE selectRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_ROW *row, int direction, SCIP_VAR **roundvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
assert(minobj< SCIPgetCutoffbound(scip))
SCIPcreateSol(scip, &heurdata->sol, heur))
SCIPlinkLPSol(scip, sol))
LP rounding heuristic that tries to recover from intermediate infeasibilities.
memory allocation routines
public methods for primal heuristics
public methods for LP management
public methods for message output
public methods for problem variables
public methods for branching rule plugins and branching
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 SCIP parameter handling
public methods for solutions
public methods for querying solving statistics
#define SCIP_DECL_HEURINITSOL(x)
Definition type_heur.h:132
#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
#define SCIP_DECL_HEUREXIT(x)
Definition type_heur.h:121
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXITSOL(x)
Definition type_heur.h:143
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
@ 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_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
#define SCIP_HEURTIMING_AFTERLPNODE
Definition type_timing.h:83
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141