SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_bound.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_bound.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief heuristic which fixes all integer variables to a bound (lower/upper) and solves the remaining LP
28 * @author Gerald Gamrath
29 *
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
34#include "scip/heur_bound.h"
35#include "scip/pub_heur.h"
36#include "scip/pub_message.h"
37#include "scip/pub_tree.h"
38#include "scip/pub_var.h"
39#include "scip/scip_branch.h"
41#include "scip/scip_exact.h"
42#include "scip/scip_general.h"
43#include "scip/scip_heur.h"
44#include "scip/scip_lp.h"
45#include "scip/scip_mem.h"
46#include "scip/scip_message.h"
47#include "scip/scip_numerics.h"
48#include "scip/scip_param.h"
49#include "scip/scip_prob.h"
50#include "scip/scip_probing.h"
51#include "scip/scip_sol.h"
53#include "scip/scip_timing.h"
54#include "scip/scip_tree.h"
55#include <string.h>
56
57#ifdef SCIP_STATISTIC
58#include "scip/clock.h"
59#endif
60
61#define HEUR_NAME "bound"
62#define HEUR_DESC "heuristic which fixes all integer variables to a bound and solves the remaining LP"
63#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
64#define HEUR_PRIORITY -1107000
65#define HEUR_FREQ -1
66#define HEUR_FREQOFS 0
67#define HEUR_MAXDEPTH -1
68#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
69#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
70
71#define DEFAULT_ONLYWITHOUTSOL TRUE /**< Should heuristic only be executed if no primal solution was found, yet? */
72#define DEFAULT_MAXPROPROUNDS 0 /* maximum number of propagation rounds during probing */
73#define DEFAULT_BOUND 'l' /**< to which bound should integer variables be fixed? */
74
75
76/*
77 * Data structures
78 */
79
80/** primal heuristic data */
81struct SCIP_HeurData
82{
83 SCIP_Bool onlywithoutsol; /**< Should heuristic only be executed if no primal solution was found, yet? */
84 int maxproprounds; /**< maximum number of propagation rounds during probing */
85 char bound; /**< to which bound should integer variables be fixed? */
86};
87
88/*
89 * Local methods
90 */
91
92/** main procedure of the bound heuristic */
93static
95 SCIP* scip, /**< original SCIP data structure */
96 SCIP_HEUR* heur, /**< heuristic */
97 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
98 SCIP_Bool lower, /**< should integer variables be fixed to their lower bound? */
99 SCIP_RESULT* result /**< pointer to store the result */
100 )
101{
103 SCIP_VAR* var;
104 SCIP_Bool infeasible = FALSE;
106 int maxproprounds;
107 int v;
108
109 assert(nvars >= 0);
110
111 maxproprounds = heurdata->maxproprounds;
112 if( maxproprounds == -2 )
113 maxproprounds = 0;
114
115 /* stop if we would have infinite fixings */
116 if( lower )
117 {
118 for( v = 0; v < nvars; ++v )
119 {
121 return SCIP_OKAY;
122 }
123 }
124 else
125 {
126 for( v = 0; v < nvars; ++v )
127 {
129 return SCIP_OKAY;
130 }
131 }
132
133 /* start probing */
135
136 for( v = 0; v < nvars; ++v )
137 {
138 var = vars[v];
140
141 /* skip variables which are already fixed */
143 continue;
144
145 /* fix variable to lower bound */
146 if( lower )
147 {
149 SCIPdebugMsg(scip, "fixing %d: variable <%s> to lower bound <%g> (%d pseudo cands)\n",
151 }
152 /* fix variable to upper bound */
153 else
154 {
156 SCIPdebugMsg(scip, "fixing %d: variable <%s> to upper bound <%g> (%d pseudo cands)\n",
158 }
159
160 /* propagate fixings */
161 if( heurdata->maxproprounds != 0 )
162 {
163 SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, &infeasible, NULL) );
164 }
165
166 /* todo: try to backtrack */
167 /* stop if infeasible */
168 if( infeasible )
169 break;
170 }
171
172 SCIPdebugMsg(scip, "probing ended with %sfeasible problem\n", infeasible ? "in" : "");
173
174 /*************************** Probing LP Solving ***************************/
175
176 /* solve lp only if the problem is still feasible */
177 if( !infeasible )
178 {
179 char strbuf[SCIP_MAXSTRLEN];
180 SCIP_LPSOLSTAT lpstatus;
182 int ncols;
183
184 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
185 * which the user sees no output; more detailed probing stats only in debug mode */
186 ncols = SCIPgetNLPCols(scip);
187 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
188 {
189 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
190
191 if( nunfixedcols > 0.5 * ncols )
192 {
194 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
195 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
196 }
197 }
198 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
200
201 /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
202 * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
203 * SCIP will stop.
204 */
205 SCIPdebugMsg(scip, "starting solving bound-heur LP at time %g, LP iterations: %" SCIP_LONGINT_FORMAT "\n",
207#ifdef NDEBUG
208 {
209 SCIP_Bool retstat;
210 retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
211 if( retstat != SCIP_OKAY )
212 {
213 SCIPwarningMessage(scip, "Error while solving LP in bound heuristic; LP solve terminated with code <%d>\n",
214 retstat);
215 }
216 }
217#else
219#endif
220 SCIPdebugMsg(scip, "ending solving bound-heur LP at time %g\n", SCIPgetSolvingTime(scip));
221
222 lpstatus = SCIPgetLPSolstat(scip);
223
224 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
225 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, lpstatus);
226
227 /* check if this is a feasible solution */
228 if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
229 {
230 SCIP_SOL* newsol;
231 SCIP_Bool stored;
232 SCIP_Bool success;
233
234 /* create temporary solution */
235 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
236
237 /* copy the current LP solution to the working solution */
238 SCIP_CALL( SCIPlinkLPSol(scip, newsol) );
239
240 SCIP_CALL( SCIProundSol(scip, newsol, &success) );
241
242 if( success )
243 {
244 SCIPdebugMsg(scip, "bound heuristic found roundable primal solution: obj=%g\n",
245 SCIPgetSolOrigObj(scip, newsol));
246
247 /* check solution for feasibility, and add it to solution store if possible.
248 * Neither integrality nor feasibility of LP rows have to be checked, because they
249 * are guaranteed by the heuristic at this stage.
250 */
251#ifdef SCIP_DEBUG
252 SCIP_CALL( SCIPtrySol(scip, newsol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
253#else
254 SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, FALSE, FALSE, &stored) );
255#endif
256
257 if( stored )
258 {
259 SCIPdebugMsg(scip, "found feasible solution:\n");
261 }
262 }
263
264 /* free solution */
265 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
266 }
267 }
268
269 /* exit probing mode */
271
272 return SCIP_OKAY;
273}
274
275
276/*
277 * Callback methods of primal heuristic
278 */
279
280/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
281static
282SCIP_DECL_HEURCOPY(heurCopyBound)
283{ /*lint --e{715}*/
284 assert(scip != NULL);
285 assert(heur != NULL);
286 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
287
288 /* call inclusion method of heuristic */
290
291 return SCIP_OKAY;
292}
293
294/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
295static
296SCIP_DECL_HEURFREE(heurFreeBound)
297{ /*lint --e{715}*/
299
300 /* free heuristic data */
302
304 SCIPheurSetData(heur, NULL);
305
306 return SCIP_OKAY;
307}
308
309/** execution method of primal heuristic */
310static
311SCIP_DECL_HEUREXEC(heurExecBound)
312{ /*lint --e{715}*/
314
315 assert(heur != NULL);
316 assert(scip != NULL);
317 assert(result != NULL);
318
320
322 return SCIP_OKAY;
323
325 return SCIP_OKAY;
326
328 assert(heurdata != NULL);
329
331
332 if( SCIPisStopped(scip) )
333 return SCIP_OKAY;
334
335 /* stop execution method if there is already a primal feasible solution at hand */
336 if( SCIPgetBestSol(scip) != NULL && heurdata->onlywithoutsol )
337 return SCIP_OKAY;
338
339 SCIPdebugMsg(scip, "apply bound heuristic at node %lld\n",
341
343 {
345
347
348 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
349 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
350 * give a certificate for the cutoff
351 */
352 if( cutoff && !SCIPisCertified(scip) )
353 {
355 return SCIP_OKAY;
356 }
357
359 }
360
361 if( heurdata->bound == 'l' || heurdata->bound == 'b' )
362 {
364 }
365 if( heurdata->bound == 'u' || heurdata->bound == 'b' )
366 {
368 }
369
370 return SCIP_OKAY;
371}
372
373/*
374 * primal heuristic specific interface methods
375 */
376
377/** creates the bound primal heuristic and includes it in SCIP */
379 SCIP* scip /**< SCIP data structure */
380 )
381{
383 SCIP_HEUR* heur;
384
385 /* create bound primal heuristic data */
387
388 /* include primal heuristic */
392
393 assert(heur != NULL);
394
395 /* primal heuristic is safe to use in exact solving mode */
396 SCIPheurMarkExact(heur);
397
398 /* set non-NULL pointers to callback methods */
399 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyBound) );
400 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeBound) );
401
402 /* add bound heuristic parameters */
403
404 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/onlywithoutsol",
405 "Should heuristic only be executed if no primal solution was found, yet?",
406 &heurdata->onlywithoutsol, TRUE, DEFAULT_ONLYWITHOUTSOL, NULL, NULL) );
407
408 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
409 "maximum number of propagation rounds during probing (-1 infinity, -2 parameter settings)",
410 &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
411
412 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/bound",
413 "to which bound should integer variables be fixed? ('l'ower, 'u'pper, or 'b'oth)",
414 &heurdata->bound, FALSE, DEFAULT_BOUND, "lub", NULL, NULL) );
415
416 return SCIP_OKAY;
417}
static long bound
#define DEFAULT_MAXPROPROUNDS
internal methods for clocks and timing issues
#define NULL
Definition def.h:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#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_LONGINT_FORMAT
Definition def.h:155
#define SCIP_CALL(x)
Definition def.h:362
SCIP_Bool SCIPisStopped(SCIP *scip)
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
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:167
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 SCIPincludeHeurBound(SCIP *scip)
Definition heur_bound.c:378
int SCIPgetNPseudoBranchCands(SCIP *scip)
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition scip_heur.c:122
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition heur.c:1457
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition heur.c:1378
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition scip_lp.c:154
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition scip_lp.c:130
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition scip_lp.c:105
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
int SCIPgetNUnfixedLPCols(SCIP *scip)
Definition scip_lp.c:554
int SCIPgetNLPCols(SCIP *scip)
Definition scip_lp.c:533
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition scip_lp.c:673
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition tree.c:8513
char * SCIPsnprintfProbingStats(SCIP *scip, char *strbuf, int len)
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2988
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition scip_sol.c:3130
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_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition scip_tree.c:436
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition scip_tree.c:91
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24268
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23453
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23267
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24234
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
SCIPfreeSol(scip, &heurdata->sol))
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIPcreateSol(scip, &heurdata->sol, heur))
#define DEFAULT_ONLYWITHOUTSOL
Definition heur_bound.c:71
static SCIP_RETCODE applyBoundHeur(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_Bool lower, SCIP_RESULT *result)
Definition heur_bound.c:94
#define DEFAULT_BOUND
Definition heur_bound.c:73
heuristic which fixes all integer variables to a bound (lower/upper) and solves the remaining LP
SCIP_Bool lperror
SCIPendProbing(scip))
SCIP_Bool cutoff
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIPlinkLPSol(scip, sol))
SCIP_VAR * var
static SCIP_VAR ** vars
public methods for primal heuristics
public methods for message output
public methods for branch and bound tree
public methods for problem variables
public methods for branching rule plugins and branching
public methods for certified solving
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 SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for timing
public methods for the branch-and-bound tree
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition type_lp.h:52
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
@ SCIP_VERBLEVEL_FULL
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_FOUNDSOL
Definition type_result.h:56
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71