SCIP Doxygen Documentation
Loading...
Searching...
No Matches
heur_fixandinfer.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_fixandinfer.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief fix-and-infer primal heuristic
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/pub_heur.h"
35#include "scip/pub_message.h"
36#include "scip/pub_var.h"
37#include "scip/scip_branch.h"
38#include "scip/scip_general.h"
39#include "scip/scip_heur.h"
40#include "scip/scip_mem.h"
41#include "scip/scip_message.h"
42#include "scip/scip_numerics.h"
43#include "scip/scip_param.h"
44#include "scip/scip_prob.h"
45#include "scip/scip_probing.h"
46#include "scip/scip_sol.h"
47#include "scip/scip_tree.h"
48#include "scip/scip_var.h"
49
50
51#define HEUR_NAME "fixandinfer"
52#define HEUR_DESC "iteratively fixes variables and propagates inferences"
53#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
54#define HEUR_PRIORITY -500000
55#define HEUR_FREQ -1 /* at the moment, the heuristic seems to be useless */
56#define HEUR_FREQOFS 0
57#define HEUR_MAXDEPTH -1
58#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
59#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
60
61#define MAXDIVEDEPTH 100
62
63
64/*
65 * Default parameter settings
66 */
67
68#define DEFAULT_PROPROUNDS 0 /**< maximal number of propagation rounds in probing subproblems */
69#define DEFAULT_MINFIXINGS 100 /**< minimal number of fixings to apply before dive may be aborted */
70
71
72/*
73 * Data structures
74 */
75
76/** primal heuristic data */
77struct SCIP_HeurData
78{
79 int proprounds; /**< maximal number of propagation rounds in probing subproblems */
80 int minfixings; /**< minimal number of fixings to apply before dive may be aborted */
81};
82
83
84/*
85 * Local methods
86 */
87
88/** selects a variable and fixes it to its current pseudo solution value */
89static
91 SCIP* scip, /**< SCIP data structure */
92 SCIP_VAR** pseudocands, /**< array of unfixed variables */
93 int npseudocands, /**< number of unfixed variables */
94 SCIP_Real large /**< large value to be used instead of infinity */
95 )
96{
98 SCIP_Real bestscore;
99 SCIP_Real score;
100 SCIP_Real solval;
101 int bestcand;
102 int ncands;
103 int c;
104
106 assert(npseudocands > 0);
107
108 /* if existing, choose one of the highest priority binary variables; if no high priority binary variables
109 * exist, choose a variable among all unfixed integral variables
110 */
112 if( ncands == 0 )
113 ncands = npseudocands;
114
115 /* select variable to tighten the domain for */
116 bestscore = -SCIPinfinity(scip);
117 bestcand = -1;
118 for( c = 0; c < ncands; ++c )
119 {
121 if( score > bestscore )
122 {
123 bestscore = score;
124 bestcand = c;
125 }
126 }
127 assert(bestcand != -1);
128
129 /* fix variable to its current pseudo solution value */
131 solval = SCIPgetVarSol(scip, var);
132
133 /* adapt solution value if it is infinite */
134 if( SCIPisInfinity(scip, solval) )
135 {
136 SCIP_Real lb;
139
140 /* adapt fixing value by changing it to a large value */
141 if( SCIPisInfinity(scip, -lb) )
142 solval = SCIPceil(scip, large);
143 else if( !SCIPisInfinity(scip, SCIPceil(scip, lb+large)) )
144 solval = SCIPceil(scip, lb+large);
145 }
146 else if( SCIPisInfinity(scip, -solval) )
147 {
148 SCIP_Real ub;
151
152 /* adapt fixing value by changing it to a large negative value */
153 if( SCIPisInfinity(scip, ub) )
154 solval = SCIPfloor(scip, -large);
155 else if( !SCIPisInfinity(scip, -SCIPfloor(scip, ub-large)) )
156 solval = SCIPfloor(scip, ub-large);
157 }
158
159 assert(SCIPisFeasIntegral(scip, solval)); /* in probing, we always have the pseudo solution */
160 SCIPdebugMsg(scip, " -> fixed variable <%s>[%g,%g] = %g (%d candidates left)\n",
161 SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), solval, npseudocands - 1);
162 SCIP_CALL( SCIPfixVarProbing(scip, var, solval) );
163
164 return SCIP_OKAY;
165}
166
167
168/*
169 * Callback methods of primal heuristic
170 */
171
172/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
173static
174SCIP_DECL_HEURCOPY(heurCopyFixandinfer)
175{ /*lint --e{715}*/
176 assert(scip != NULL);
177 assert(heur != NULL);
178
180
181 /* call inclusion method of primal heuristic */
183
184 return SCIP_OKAY;
185}
186
187/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
188static
189SCIP_DECL_HEURFREE(heurFreeFixandinfer) /*lint --e{715}*/
190{ /*lint --e{715}*/
192
193 /* free heuristic data */
198
199 return SCIP_OKAY;
200}
201
202
203/** execution method of primal heuristic */
204static
205SCIP_DECL_HEUREXEC(heurExecFixandinfer)
206{ /*lint --e{715}*/
208 SCIP_VAR** cands;
209 int ncands;
210 int startncands;
211 int divedepth;
213 SCIP_Real large;
214
216
217 /* do not call heuristic of node was already detected to be infeasible */
218 if( nodeinfeasible )
219 return SCIP_OKAY;
220
221 /* we cannot run on problems with continuous variables */
222 if( SCIPgetNContVars(scip) > 0 )
223 return SCIP_OKAY;
224
225 /* get unfixed variables */
226 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, &ncands, NULL) );
227 if( ncands == 0 )
228 return SCIP_OKAY;
229
230 /* get heuristic data */
232 assert(heurdata != NULL);
233
234 /* fix variables and propagate inferences as long as the problem is still feasible and there are
235 * unfixed integral variables
236 */
237 cutoff = FALSE;
238 divedepth = 0;
239 startncands = ncands;
240
241 /* start probing */
243
245 {
247 return SCIP_OKAY;
248 }
249
250 SCIPdebugMsg(scip, "starting fix-and-infer heuristic with %d unfixed integral variables\n", ncands);
251
253
254 /* create next probing node */
256
257 /* determine large value to set variables to */
258 large = SCIPinfinity(scip);
259 if( !SCIPisInfinity(scip, 0.1 / SCIPfeastol(scip)) )
260 large = 0.1 / SCIPfeastol(scip);
261
262 while( !cutoff && ncands > 0
263 && (divedepth < heurdata->minfixings || (startncands - ncands) * 2 * MAXDIVEDEPTH >= startncands * divedepth)
264 && !SCIPisStopped(scip) )
265 {
266 divedepth++;
267
268 /* fix next variable */
269 SCIP_CALL( fixVariable(scip, cands, ncands, large) );
270
271 /* propagate the fixing */
273
274 /* get remaining unfixed variables */
275 if( !cutoff )
276 {
277 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, &ncands, NULL) );
278 }
279 }
280
281 /* check, if we are still feasible */
282 if( cutoff )
283 {
284 SCIPdebugMsg(scip, "propagation detected a cutoff\n");
285 }
286 else if( ncands == 0 )
287 {
288 SCIP_Bool success;
289
290 success = FALSE;
291
292 /* try to add solution to SCIP */
293 SCIP_CALL( SCIPtryCurrentSol(scip, heur, FALSE, FALSE, FALSE, TRUE, &success) );
294
295 if( success )
296 {
297 SCIPdebugMsg(scip, "found primal feasible solution\n");
299 }
300 else
301 {
302 SCIPdebugMsg(scip, "primal solution was rejected\n");
303 }
304 }
305 else
306 {
307 SCIPdebugMsg(scip, "probing was aborted (probing depth: %d, fixed: %d/%d)", divedepth, startncands - ncands, startncands);
308 }
309
310 /* end probing */
312
313 return SCIP_OKAY;
314}
315
316
317/*
318 * primal heuristic specific interface methods
319 */
320
321/** creates the fix-and-infer primal heuristic and includes it in SCIP */
323 SCIP* scip /**< SCIP data structure */
324 )
325{
327 SCIP_HEUR* heur;
328
329 /* create Fixandinfer primal heuristic data */
331
332 /* include primal heuristic */
335 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecFixandinfer, heurdata) );
336
337 assert(heur != NULL);
338
339 /* primal heuristic is safe to use in exact solving mode */
340 SCIPheurMarkExact(heur);
341
342 /* set non-NULL pointers to callback methods */
343 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyFixandinfer) );
344 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeFixandinfer) );
345
346 /* fixandinfer heuristic parameters */
348 "heuristics/fixandinfer/proprounds",
349 "maximal number of propagation rounds in probing subproblems (-1: no limit, 0: auto)",
350 &heurdata->proprounds, TRUE, DEFAULT_PROPROUNDS, -1, INT_MAX, NULL, NULL) );
352 "heuristics/fixandinfer/minfixings",
353 "minimal number of fixings to apply before dive may be aborted",
354 &heurdata->minfixings, TRUE, DEFAULT_MINFIXINGS, 0, INT_MAX, NULL, NULL) );
355
356 return SCIP_OKAY;
357}
#define NULL
Definition def.h:257
#define SCIP_MAXTREEDEPTH
Definition def.h:306
#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
SCIP_Bool SCIPisStopped(SCIP *scip)
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2569
#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 SCIPincludeHeurFixandinfer(SCIP *scip)
int SCIPgetNPrioPseudoBranchBins(SCIP *scip)
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
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
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
SCIP_RETCODE SCIPtryCurrentSol(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition scip_sol.c:4212
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Real SCIPgetVarAvgInferenceScore(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:11945
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:3051
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
#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
SCIPheurSetData(heur, NULL)
#define DEFAULT_PROPROUNDS
#define DEFAULT_MINFIXINGS
#define MAXDIVEDEPTH
static SCIP_RETCODE fixVariable(SCIP *scip, SCIP_VAR **pseudocands, int npseudocands, SCIP_Real large)
fix-and-infer primal heuristic
int divedepth
SCIP_VAR ** pseudocands
int c
SCIPendProbing(scip))
SCIP_Bool cutoff
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_VAR * var
int bestcand
public methods for primal heuristics
public methods for message output
public methods for problem variables
public methods for branching rule plugins and branching
general public methods
public methods for primal heuristic plugins and divesets
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for the branch-and-bound tree
public methods for SCIP variables
#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
@ 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_Var SCIP_VAR
Definition type_var.h:166