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#include <string.h>
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 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
434
435 /* call inclusion method of primal heuristic */
437
438 return SCIP_OKAY;
439}
440
441/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
442static
443SCIP_DECL_HEURFREE(heurFreeRounding) /*lint --e{715}*/
444{ /*lint --e{715}*/
446
447 assert(heur != NULL);
448 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
450
451 /* free heuristic data */
456
457 return SCIP_OKAY;
458}
459
460/** initialization method of primal heuristic (called after problem was transformed) */
461static
462SCIP_DECL_HEURINIT(heurInitRounding) /*lint --e{715}*/
463{ /*lint --e{715}*/
465
466 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
467
469 assert(heurdata != NULL);
470
471 /* create heuristic data */
473 heurdata->lastlp = -1;
474
475 return SCIP_OKAY;
476}
477
478/** deinitialization method of primal heuristic (called before transformed problem is freed) */
479static
480SCIP_DECL_HEUREXIT(heurExitRounding) /*lint --e{715}*/
481{ /*lint --e{715}*/
483
484 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
485
486 /* free heuristic data */
488 assert(heurdata != NULL);
490
491 return SCIP_OKAY;
492}
493
494/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
495static
496SCIP_DECL_HEURINITSOL(heurInitsolRounding)
497{
499
500 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
501
503 assert(heurdata != NULL);
504 heurdata->lastlp = -1;
505
506 /* change the heuristic's timingmask, if nit should be called only once per node */
507 if( heurdata->oncepernode )
509
510 return SCIP_OKAY;
511}
512
513/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
514static
515SCIP_DECL_HEUREXITSOL(heurExitsolRounding)
516{
517 /* reset the timing mask to its default value */
519
520 return SCIP_OKAY;
521}
522
523
524/** execution method of primal heuristic */
525static
526SCIP_DECL_HEUREXEC(heurExecRounding) /*lint --e{715}*/
527{ /*lint --e{715}*/
539 int nfrac;
543 int c;
544 int r;
549
550 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
551 assert(scip != NULL);
554
556
557 /* only call heuristic, if an optimal LP solution is at hand */
559 return SCIP_OKAY;
560
561 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
563 return SCIP_OKAY;
564
565 /* get heuristic data */
567 assert(heurdata != NULL);
568
569 /* don't call heuristic, if we have already processed the current LP solution */
571 if( nlps == heurdata->lastlp )
572 return SCIP_OKAY;
573 heurdata->lastlp = nlps;
574
575 /* don't call heuristic, if it was not successful enough in the past */
579 if( nnodes % ((ncalls/heurdata->successfactor)/(nsolsfound+1)+1) != 0 )
580 return SCIP_OKAY;
581
582 /* get fractional variables, that should be integral */
584
585 /* only call heuristic, if LP solution is fractional */
586 if( nlpcands == 0 )
587 return SCIP_OKAY;
588
590
591 /* get LP rows */
593
594 SCIPdebugMsg(scip, "executing rounding heuristic: %d LP rows, %d LP candidates\n", nlprows, nlpcands);
595
596 /* get memory for activities, violated rows, and row violation positions */
597 nfrac = nlpcands;
601
602 /* get the activities for all globally valid rows;
603 * the rows should be feasible, but due to numerical inaccuracies in the LP solver, they can be violated
604 */
605 nviolrows = 0;
606 for( r = 0; r < nlprows; ++r )
607 {
608 SCIP_ROW* row;
609
610 row = lprows[r];
611 assert(SCIProwGetLPPos(row) == r);
612
613 if( !SCIProwIsLocal(row) )
614 {
618 {
619 violrows[nviolrows] = row;
621 nviolrows++;
622 }
623 else
624 violrowpos[r] = -1;
625 }
626 }
627
628 /* get the working solution from heuristic's local data */
629 sol = heurdata->sol;
631
632 /* copy the current LP solution to the working solution */
634
635 /* calculate the minimal objective value possible after rounding fractional variables */
638 for( c = 0; c < nlpcands; ++c )
639 {
643 }
644
645 /* try to round remaining variables in order to become/stay feasible */
646 while( nfrac > 0 )
647 {
648 SCIP_VAR* roundvar;
649 SCIP_Real oldsolval;
650 SCIP_Real newsolval;
651
652 SCIPdebugMsg(scip, "rounding heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
654
655 /* minobj < SCIPgetCutoffbound(scip) should be true, otherwise the rounding variable selection
656 * should have returned NULL. Due to possible cancellation we use SCIPisLE. */
658
659 /* choose next variable to process:
660 * - if a violated row exists, round a variable decreasing the violation, that has least impact on other rows
661 * - otherwise, round a variable, that has strongest devastating impact on rows in opposite direction
662 */
663 if( nviolrows > 0 )
664 {
665 SCIP_ROW* row;
666 int rowpos;
667
668 row = violrows[nviolrows-1];
669 rowpos = SCIProwGetLPPos(row);
670 assert(0 <= rowpos && rowpos < nlprows);
671 assert(violrowpos[rowpos] == nviolrows-1);
672
673 SCIPdebugMsg(scip, "rounding heuristic: try to fix violated row <%s>: %g <= %g <= %g\n",
674 SCIProwGetName(row), SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row));
675 if( SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row)) )
676 {
677 /* lhs is violated: select a variable rounding, that increases the activity */
678 SCIP_CALL( selectIncreaseRounding(scip, sol, minobj, row, &roundvar, &oldsolval, &newsolval) );
679 }
680 else
681 {
683 /* rhs is violated: select a variable rounding, that decreases the activity */
684 SCIP_CALL( selectDecreaseRounding(scip, sol, minobj, row, &roundvar, &oldsolval, &newsolval) );
685 }
686 }
687 else
688 {
689 SCIPdebugMsg(scip, "rounding heuristic: search rounding variable and try to stay feasible\n");
690 SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &roundvar, &oldsolval, &newsolval) );
691 }
692
693 /* check, whether rounding was possible */
694 if( roundvar == NULL )
695 {
696 SCIPdebugMsg(scip, "rounding heuristic: -> didn't find a rounding variable\n");
697 break;
698 }
699
700 SCIPdebugMsg(scip, "rounding heuristic: -> round var <%s>, oldval=%g, newval=%g, obj=%g\n",
701 SCIPvarGetName(roundvar), oldsolval, newsolval, SCIPvarGetObj(roundvar));
702
703 /* update row activities of globally valid rows */
705 roundvar, oldsolval, newsolval) );
706
707 /* store new solution value and decrease fractionality counter */
708 SCIP_CALL( SCIPsetSolVal(scip, sol, roundvar, newsolval) );
709 nfrac--;
710
711 /* update minimal objective value possible after rounding remaining variables */
712 obj = SCIPvarGetObj(roundvar);
713 if( obj > 0.0 && newsolval > oldsolval )
714 minobj += obj;
715 else if( obj < 0.0 && newsolval < oldsolval )
716 minobj -= obj;
717
718 SCIPdebugMsg(scip, "rounding heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
720 }
721
722 /* check, if the new solution is feasible */
723 if( nfrac == 0 && nviolrows == 0 )
724 {
725 SCIP_Bool stored;
726
727 /* check solution for feasibility, and add it to solution store if possible
728 * neither integrality nor feasibility of LP rows has to be checked, because this is already
729 * done in the rounding heuristic itself; however, be better check feasibility of LP rows,
730 * because of numerical problems with activity updating
731 */
733
734 if( stored )
735 {
736#ifdef SCIP_DEBUG
737 SCIPdebugMsg(scip, "found feasible rounded solution:\n");
739#endif
741 }
742 }
743
744 /* free memory buffers */
748
749 return SCIP_OKAY;
750}
751
752
753/*
754 * heuristic specific interface methods
755 */
756
757/** creates the rounding heuristic with infeasibility recovering and includes it in SCIP */
759 SCIP* scip /**< SCIP data structure */
760 )
761{
763 SCIP_HEUR* heur;
764
765 /* create Rounding primal heuristic data */
767
768 /* include primal heuristic */
771 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRounding, heurdata) );
772
773 assert(heur != NULL);
774
775 /* primal heuristic is safe to use in exact solving mode */
776 SCIPheurMarkExact(heur);
777
778 /* set non-NULL pointers to callback methods */
779 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRounding) );
780 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRounding) );
781 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRounding) );
782 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitRounding) );
783 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolRounding) );
784 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolRounding) );
785
786 /* add rounding primal heuristic parameters */
787 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/successfactor",
788 "number of calls per found solution that are considered as standard success, a higher factor causes the heuristic to be called more often",
789 &heurdata->successfactor, TRUE, DEFAULT_SUCCESSFACTOR, -1, INT_MAX, NULL, NULL) );
790
791 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/oncepernode",
792 "should the heuristic only be called once per node?",
793 &heurdata->oncepernode, TRUE, DEFAULT_ONCEPERNODE, NULL, NULL) );
794
795 return SCIP_OKAY;
796}
#define NULL
Definition def.h:255
#define SCIP_Longint
Definition def.h:148
#define SCIP_Bool
Definition def.h:98
#define SCIP_Real
Definition def.h:163
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define SCIP_CALL(x)
Definition def.h:362
#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:2353
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:4019
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:2136
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:23683
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
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23267
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4328
#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
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