Scippy

SCIP

Solving Constraint Integer Programs

heur_nlpdiving.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_nlpdiving.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief NLP diving heuristic that chooses fixings w.r.t. the fractionalities
28 * @author Timo Berthold
29 * @author Stefan Vigerske
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
35#include "scip/heur_nlpdiving.h"
36#include "scip/heur_subnlp.h"
38#include "scip/pub_event.h"
39#include "scip/pub_heur.h"
40#include "scip/pub_message.h"
41#include "scip/pub_misc.h"
42#include "scip/pub_sol.h"
43#include "scip/pub_var.h"
44#include "scip/scip_branch.h"
45#include "scip/scip_copy.h"
46#include "scip/scip_event.h"
47#include "scip/scip_general.h"
48#include "scip/scip_heur.h"
49#include "scip/scip_lp.h"
50#include "scip/scip_mem.h"
51#include "scip/scip_message.h"
52#include "scip/scip_nlp.h"
53#include "scip/scip_nlpi.h"
54#include "scip/scip_nodesel.h"
55#include "scip/scip_numerics.h"
56#include "scip/scip_param.h"
57#include "scip/scip_prob.h"
58#include "scip/scip_probing.h"
60#include "scip/scip_sol.h"
61#include "scip/scip_solve.h"
63#include "scip/scip_timing.h"
64#include "scip/scip_tree.h"
65#include "scip/scip_var.h"
66#include <string.h>
67
68#define HEUR_NAME "nlpdiving"
69#define HEUR_DESC "NLP diving heuristic that chooses fixings w.r.t. the fractionalities"
70#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
71#define HEUR_PRIORITY -1003010
72#define HEUR_FREQ 10
73#define HEUR_FREQOFS 3
74#define HEUR_MAXDEPTH -1
75#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
76#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
77
78/* event handler properties */
79#define EVENTHDLR_NAME "Nlpdiving"
80#define EVENTHDLR_DESC "bound change event handler for " HEUR_NAME " heuristic"
81
82
83/*
84 * Default parameter settings
85 */
86
87#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
88#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
89#define DEFAULT_MAXNLPITERABS 200 /**< minimial absolute number of allowed NLP iterations */
90#define DEFAULT_MAXNLPITERREL 10 /**< additional allowed number of NLP iterations relative to successfully found solutions */
91#define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
92 * where diving is performed (0.0: no limit) */
93#define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
94 * where diving is performed (0.0: no limit) */
95#define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
96#define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
97#define DEFAULT_MINSUCCQUOT 0.1 /**< heuristic will not run if less then this percentage of calls succeeded (0.0: no limit) */
98#define DEFAULT_MAXFEASNLPS 10 /**< maximal number of NLPs with feasible solution to solve during one dive */
99#define DEFAULT_FIXQUOT 0.2 /**< percentage of fractional variables that should be fixed before the next NLP solve */
100#define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
101#define DEFAULT_LP FALSE /**< should the LP relaxation be solved before the NLP relaxation? */
102#define DEFAULT_PREFERLPFRACS FALSE /**< prefer variables that are also fractional in LP solution? */
103#define DEFAULT_PREFERCOVER TRUE /**< should variables in a minimal cover be preferred? */
104#define DEFAULT_SOLVESUBMIP FALSE /**< should a sub-MIP be solved if all cover variables are fixed? */
105#define DEFAULT_NLPSTART 's' /**< which point should be used as starting point for the NLP solver? */
106#define DEFAULT_VARSELRULE 'd' /**< which variable selection should be used? ('f'ractionality, 'c'oefficient,
107 * 'p'seudocost, 'g'uided, 'd'ouble)
108 */
109#define DEFAULT_NLPFASTFAIL TRUE /**< should the NLP solver stop early if it converges slow? */
110#define DEFAULT_RANDSEED 97 /**< initial random seed */
111
112#define MINNLPITER 10 /**< minimal number of NLP iterations allowed in each NLP solving call */
113
114/* locally defined heuristic data */
115struct SCIP_HeurData
116{
117 SCIP_SOL* sol; /**< working solution */
118 SCIP_Real minreldepth; /**< minimal relative depth to start diving */
119 SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
120 int maxnlpiterabs; /**< minimial absolute number of allowed NLP iterations */
121 int maxnlpiterrel; /**< additional allowed number of NLP iterations relative to successfully found solutions */
122 SCIP_Real maxdiveubquot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
123 * where diving is performed (0.0: no limit) */
124 SCIP_Real maxdiveavgquot; /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
125 * where diving is performed (0.0: no limit) */
126 SCIP_Real maxdiveubquotnosol; /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
127 SCIP_Real maxdiveavgquotnosol;/**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
128 int maxfeasnlps; /**< maximal number of NLPs with feasible solution to solve during one dive */
129 SCIP_Real minsuccquot; /**< heuristic will not run if less then this percentage of calls succeeded (0.0: no limit) */
130 SCIP_Real fixquot; /**< percentage of fractional variables that should be fixed before the next NLP solve */
131 SCIP_Bool backtrack; /**< use one level of backtracking if infeasibility is encountered? */
132 SCIP_Bool lp; /**< should the LP relaxation be solved before the NLP relaxation? */
133 SCIP_Bool preferlpfracs; /**< prefer variables that are also fractional in LP solution? */
134 SCIP_Bool prefercover; /**< should variables in a minimal cover be preferred? */
135 SCIP_Bool solvesubmip; /**< should a sub-MIP be solved if all cover variables are fixed? */
136 SCIP_Bool nlpfastfail; /**< should the NLP solver stop early if it converges slow? */
137 char nlpstart; /**< which point should be used as starting point for the NLP solver? */
138 char varselrule; /**< which variable selection should be used? ('f'ractionality, 'c'oefficient,
139 * 'p'seudocost, 'g'uided, 'd'ouble)
140 */
141
142 int nnlpiterations; /**< NLP iterations used in this heuristic */
143 int nsuccess; /**< number of runs that produced at least one feasible solution */
144 int nfixedcovervars; /**< number of variables in the cover that are already fixed */
145#ifdef SCIP_STATISTIC
146 int nnlpsolves; /**< number of NLP solves */
147 int nfailcutoff; /**< number of fails due to cutoff */
148 int nfaildepth; /**< number of fails due to too deep */
149 int nfailnlperror; /**< number of fails due to NLP error */
150#endif
151 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
152 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
153 SCIP_HEURTIMING inittiming; /**< initial heuristic timing */
154};
155
156
157/*
158 * local methods
159 */
160
161/** gets fractional variables of last NLP solution along with solution values and fractionalities
162 *
163 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
164 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
165 *
166 * @pre This method can be called if SCIP is in one of the following stages:
167 * - \ref SCIP_STAGE_INITSOLVE
168 * - \ref SCIP_STAGE_SOLVING
169 */
170static
172 SCIP* scip, /**< SCIP data structure */
173 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
174 SCIP_VAR*** nlpcands, /**< pointer to store the array of NLP fractional variables, or NULL */
175 SCIP_Real** nlpcandssol, /**< pointer to store the array of NLP fractional variables solution values, or NULL */
176 SCIP_Real** nlpcandsfrac, /**< pointer to store the array of NLP fractional variables fractionalities, or NULL */
177 int* nnlpcands /**< pointer to store the number of NLP fractional variables , or NULL */
178 )
179{
180 int c;
181
182 assert(scip != NULL);
183 assert(heurdata != NULL);
184 assert(nlpcands != NULL);
185 assert(nlpcandssol != NULL);
186 assert(nlpcandsfrac != NULL);
187 assert(nnlpcands != NULL);
188
189 /* get fractional variables that should be integral */
190 SCIP_CALL( SCIPgetNLPFracVars(scip, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, NULL) );
191
192 /* values may be outside the domain in exact arithmetic, but inside the domain within relative tolerance, and still
193 * slightly fractional, because SCIPisFeasIntegral() uses absolute tolerance; project value onto domain to avoid this
194 * (example: primsol=29.99999853455704, lower bound = 30)
195 */
196 for( c = 0; c < *nnlpcands; ++c )
197 {
198 assert(!SCIPisFeasIntegral(scip, (*nlpcandssol)[c]));
199
200 if( (*nlpcandssol)[c] < SCIPvarGetLbLocal((*nlpcands)[c]) || (*nlpcandssol)[c] > SCIPvarGetUbLocal((*nlpcands)[c]) )
201 {
202 SCIP_Real newval;
203
204 newval = ((*nlpcandssol)[c] < SCIPvarGetLbLocal((*nlpcands)[c]))
205 ? SCIPvarGetLbLocal((*nlpcands)[c]) - 0.5*SCIPfeastol(scip)
206 : SCIPvarGetUbLocal((*nlpcands)[c]) + 0.5*SCIPfeastol(scip);
207
208 assert(SCIPisFeasIntegral(scip, newval));
209
210 SCIP_CALL( SCIPsetSolVal(scip, heurdata->sol, (*nlpcands)[c], newval) );
211
212 (*nnlpcands)--;
213
214 if( c < *nnlpcands )
215 {
216 (*nlpcands)[c] = (*nlpcands)[*nnlpcands];
217 (*nlpcandssol)[c] = (*nlpcandssol)[*nnlpcands];
218 (*nlpcandsfrac)[c] = (*nlpcandsfrac)[*nnlpcands];
219 }
220 }
221 }
222
223 /* prefer decisions on variables which are also fractional in LP solution */
224 if( heurdata->preferlpfracs && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
225 {
226 for( c = 0; c < *nnlpcands; ++c )
227 {
228 if( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, (*nlpcands)[c])) )
229 (*nlpcandsfrac)[c] *= 100.0;
230 }
231 }
232
233 return SCIP_OKAY;
234}
235
236/** finds best candidate variable w.r.t. fractionality:
237 * - prefer variables that may not be rounded without destroying NLP feasibility:
238 * - of these variables, round least fractional variable in corresponding direction
239 * - if all remaining fractional variables may be rounded without destroying NLP feasibility:
240 * - round variable with least increasing objective value
241 * - binary variables are prefered
242 * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
243 * also be prefered if a correpsonding parameter is set
244 */
245static
247 SCIP* scip, /**< original SCIP data structure */
248 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
249 SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
250 SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
251 SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
252 int nnlpcands, /**< number of NLP fractional variables */
253 SCIP_HASHMAP* varincover, /**< hash map for variables */
254 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
255 int* bestcand, /**< pointer to store the index of the best candidate variable */
256 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
257 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
258 )
259{
260 SCIP_Real bestobjgain;
261 SCIP_Real bestfrac;
262 SCIP_Bool bestcandmayrounddown;
263 SCIP_Bool bestcandmayroundup;
264 int c;
265
266 /* check preconditions */
267 assert(scip != NULL);
268 assert(heurdata != NULL);
269 assert(nlpcands != NULL);
270 assert(nlpcandssol != NULL);
271 assert(nlpcandsfrac != NULL);
272 assert(covercomputed == (varincover != NULL));
273 assert(bestcand != NULL);
274 assert(bestcandmayround != NULL);
275 assert(bestcandroundup != NULL);
276
277 bestcandmayrounddown = TRUE;
278 bestcandmayroundup = TRUE;
279 bestobjgain = SCIPinfinity(scip);
280 bestfrac = SCIP_INVALID;
281
282 for( c = 0; c < nnlpcands; ++c )
283 {
284 SCIP_VAR* var;
285 SCIP_Bool mayrounddown;
286 SCIP_Bool mayroundup;
287 SCIP_Bool roundup;
288 SCIP_Real frac;
289 SCIP_Real obj;
290 SCIP_Real objgain;
291
292 var = nlpcands[c];
293
294 mayrounddown = SCIPvarMayRoundDown(var);
295 mayroundup = SCIPvarMayRoundUp(var);
296 frac = nlpcandsfrac[c];
297 obj = SCIPvarGetObj(var);
298
299 /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
300 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
301 continue;
302
303 if( mayrounddown || mayroundup )
304 {
305 /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
306 if( bestcandmayrounddown || bestcandmayroundup )
307 {
308 /* choose rounding direction:
309 * - if variable may be rounded in both directions, round corresponding to the fractionality
310 * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
311 * the current fractional solution
312 */
313 if( mayrounddown && mayroundup )
314 {
315 if( SCIPisEQ(scip, frac, 0.5) )
316 roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
317 else
318 roundup = (frac > 0.5);
319 }
320 else
321 roundup = mayrounddown;
322
323 if( roundup )
324 {
325 frac = 1.0 - frac;
326 objgain = frac*obj;
327 }
328 else
329 objgain = -frac*obj;
330
331 /* penalize too small fractions */
332 if( SCIPisEQ(scip, frac, 0.01) )
333 {
334 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
335 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
336 */
337 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
338 objgain *= 1000.0;
339 }
340 else if( frac < 0.01 )
341 objgain *= 1000.0;
342
343 /* prefer decisions on binary variables */
344 if( !SCIPvarIsBinary(var) )
345 objgain *= 1000.0;
346
347 /* prefer decisions on cover variables */
348 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
349 objgain *= 1000.0;
350
351 /* check, if candidate is new best candidate */
352 if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
353 {
354 *bestcand = c;
355 bestobjgain = objgain;
356 bestfrac = frac;
357 bestcandmayrounddown = mayrounddown;
358 bestcandmayroundup = mayroundup;
359 *bestcandroundup = roundup;
360 }
361 }
362 }
363 else
364 {
365 /* the candidate may not be rounded */
366 if( SCIPisEQ(scip, frac, 0.5) )
367 roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
368 else if( frac < 0.5 )
369 roundup = FALSE;
370 else
371 roundup = TRUE;
372
373 /* adjust fractional part */
374 if( roundup )
375 frac = 1.0 - frac;
376
377 /* penalize too small fractions */
378 if( SCIPisEQ(scip, frac, 0.01) )
379 {
380 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
381 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
382 */
383 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
384 frac += 10.0;
385 }
386 else if( frac < 0.01 )
387 frac += 10.0;
388
389 /* prefer decisions on binary variables */
390 if( !SCIPvarIsBinary(var) )
391 frac *= 1000.0;
392
393 /* prefer decisions on cover variables */
394 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
395 frac *= 1000.0;
396
397 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
398 if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
399 {
400 *bestcand = c;
401 bestfrac = frac;
402 bestcandmayrounddown = FALSE;
403 bestcandmayroundup = FALSE;
404 *bestcandroundup = roundup;
405 }
406 assert(bestfrac < SCIP_INVALID);
407 }
408 }
409
410 *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
411
412 return SCIP_OKAY;
413}
414
415/** finds best candidate variable w.r.t. vector length:
416 * - round variable with a small ratio between the increase in the objective and the locking numbers
417 * - binary variables are prefered
418 * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
419 * also be prefered if a corresponding parameter is set
420 */
421static
423 SCIP* scip, /**< original SCIP data structure */
424 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
425 SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
426 SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
427 SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
428 int nnlpcands, /**< number of NLP fractional variables */
429 SCIP_HASHMAP* varincover, /**< hash map for variables */
430 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
431 int* bestcand, /**< pointer to store the index of the best candidate variable */
432 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
433 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
434 )
435{
436 SCIP_Real bestscore;
437 int c;
438
439 /* check preconditions */
440 assert(scip != NULL);
441 assert(heurdata != NULL);
442 assert(nlpcands != NULL);
443 assert(nlpcandsfrac != NULL);
444 assert(nlpcandssol != NULL);
445 assert(bestcand != NULL);
446 assert(bestcandmayround != NULL);
447 assert(bestcandroundup != NULL);
448
449 *bestcandmayround = TRUE;
450 bestscore = SCIP_REAL_MAX;
451
452 /* get best candidate */
453 for( c = 0; c < nnlpcands; ++c )
454 {
455 SCIP_VAR* var;
456
457 SCIP_Real obj;
458 SCIP_Real objdelta;
459 SCIP_Real frac;
460 SCIP_Real score;
461
462 int nlocks;
463
464 SCIP_Bool roundup;
465
466 var = nlpcands[c];
467
468 /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
469 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
470 continue;
471
472 frac = nlpcandsfrac[c];
473 obj = SCIPvarGetObj(var);
474 roundup = (obj >= 0.0);
475 objdelta = (roundup ? (1.0-frac)*obj : -frac * obj);
476 assert(objdelta >= 0.0);
477
478 /* check whether the variable is roundable */
479 *bestcandmayround = *bestcandmayround && (SCIPvarMayRoundDown(var) || SCIPvarMayRoundUp(var));
481
482 /* smaller score is better */
483 score = (objdelta + SCIPsumepsilon(scip))/((SCIP_Real)nlocks+1.0);
484
485 /* prefer decisions on binary variables */
487 score *= 1000.0;
488
489 /* prefer decisions on cover variables */
490 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
491 score *= 1000;
492
493 /* check, if candidate is new best candidate */
494 if( score < bestscore )
495 {
496 *bestcand = c;
497 bestscore = score;
498 *bestcandroundup = roundup;
499 }
500 }
501
502 return SCIP_OKAY;
503}
504
505
506/** finds best candidate variable w.r.t. locking numbers:
507 * - prefer variables that may not be rounded without destroying LP feasibility:
508 * - of these variables, round variable with least number of locks in corresponding direction
509 * - if all remaining fractional variables may be rounded without destroying LP feasibility:
510 * - round variable with least number of locks in opposite of its feasible rounding direction
511 * - binary variables are prefered
512 * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
513 * also be prefered if a correpsonding parameter is set
514 */
515static
517 SCIP* scip, /**< original SCIP data structure */
518 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
519 SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
520 SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
521 SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
522 int nnlpcands, /**< number of NLP fractional variables */
523 SCIP_HASHMAP* varincover, /**< hash map for variables */
524 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
525 int* bestcand, /**< pointer to store the index of the best candidate variable */
526 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
527 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
528 )
529{
530 SCIP_Bool bestcandmayrounddown;
531 SCIP_Bool bestcandmayroundup;
532 int bestnviolrows; /* number of violated rows for best candidate */
533 SCIP_Real bestcandfrac; /* fractionality of best candidate */
534 int c;
535
536 /* check preconditions */
537 assert(scip != NULL);
538 assert(heurdata != NULL);
539 assert(nlpcands != NULL);
540 assert(nlpcandsfrac != NULL);
541 assert(nlpcandssol != NULL);
542 assert(bestcand != NULL);
543 assert(bestcandmayround != NULL);
544 assert(bestcandroundup != NULL);
545
546 bestcandmayrounddown = TRUE;
547 bestcandmayroundup = TRUE;
548 bestnviolrows = INT_MAX;
549 bestcandfrac = SCIP_INVALID;
550
551 /* get best candidate */
552 for( c = 0; c < nnlpcands; ++c )
553 {
554 SCIP_VAR* var;
555
556 int nlocksdown;
557 int nlocksup;
558 int nviolrows;
559
560 SCIP_Bool mayrounddown;
561 SCIP_Bool mayroundup;
562 SCIP_Bool roundup;
563 SCIP_Real frac;
564
565 var = nlpcands[c];
566 mayrounddown = SCIPvarMayRoundDown(var);
567 mayroundup = SCIPvarMayRoundUp(var);
568 frac = nlpcandsfrac[c];
569
570 /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
571 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
572 continue;
573
574 if( mayrounddown || mayroundup )
575 {
576 /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
577 if( bestcandmayrounddown || bestcandmayroundup )
578 {
579 /* choose rounding direction:
580 * - if variable may be rounded in both directions, round corresponding to the fractionality
581 * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
582 * the current fractional solution
583 */
584 if( mayrounddown && mayroundup )
585 {
586 if( SCIPisEQ(scip, frac, 0.5) )
587 roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
588 else
589 roundup = (frac > 0.5);
590 }
591 else
592 roundup = mayrounddown;
593
594 if( roundup )
595 {
596 frac = 1.0 - frac;
598 }
599 else
601
602 /* penalize too small fractions */
603 if( SCIPisEQ(scip, frac, 0.01) )
604 {
605 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
606 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
607 */
608 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
609 nviolrows *= 100;
610 }
611 else if( frac < 0.01 )
612 nviolrows *= 100;
613
614 /* prefer decisions on binary variables */
615 if( !SCIPvarIsBinary(var) )
616 nviolrows *= 1000;
617
618 /* prefer decisions on cover variables */
619 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
620 nviolrows *= 1000;
621
622 /* check, if candidate is new best candidate */
623 assert( (0.0 < frac && frac < 1.0) || SCIPvarIsBinary(var) );
624 if( nviolrows + frac < bestnviolrows + bestcandfrac )
625 {
626 *bestcand = c;
627 bestnviolrows = nviolrows;
628 bestcandfrac = frac;
629 bestcandmayrounddown = mayrounddown;
630 bestcandmayroundup = mayroundup;
631 *bestcandroundup = roundup;
632 }
633 }
634 }
635 else
636 {
637 /* the candidate may not be rounded */
640
641 roundup = (nlocksdown > nlocksup);
642 if( !roundup )
643 {
644 roundup = (nlocksdown == nlocksup);
645 if( SCIPisEQ(scip, frac, 0.5) )
646 roundup = (roundup && (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0));
647 else
648 roundup = (roundup && frac > 0.5);
649 }
650
651 if( roundup )
652 {
653 nviolrows = nlocksup;
654 frac = 1.0 - frac;
655 }
656 else
657 nviolrows = nlocksdown;
658
659 /* penalize too small fractions */
660 if( SCIPisEQ(scip, frac, 0.01) )
661 {
662 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
663 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
664 */
665 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
666 nviolrows *= 100;
667 }
668 else if( frac < 0.01 )
669 nviolrows *= 100;
670
671 /* prefer decisions on binary variables */
672 if( !SCIPvarIsBinary(var) )
673 nviolrows *= 100;
674
675 /* prefer decisions on cover variables */
676 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
677 nviolrows *= 1000;
678
679 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
680 assert((0.0 < frac && frac < 1.0) || SCIPvarIsBinary(var));
681 if( bestcandmayrounddown || bestcandmayroundup || nviolrows + frac < bestnviolrows + bestcandfrac )
682 {
683 *bestcand = c;
684 bestnviolrows = nviolrows;
685 bestcandfrac = frac;
686 bestcandmayrounddown = FALSE;
687 bestcandmayroundup = FALSE;
688 *bestcandroundup = roundup;
689 }
690 assert(bestcandfrac < SCIP_INVALID);
691 }
692 }
693
694 *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
695
696 return SCIP_OKAY;
697}
698
699/** calculates the pseudocost score for a given variable w.r.t. a given solution value and a given rounding direction */
700static
702 SCIP* scip, /**< SCIP data structure */
703 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
704 SCIP_VAR* var, /**< problem variable */
705 SCIP_Real primsol, /**< primal solution of variable */
706 SCIP_Real frac, /**< fractionality of variable */
707 int rounddir, /**< -1: round down, +1: round up, 0: select due to pseudo cost values */
708 SCIP_Real* pscostquot, /**< pointer to store pseudo cost quotient */
709 SCIP_Bool* roundup, /**< pointer to store whether the variable should be rounded up */
710 SCIP_Bool prefvar /**< should this variable be preferred because it is in a minimal cover? */
711 )
712{
713 SCIP_Real pscostdown;
714 SCIP_Real pscostup;
715
716 assert(heurdata != NULL);
717 assert(pscostquot != NULL);
718 assert(roundup != NULL);
719 assert(SCIPisEQ(scip, frac, primsol - SCIPfeasFloor(scip, primsol)));
720
721 /* bound fractions to not prefer variables that are nearly integral */
722 frac = MAX(frac, 0.1);
723 frac = MIN(frac, 0.9);
724
725 /* get pseudo cost quotient */
726 pscostdown = SCIPgetVarPseudocostVal(scip, var, 0.0-frac);
727 pscostup = SCIPgetVarPseudocostVal(scip, var, 1.0-frac);
728 assert(pscostdown >= 0.0 && pscostup >= 0.0);
729
730 /* choose rounding direction
731 *
732 * to avoid performance variability caused by numerics we use random numbers to decide whether we want to roundup or
733 * round down if the values to compare are equal within tolerances.
734 */
735 if( rounddir == -1 )
736 *roundup = FALSE;
737 else if( rounddir == +1 )
738 *roundup = TRUE;
739 else if( SCIPisLT(scip, primsol, SCIPvarGetRootSol(var) - 0.4)
740 || (SCIPisEQ(scip, primsol, SCIPvarGetRootSol(var) - 0.4) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
741 *roundup = FALSE;
742 else if( SCIPisGT(scip, primsol, SCIPvarGetRootSol(var) + 0.4)
743 || (SCIPisEQ(scip, primsol, SCIPvarGetRootSol(var) + 0.4) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
744 *roundup = TRUE;
745 else if( SCIPisLT(scip, frac, 0.3) || (SCIPisEQ(scip, frac, 0.3) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
746 *roundup = FALSE;
747 else if( SCIPisGT(scip, frac, 0.7) || (SCIPisEQ(scip, frac, 0.7) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
748 *roundup = TRUE;
749 else if( SCIPisLT(scip, pscostdown, pscostup)
750 || (SCIPisEQ(scip, pscostdown, pscostup) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0))
751 *roundup = FALSE;
752 else
753 *roundup = TRUE;
754
755 /* calculate pseudo cost quotient */
756 if( *roundup )
757 *pscostquot = sqrt(frac) * (1.0+pscostdown) / (1.0+pscostup);
758 else
759 *pscostquot = sqrt(1.0-frac) * (1.0+pscostup) / (1.0+pscostdown);
760
761 /* prefer decisions on binary variables */
762 if( SCIPvarIsBinary(var) )
763 (*pscostquot) *= 1000.0;
764
765 /* prefer decisions on cover variables */
766 if( prefvar )
767 (*pscostquot) *= 1000.0;
768}
769
770/** finds best candidate variable w.r.t. pseudo costs:
771 * - prefer variables that may not be rounded without destroying LP feasibility:
772 * - of these variables, round variable with largest rel. difference of pseudo cost values in corresponding
773 * direction
774 * - if all remaining fractional variables may be rounded without destroying LP feasibility:
775 * - round variable in the objective value direction
776 * - binary variables are prefered
777 * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
778 * also be prefered if a correpsonding parameter is set
779 */
780static
782 SCIP* scip, /**< original SCIP data structure */
783 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
784 SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
785 SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
786 SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
787 int nnlpcands, /**< number of NLP fractional variables */
788 SCIP_HASHMAP* varincover, /**< hash map for variables */
789 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
790 int* bestcand, /**< pointer to store the index of the best candidate variable */
791 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
792 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
793 )
794{
795 SCIP_Bool bestcandmayrounddown;
796 SCIP_Bool bestcandmayroundup;
797 SCIP_Real bestpscostquot;
798 int c;
799
800 /* check preconditions */
801 assert(scip != NULL);
802 assert(heurdata != NULL);
803 assert(nlpcands != NULL);
804 assert(nlpcandsfrac != NULL);
805 assert(nlpcandssol != NULL);
806 assert(bestcand != NULL);
807 assert(bestcandmayround != NULL);
808 assert(bestcandroundup != NULL);
809
810 bestcandmayrounddown = TRUE;
811 bestcandmayroundup = TRUE;
812 bestpscostquot = -1.0;
813
814 for( c = 0; c < nnlpcands; ++c )
815 {
816 SCIP_VAR* var;
817 SCIP_Real primsol;
818
819 SCIP_Bool mayrounddown;
820 SCIP_Bool mayroundup;
821 SCIP_Bool roundup;
822 SCIP_Bool prefvar;
823 SCIP_Real frac;
824 SCIP_Real pscostquot;
825
826 var = nlpcands[c];
827 mayrounddown = SCIPvarMayRoundDown(var);
828 mayroundup = SCIPvarMayRoundUp(var);
829 primsol = nlpcandssol[c];
830 frac = nlpcandsfrac[c];
831 prefvar = covercomputed && heurdata->prefercover && SCIPhashmapExists(varincover, var);
832 pscostquot = SCIP_INVALID;
833
834 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
835 continue;
836
837 if( mayrounddown || mayroundup )
838 {
839 /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
840 if( bestcandmayrounddown || bestcandmayroundup )
841 {
842 /* choose rounding direction:
843 * - if variable may be rounded in both directions, round corresponding to the pseudo cost values
844 * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
845 * the current fractional solution
846 */
847 roundup = FALSE;
848 if( mayrounddown && mayroundup )
849 calcPscostQuot(scip, heurdata, var, primsol, frac, 0, &pscostquot, &roundup, prefvar);
850 else if( mayrounddown )
851 calcPscostQuot(scip, heurdata, var, primsol, frac, +1, &pscostquot, &roundup, prefvar);
852 else
853 calcPscostQuot(scip, heurdata, var, primsol, frac, -1, &pscostquot, &roundup, prefvar);
854
855 assert(!SCIPisInfinity(scip,ABS(pscostquot)));
856
857 /* check, if candidate is new best candidate */
858 if( pscostquot > bestpscostquot )
859 {
860 *bestcand = c;
861 bestpscostquot = pscostquot;
862 bestcandmayrounddown = mayrounddown;
863 bestcandmayroundup = mayroundup;
864 *bestcandroundup = roundup;
865 }
866 }
867 }
868 else
869 {
870 /* the candidate may not be rounded: calculate pseudo cost quotient and preferred direction */
871 calcPscostQuot(scip, heurdata, var, primsol, frac, 0, &pscostquot, &roundup, prefvar);
872 assert(!SCIPisInfinity(scip,ABS(pscostquot)));
873
874 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
875 if( bestcandmayrounddown || bestcandmayroundup || pscostquot > bestpscostquot )
876 {
877 *bestcand = c;
878 bestpscostquot = pscostquot;
879 bestcandmayrounddown = FALSE;
880 bestcandmayroundup = FALSE;
881 *bestcandroundup = roundup;
882 }
883 }
884 }
885
886 *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
887
888 return SCIP_OKAY;
889}
890
891/** finds best candidate variable w.r.t. the incumbent solution:
892 * - prefer variables that may not be rounded without destroying LP feasibility:
893 * - of these variables, round a variable to its value in direction of incumbent solution, and choose the
894 * variable that is closest to its rounded value
895 * - if all remaining fractional variables may be rounded without destroying LP feasibility:
896 * - round variable in direction that destroys LP feasibility (other direction is checked by SCIProundSol())
897 * - round variable with least increasing objective value
898 * - binary variables are prefered
899 * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
900 * also be prefered if a correpsonding parameter is set
901 */
902static
904 SCIP* scip, /**< original SCIP data structure */
905 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
906 SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
907 SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
908 SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
909 int nnlpcands, /**< number of NLP fractional variables */
910 SCIP_SOL* bestsol, /**< incumbent solution */
911 SCIP_HASHMAP* varincover, /**< hash map for variables */
912 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
913 int* bestcand, /**< pointer to store the index of the best candidate variable */
914 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
915 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
916 )
917{
918 SCIP_Real bestobjgain;
919 SCIP_Real bestfrac;
920 SCIP_Bool bestcandmayrounddown;
921 SCIP_Bool bestcandmayroundup;
922 int c;
923
924 /* check preconditions */
925 assert(scip != NULL);
926 assert(heurdata != NULL);
927 assert(nlpcands != NULL);
928 assert(nlpcandsfrac != NULL);
929 assert(nlpcandssol != NULL);
930 assert(bestcand != NULL);
931 assert(bestcandmayround != NULL);
932 assert(bestcandroundup != NULL);
933
934 bestcandmayrounddown = TRUE;
935 bestcandmayroundup = TRUE;
936 bestobjgain = SCIPinfinity(scip);
937 bestfrac = SCIP_INVALID;
938
939 for( c = 0; c < nnlpcands; ++c )
940 {
941 SCIP_VAR* var;
942 SCIP_Real bestsolval;
943 SCIP_Real solval;
944 SCIP_Real obj;
945 SCIP_Real frac;
946 SCIP_Real objgain;
947
948 SCIP_Bool mayrounddown;
949 SCIP_Bool mayroundup;
950 SCIP_Bool roundup;
951
952 var = nlpcands[c];
953 mayrounddown = SCIPvarMayRoundDown(var);
954 mayroundup = SCIPvarMayRoundUp(var);
955 solval = nlpcandssol[c];
956 frac = nlpcandsfrac[c];
957 obj = SCIPvarGetObj(var);
958 bestsolval = SCIPgetSolVal(scip, bestsol, var);
959
960 /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
961 if( SCIPisLT(scip, solval, SCIPvarGetLbLocal(var)) || SCIPisGT(scip, solval, SCIPvarGetUbLocal(var)) )
962 continue;
963
964 /* select default rounding direction
965 * try to avoid variability; decide randomly if the LP solution can contain some noise
966 */
967 if( SCIPisEQ(scip, solval, bestsolval) )
968 roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
969 else
970 roundup = (solval < bestsolval);
971
972 if( mayrounddown || mayroundup )
973 {
974 /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
975 if( bestcandmayrounddown || bestcandmayroundup )
976 {
977 /* choose rounding direction:
978 * - if variable may be rounded in both directions, round corresponding to its value in incumbent solution
979 * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
980 * the current fractional solution with SCIProundSol()
981 */
982 if( !mayrounddown || !mayroundup )
983 roundup = mayrounddown;
984
985 if( roundup )
986 {
987 frac = 1.0 - frac;
988 objgain = frac*obj;
989 }
990 else
991 objgain = -frac*obj;
992
993 /* penalize too small fractions */
994 if( SCIPisEQ(scip, frac, 0.01) )
995 {
996 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
997 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
998 */
999 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
1000 objgain *= 1000.0;
1001 }
1002 else if( frac < 0.01 )
1003 objgain *= 1000.0;
1004
1005 /* prefer decisions on binary variables */
1006 if( !SCIPvarIsBinary(var) )
1007 objgain *= 1000.0;
1008
1009 /* prefer decisions on cover variables */
1010 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
1011 objgain *= 1000.0;
1012
1013 /* check, if candidate is new best candidate */
1014 if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
1015 {
1016 *bestcand = c;
1017 bestobjgain = objgain;
1018 bestfrac = frac;
1019 bestcandmayrounddown = mayrounddown;
1020 bestcandmayroundup = mayroundup;
1021 *bestcandroundup = roundup;
1022 }
1023 }
1024 }
1025 else
1026 {
1027 /* the candidate may not be rounded */
1028 if( roundup )
1029 frac = 1.0 - frac;
1030
1031 /* penalize too small fractions */
1032 if( SCIPisEQ(scip, frac, 0.01) )
1033 {
1034 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
1035 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
1036 */
1037 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
1038 frac += 10.0;
1039 }
1040 else if( frac < 0.01 )
1041 frac += 10.0;
1042
1043 /* prefer decisions on binary variables */
1044 if( !SCIPvarIsBinary(var) )
1045 frac *= 1000.0;
1046
1047 /* prefer decisions on cover variables */
1048 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
1049 frac *= 1000.0;
1050
1051 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
1052 if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
1053 {
1054 *bestcand = c;
1055 bestfrac = frac;
1056 bestcandmayrounddown = FALSE;
1057 bestcandmayroundup = FALSE;
1058 *bestcandroundup = roundup;
1059 }
1060 }
1061 }
1062
1063 *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
1064
1065 return SCIP_OKAY;
1066}
1067
1068/** finds best candidate variable w.r.t. both, the LP and the NLP solution:
1069 * - choose a variable for which the sum of the distances from the relaxations' solutions to a common
1070 * integer value is minimal
1071 * - binary variables are prefered
1072 * - variables in a minimal cover might be prefered if a corresponding parameter is set
1073 */
1074static
1076 SCIP* scip, /**< original SCIP data structure */
1077 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1078 SCIP_VAR** pseudocands, /**< array of non-fixed variables */
1079 SCIP_Real* pseudocandsnlpsol, /**< array of NLP solution values */
1080 SCIP_Real* pseudocandslpsol, /**< array of LP solution values */
1081 int npseudocands, /**< number of NLP fractional variables */
1082 SCIP_HASHMAP* varincover, /**< hash map for variables */
1083 SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
1084 int* bestcand, /**< pointer to store the index of the best candidate variable */
1085 SCIP_Real* bestboundval, /**< pointer to store the bound, the best candidate should be rounded to */
1086 SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
1087 SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
1088 )
1089{
1090 SCIP_Real bestfrac;
1091 int c;
1092
1093 /* check preconditions */
1094 assert(scip != NULL);
1095 assert(heurdata != NULL);
1096 assert(pseudocands != NULL);
1097 assert(pseudocandsnlpsol != NULL);
1098 assert(pseudocandslpsol != NULL);
1099 assert(covercomputed == (varincover != NULL));
1100 assert(bestcand != NULL);
1101 assert(bestcandmayround != NULL);
1102 assert(bestcandroundup != NULL);
1103
1104 bestfrac = SCIP_INVALID;
1105
1106 for( c = 0; c < npseudocands; ++c )
1107 {
1108 SCIP_VAR* var;
1109 SCIP_Bool mayround;
1110 SCIP_Bool roundup;
1111
1112 SCIP_Real frac;
1113 SCIP_Real lpsol;
1114 SCIP_Real nlpsol;
1115 SCIP_Real lpsolfloor;
1116 SCIP_Real nlpsolfloor;
1117 SCIP_Real lpsolceil;
1118 SCIP_Real nlpsolceil;
1119 SCIP_Real boundval;
1120 SCIP_Real floorval;
1121 SCIP_Real ceilval;
1122
1123 var = pseudocands[c];
1124 lpsol = pseudocandslpsol[c];
1125 nlpsol = pseudocandsnlpsol[c];
1126
1127 assert(SCIPvarGetUbLocal(var)-SCIPvarGetLbLocal(var) > 0.5);
1128 assert(SCIPisLE(scip, SCIPvarGetLbLocal(var), lpsol) && SCIPisLE(scip, lpsol, SCIPvarGetUbLocal(var)));
1129
1130 /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
1131 if( SCIPisLT(scip, nlpsol, SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpsol, SCIPvarGetUbLocal(var)) )
1132 continue;
1133
1134 mayround = SCIPvarMayRoundDown(var) || SCIPvarMayRoundUp(var);
1135
1136 /* if this candidate is trivially roundable, and we already know a candidate that is not, continue */
1137 if( mayround && !(*bestcandmayround) )
1138 continue;
1139
1140 if( SCIPisFeasEQ(scip, lpsol, nlpsol) && SCIPisFeasIntegral(scip, lpsol))
1141 continue;
1142
1143 lpsolfloor = SCIPfeasFloor(scip, lpsol);
1144 nlpsolfloor = SCIPfeasFloor(scip, nlpsol);
1145 lpsolceil = SCIPfeasCeil(scip, lpsol);
1146 nlpsolceil = SCIPfeasCeil(scip, nlpsol);
1147 floorval = MIN(lpsolfloor,nlpsolfloor);
1148 ceilval = MAX(lpsolceil,nlpsolceil);
1149
1150 /* if both values are in the same interval, find out which integer is (in sum) the closer one, this will be the
1151 * new bound. The minima and maxima are necessary since one or both values with be integer
1152 */
1153 if( SCIPvarIsBinary(var) || ceilval-floorval < 1.5 )
1154 {
1155 frac = 0.33*(lpsol-floorval) + 0.67*(nlpsol-floorval);
1156 if( frac < 0.5 )
1157 {
1158 roundup = FALSE;
1159 boundval = MIN(lpsolfloor,nlpsolfloor);
1160 }
1161 else
1162 {
1163 roundup = TRUE;
1164 frac = 1.0-frac;
1165 boundval = MAX(nlpsolceil,lpsolceil);
1166 }
1167 }
1168 else
1169 {
1170 /* determine new bound in the middle of both relaxations, such that the NLP stays feasible */
1171 SCIP_Real midval;
1172 midval = (nlpsol+lpsol)/2.0;
1173 roundup = nlpsol > lpsol;
1174 frac = ABS(nlpsol-lpsol);
1175
1176 if( roundup )
1177 boundval = SCIPfeasCeil(scip, midval);
1178 else
1179 boundval = SCIPfeasFloor(scip, midval);
1180
1181 assert(roundup == SCIPisGT(scip, nlpsol, boundval));
1182 }
1183
1184 /* penalize too small fractions */
1185 if( SCIPisEQ(scip, frac, 0.01) )
1186 {
1187 /* try to avoid variability; decide randomly if the LP solution can contain some noise.
1188 * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
1189 */
1190 if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
1191 frac += 10.0;
1192 }
1193 else if( frac < 0.01 )
1194 frac += 10.0;
1195
1196 /* prefer decisions on binary variables */
1197 if( !SCIPvarIsBinary(var) )
1198 frac *= 1000.0;
1199
1200 /* prefer decisions on cover variables */
1201 if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
1202 frac *= 1000.0;
1203
1204 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
1205 if( frac < bestfrac || (*bestcandmayround && !mayround) )
1206 {
1207 *bestcand = c;
1208 bestfrac = frac;
1209 *bestcandmayround = FALSE;
1210 *bestcandroundup = roundup;
1211 *bestboundval = boundval;
1212 }
1213 assert(bestfrac < SCIP_INVALID);
1214 }
1215
1216 if( *bestcandroundup )
1217 *bestboundval -= 0.5;
1218 else
1219 *bestboundval += 0.5;
1220
1221 return SCIP_OKAY;
1222}
1223
1224/** creates a new solution for the original problem by copying the solution of the subproblem */
1225static
1227 SCIP* scip, /**< original SCIP data structure */
1228 SCIP* subscip, /**< SCIP structure of the subproblem */
1229 SCIP_HEUR* heur, /**< heuristic structure */
1230 SCIP_HASHMAP* varmap, /**< hash map for variables */
1231 SCIP_SOL* subsol, /**< solution of the subproblem */
1232 SCIP_Bool* success /**< used to store whether new solution was found or not */
1233 )
1234{
1235 SCIP_VAR** vars; /* the original problem's variables */
1236 SCIP_Real* subsolvals; /* solution values of the subproblem */
1237 SCIP_SOL* newsol; /* solution to be created for the original problem */
1238 int nvars; /* the original problem's number of variables */
1239 SCIP_VAR* subvar;
1240 int i;
1241
1242 assert(scip != NULL);
1243 assert(subscip != NULL);
1244 assert(subsol != NULL);
1245
1246 /* get variables' data */
1247 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1248
1249 SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
1250
1251 /* copy the solution */
1252 for( i = 0; i < nvars; ++i )
1253 {
1254 subvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
1255 if( subvar == NULL )
1256 subsolvals[i] = MIN(MAX(0.0, SCIPvarGetLbLocal(vars[i])), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
1257 else
1258 subsolvals[i] = SCIPgetSolVal(subscip, subsol, subvar);
1259 }
1260
1261 /* create new solution for the original problem */
1262 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
1263 SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
1264
1265 /* try to add new solution to scip and free it immediately */
1266 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
1267
1268 SCIPfreeBufferArray(scip, &subsolvals);
1269
1270 return SCIP_OKAY;
1271}
1272
1273/** todo setup and solve the subMIP */
1274static
1276 SCIP* scip, /**< SCIP data structure */
1277 SCIP* subscip, /**< NLP diving subscip */
1278 SCIP_HEUR* heur, /**< heuristic data structure */
1279 SCIP_VAR** covervars, /**< variables in the cover, should be fixed locally */
1280 int ncovervars, /**< number of variables in the cover */
1281 SCIP_Bool* success /**< pointer to store whether a solution was found */
1282 )
1283{
1284 SCIP_HASHMAP* varmap;
1285 SCIP_SOL** subsols;
1286 int c;
1287 int nsubsols;
1288
1289 assert(subscip != NULL);
1290 assert(scip != NULL);
1291 assert(heur != NULL);
1292
1293 /* create the variable mapping hash map */
1294 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPgetNVars(scip)) );
1295
1296 *success = FALSE;
1297
1298 /* copy original problem to subproblem; do not copy pricers */
1299 SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmap, NULL, "undercoversub", NULL, NULL, 0, FALSE, FALSE, FALSE,
1300 TRUE, NULL) );
1301
1302 /* assert that cover variables are fixed in source and target SCIP */
1303 for( c = 0; c < ncovervars; c++)
1304 {
1305 assert(SCIPhashmapGetImage(varmap, covervars[c]) != NULL); /* cover variable cannot be relaxation-only, thus must have been copied */
1306 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(covervars[c]), SCIPvarGetUbLocal(covervars[c])));
1307 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal((SCIP_VAR*) SCIPhashmapGetImage(varmap, covervars[c])),
1308 SCIPvarGetUbGlobal((SCIP_VAR*) SCIPhashmapGetImage(varmap, covervars[c]))));
1309 }
1310
1311 /* set parameters for sub-SCIP */
1312
1313 /* do not abort subproblem on CTRL-C */
1314 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
1315
1316#ifdef SCIP_DEBUG
1317 /* for debugging, enable full output */
1318 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
1319 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
1320#else
1321 /* disable statistic timing inside sub SCIP and output to console */
1322 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
1323 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
1324#endif
1325
1326 /* set limits for the subproblem */
1327 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
1328 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", (SCIP_Longint)100) );
1329 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", (SCIP_Longint)500) );
1330
1331 /* forbid recursive call of heuristics and separators solving sub-SCIPs */
1332 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
1333
1334 /* disable cutting plane separation */
1336
1337 /* disable expensive presolving */
1339
1340 /* use best estimate node selection */
1341 if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
1342 {
1343 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
1344 }
1345
1346 /* use inference branching */
1347 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
1348 {
1349 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
1350 }
1351
1352 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
1353 if( !SCIPisParamFixed(subscip, "conflict/enable") )
1354 {
1355 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
1356 }
1357 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
1358 {
1359 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
1360 }
1361 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
1362 {
1363 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
1364 }
1365
1366 if( SCIPgetNSols(scip) > 0 )
1367 {
1368 SCIP_Real upperbound;
1369 SCIP_Real cutoffbound;
1370 SCIP_Real minimprove;
1371
1373
1374 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1375 minimprove = 0.01;
1376
1378 {
1379 cutoffbound = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
1380 }
1381 else
1382 {
1383 if( SCIPgetUpperbound(scip) >= 0 )
1384 cutoffbound = (1 - minimprove)*SCIPgetUpperbound(scip);
1385 else
1386 cutoffbound = (1 + minimprove)*SCIPgetUpperbound(scip);
1387 }
1388 cutoffbound = MIN(upperbound, cutoffbound);
1389 SCIP_CALL( SCIPsetObjlimit(subscip, cutoffbound) );
1390 }
1391
1392 SCIP_CALL_ABORT( SCIPsolve(subscip) );
1393
1394 /* check, whether a solution was found;
1395 * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
1396 */
1397 nsubsols = SCIPgetNSols(subscip);
1398 subsols = SCIPgetSols(subscip);
1399 for( c = 0; c < nsubsols && !(*success); ++c )
1400 {
1401 SCIP_CALL( createNewSol(scip, subscip, heur, varmap, subsols[c], success) );
1402 }
1403
1404 SCIPhashmapFree(&varmap);
1405
1406 return SCIP_OKAY;
1407}
1408
1409
1410/** solves subproblem and passes best feasible solution to original SCIP instance */
1411static
1413 SCIP* scip, /**< SCIP data structure of the original problem */
1414 SCIP_HEUR* heur, /**< heuristic data structure */
1415 SCIP_VAR** covervars, /**< variables in the cover, should be fixed locally */
1416 int ncovervars, /**< number of variables in the cover */
1417 SCIP_Bool* success /**< pointer to store whether a solution was found */
1418 )
1419{
1420 SCIP* subscip;
1421 SCIP_RETCODE retcode;
1422
1423 /* check whether there is enough time and memory left */
1424 SCIP_CALL( SCIPcheckCopyLimits(scip, success) );
1425
1426 if( !(*success) )
1427 return SCIP_OKAY;
1428
1429 /* create subproblem */
1430 SCIP_CALL( SCIPcreate(&subscip) );
1431
1432 retcode = doSolveSubMIP(scip, subscip, heur, covervars, ncovervars, success);
1433
1434 /* free sub-SCIP even if an error occurred during the subscip solve */
1435 SCIP_CALL( SCIPfree(&subscip) );
1436
1437 SCIP_CALL( retcode );
1438
1439 return SCIP_OKAY;
1440}
1441
1442/* ---------------- Callback methods of event handler ---------------- */
1443
1444/* exec the event handler
1445 *
1446 * We update the number of variables fixed in the cover
1447 */
1448static
1449SCIP_DECL_EVENTEXEC(eventExecNlpdiving)
1450{
1451 SCIP_EVENTTYPE eventtype;
1452 SCIP_HEURDATA* heurdata;
1453 SCIP_VAR* var;
1454
1455 SCIP_Real oldbound;
1456 SCIP_Real newbound;
1457 SCIP_Real otherbound;
1458
1459 assert(eventhdlr != NULL);
1460 assert(eventdata != NULL);
1461 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1462 assert(event != NULL);
1463
1464 heurdata = (SCIP_HEURDATA*)eventdata;
1465 assert(heurdata != NULL);
1466 assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1467
1468 oldbound = SCIPeventGetOldbound(event);
1469 newbound = SCIPeventGetNewbound(event);
1470 var = SCIPeventGetVar(event);
1471
1472 eventtype = SCIPeventGetType(event);
1473 otherbound = (eventtype & SCIP_EVENTTYPE_LBCHANGED) ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
1474
1475 switch( eventtype )
1476 {
1479 /* if cover variable is now fixed */
1480 if( SCIPisFeasEQ(scip, newbound, otherbound) && !SCIPisFeasEQ(scip, oldbound, otherbound) )
1481 {
1482 assert(!SCIPisEQ(scip, oldbound, otherbound));
1483 ++(heurdata->nfixedcovervars);
1484 }
1485 break;
1488 /* if cover variable is now unfixed */
1489 if( SCIPisFeasEQ(scip, oldbound, otherbound) && !SCIPisFeasEQ(scip, newbound, otherbound) )
1490 {
1491 assert(!SCIPisEQ(scip, newbound, otherbound));
1492 --(heurdata->nfixedcovervars);
1493 }
1494 break;
1495 default:
1496 SCIPerrorMessage("invalid event type.\n");
1497 return SCIP_INVALIDDATA;
1498 }
1499 assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1500
1501 /* SCIPdebugMsg(scip, "changed bound of cover variable <%s> from %f to %f (nfixedcovervars: %d).\n", SCIPvarGetName(var),
1502 oldbound, newbound, heurdata->nfixedcovervars); */
1503
1504 return SCIP_OKAY;
1505}
1506
1507
1508/*
1509 * Callback methods
1510 */
1511
1512/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1513static
1514SCIP_DECL_HEURCOPY(heurCopyNlpdiving)
1515{ /*lint --e{715}*/
1516 assert(scip != NULL);
1517 assert(heur != NULL);
1518 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1519
1520 /* call inclusion method of primal heuristic */
1522
1523 return SCIP_OKAY;
1524}
1525
1526/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1527static
1528SCIP_DECL_HEURFREE(heurFreeNlpdiving) /*lint --e{715}*/
1529{ /*lint --e{715}*/
1530 SCIP_HEURDATA* heurdata;
1531
1532 assert(heur != NULL);
1533 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1534 assert(scip != NULL);
1535
1536 /* free heuristic data */
1537 heurdata = SCIPheurGetData(heur);
1538 assert(heurdata != NULL);
1539 SCIPfreeBlockMemory(scip, &heurdata);
1540 SCIPheurSetData(heur, NULL);
1541
1542 return SCIP_OKAY;
1543}
1544
1545
1546/** initialization method of primal heuristic (called after problem was transformed) */
1547static
1548SCIP_DECL_HEURINIT(heurInitNlpdiving) /*lint --e{715}*/
1549{ /*lint --e{715}*/
1550 SCIP_HEURDATA* heurdata;
1551
1552 assert(heur != NULL);
1553 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1554
1555 /* get heuristic data */
1556 heurdata = SCIPheurGetData(heur);
1557 assert(heurdata != NULL);
1558
1559 /* create working solution */
1560 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
1561
1562 /* create random number generator */
1563 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE) );
1564
1565 /* initialize data */
1566 heurdata->nnlpiterations = 0;
1567 heurdata->nsuccess = 0;
1568 heurdata->nfixedcovervars = 0;
1570 heurdata->nnlpsolves = 0;
1571 heurdata->nfailcutoff = 0;
1572 heurdata->nfaildepth = 0;
1573 heurdata->nfailnlperror = 0;
1574 );
1575
1576 return SCIP_OKAY;
1577}
1578
1579
1580/** deinitialization method of primal heuristic (called before transformed problem is freed) */
1581static
1582SCIP_DECL_HEUREXIT(heurExitNlpdiving) /*lint --e{715}*/
1583{ /*lint --e{715}*/
1584 SCIP_HEURDATA* heurdata;
1585
1586 assert(heur != NULL);
1587 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1588
1589 /* get heuristic data */
1590 heurdata = SCIPheurGetData(heur);
1591 assert(heurdata != NULL);
1592
1593 /* free random number generator */
1594 SCIPfreeRandom(scip, &heurdata->randnumgen);
1595
1596 /* free working solution */
1597 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
1598
1600 if( strstr(SCIPgetProbName(scip), "_covering") == NULL && SCIPheurGetNCalls(heur) > 0 )
1601 {
1602 SCIPstatisticMessage("%-30s %5" SCIP_LONGINT_FORMAT " sols in %5" SCIP_LONGINT_FORMAT " runs, %6.1fs, %7d NLP iters in %5d NLP solves, %5.1f avg., %3d%% success %3d%% cutoff %3d%% depth %3d%% nlperror\n",
1604 heurdata->nnlpiterations, heurdata->nnlpsolves, heurdata->nnlpiterations/MAX(1.0,(SCIP_Real)heurdata->nnlpsolves),
1605 (100*heurdata->nsuccess) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailcutoff) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfaildepth) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailnlperror) / (int)SCIPheurGetNCalls(heur)
1606 );
1607 }
1608 );
1609
1610 return SCIP_OKAY;
1611}
1612
1613
1614/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1615static
1616SCIP_DECL_HEURINITSOL(heurInitsolNlpdiving)
1617{ /*lint --e{715}*/
1618 SCIP_HEURDATA* heurdata;
1619
1620 assert(heur != NULL);
1621
1622 /* get heuristic data */
1623 heurdata = SCIPheurGetData(heur);
1624 assert(heurdata != NULL);
1625
1626 /* store nlpdiving timing */
1627 heurdata->inittiming = SCIPheurGetTimingmask(heur);
1628
1629 /* disable nlpdiving heuristic */
1632
1633 return SCIP_OKAY;
1634}
1635
1636
1637/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1638static
1639SCIP_DECL_HEUREXITSOL(heurExitsolNlpdiving)
1640{ /*lint --e{715}*/
1641 SCIP_HEURDATA* heurdata;
1642
1643 assert(heur != NULL);
1644
1645 /* get heuristic data */
1646 heurdata = SCIPheurGetData(heur);
1647 assert(heurdata != NULL);
1648
1649 /* reset nlpdiving timing */
1650 SCIPheurSetTimingmask(heur, heurdata->inittiming);
1651
1652 return SCIP_OKAY;
1653}
1654
1655
1656/** execution method of primal heuristic */
1657static
1658SCIP_DECL_HEUREXEC(heurExecNlpdiving)
1659{ /*lint --e{715}*/
1660 SCIP_HEURDATA* heurdata;
1661 SCIP_NLPSOLSTAT nlpsolstat;
1662 SCIP_LPSOLSTAT lpsolstat;
1663 SCIP_SOL* nlpstartsol;
1664 SCIP_SOL* bestsol;
1665 SCIP_VAR** nlpcands;
1666 SCIP_VAR** covervars;
1667 SCIP_Real* nlpcandssol;
1668 SCIP_Real* nlpcandsfrac;
1669 SCIP_Real* pseudocandslpsol;
1670 SCIP_Real* pseudocandsnlpsol;
1671 SCIP_HASHMAP* varincover;
1672 SCIP_Real searchubbound;
1673 SCIP_Real searchavgbound;
1674 SCIP_Real searchbound;
1675 SCIP_Real objval;
1676 SCIP_Real oldobjval;
1677 SCIP_Real fixquot;
1678 SCIP_Real bestboundval;
1679 SCIP_Bool bestcandmayround;
1680 SCIP_Bool bestcandroundup;
1681 SCIP_Bool nlperror;
1682 SCIP_Bool lperror;
1683 SCIP_Bool cutoff;
1684 SCIP_Bool backtracked;
1685 SCIP_Bool solvenlp;
1686 SCIP_Bool covercomputed;
1687 SCIP_Bool solvesubmip;
1688 SCIP_Longint ncalls;
1689 SCIP_Longint nsolsfound;
1690 SCIP_VAR* backtrackvar; /* (first) variable to fix differently in backtracking */
1691 SCIP_Real backtrackvarval; /* (fractional) value of backtrack variable */
1692 SCIP_Bool backtrackroundup; /* whether variable should be rounded up in backtracking */
1693 int backtrackdepth; /* depth where to go when backtracking */
1694 int avgnnlpiterations;
1695 int maxnnlpiterations;
1696 int npseudocands;
1697 int nlpbranchcands;
1698 int ncovervars;
1699 int nnlpcands;
1700 int startnnlpcands;
1701 int depth;
1702 int maxdepth;
1703 int maxdivedepth;
1704 int divedepth;
1705 int lastnlpsolvedepth;
1706 int nfeasnlps;
1707 int bestcand;
1708 int c;
1709
1710 assert(scip != NULL);
1711 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1712 assert(result != NULL);
1713 assert(SCIPisNLPConstructed(scip));
1714 assert(SCIPgetNNlpis(scip) >= 1);
1715
1716 *result = SCIP_DIDNOTRUN;
1717
1718 /* do not call heuristic of node was already detected to be infeasible */
1719 if( nodeinfeasible )
1720 return SCIP_OKAY;
1721
1722 /* only call heuristic if the current node will not be cutoff, e.g., due to a (integer and NLP-)feasible LP solution */
1724 return SCIP_OKAY;
1725
1726 /* get heuristic's data */
1727 heurdata = SCIPheurGetData(heur);
1728 assert(heurdata != NULL);
1729
1730 /* do not call heuristic if it barely succeded */
1731 if( (SCIPheurGetNSolsFound(heur) + 1.0) / (SCIP_Real)(SCIPheurGetNCalls(heur) + 1.0) < heurdata->minsuccquot )
1732 return SCIP_OKAY;
1733
1734 *result = SCIP_DELAYED;
1735
1736 /* don't dive two times at the same node */
1738 return SCIP_OKAY;
1739
1740 *result = SCIP_DIDNOTRUN;
1741
1742 /* only try to dive if we are in the correct part of the tree, given by minreldepth and maxreldepth */
1743 depth = SCIPgetDepth(scip);
1744 maxdepth = SCIPgetMaxDepth(scip);
1745 maxdepth = MAX(maxdepth, 30);
1746 if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
1747 return SCIP_OKAY;
1748
1749 /* calculate the maximal number of NLP iterations until heuristic is aborted
1750 * maximal number is maxnlpiterabs plus a success-depending multiplier of maxnlpiterrel
1751 */
1752 ncalls = SCIPheurGetNCalls(heur);
1753 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
1754 maxnnlpiterations = heurdata->maxnlpiterabs;
1755 maxnnlpiterations += (int)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxnlpiterrel);
1756
1757 /* don't try to dive if we took too many NLP iterations during diving */
1758 if( heurdata->nnlpiterations >= maxnnlpiterations )
1759 return SCIP_OKAY;
1760
1761 /* allow at least a bit more than the so far average number of NLP iterations per dive */
1762 avgnnlpiterations = (int)(heurdata->nnlpiterations / MAX(ncalls, 1.0));
1763 maxnnlpiterations = (int)MAX((SCIP_Real) maxnnlpiterations, (SCIP_Real) heurdata->nnlpiterations + 1.2*avgnnlpiterations);
1764
1765 /* don't try to dive if there are no unfixed discrete variables */
1766 SCIP_CALL( SCIPgetPseudoBranchCands(scip, NULL, &npseudocands, NULL) );
1767 if( npseudocands == 0 )
1768 return SCIP_OKAY;
1769
1770 *result = SCIP_DIDNOTFIND;
1771
1772 /* set starting point to lp solution */
1774
1775 /* solve NLP relaxation if not solved already */
1776 nlpsolstat = SCIPgetNLPSolstat(scip);
1777 if( nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE )
1778 {
1779 SCIP_NLPSTATISTICS nlpstatistics;
1780
1782 .iterlimit = maxnnlpiterations - heurdata->nnlpiterations,
1783 .fastfail = heurdata->nlpfastfail ? SCIP_NLPPARAM_FASTFAIL_AGGRESSIVE : SCIP_NLPPARAM_FASTFAIL_CONSERVATIVE) ); /*lint !e666*/
1784 SCIPstatistic( ++heurdata->nnlpsolves );
1785
1786 /* update iteration count */
1788 {
1789 SCIP_CALL( SCIPgetNLPStatistics(scip, &nlpstatistics) );
1790 heurdata->nnlpiterations += nlpstatistics.niterations;
1791 }
1792
1793 nlpsolstat = SCIPgetNLPSolstat(scip);
1794
1795 /* give up, if no feasible solution found */
1796 if( nlpsolstat >= SCIP_NLPSOLSTAT_LOCINFEASIBLE )
1797 {
1798 SCIPdebugMsg(scip, "initial NLP infeasible or not solvable --> stop\n");
1799
1802 heurdata->nfailcutoff++;
1803 else
1804 heurdata->nfailnlperror++;
1805 )
1806
1807 return SCIP_OKAY;
1808 }
1809 }
1810
1811 /* get NLP solution */
1812 SCIP_CALL( SCIPlinkNLPSol(scip, heurdata->sol) );
1813
1814 /* get fractional variables that should be integral */
1815 SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
1816 assert(nnlpcands <= npseudocands);
1817
1818 /* get LP candidates if LP solution is optimal */
1819 lpsolstat = SCIPgetLPSolstat(scip);
1820 if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
1821 nlpbranchcands = SCIPgetNLPBranchCands(scip);
1822 else
1823 nlpbranchcands = 0;
1824
1825 /* don't try to dive, if there are no fractional variables */
1826 if( nnlpcands == 0 )
1827 {
1828 SCIP_Bool success;
1829
1830 /* check, if solution was feasible and good enough
1831 *
1832 * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
1833 * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
1834 * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
1835 */
1836#ifdef SCIP_DEBUG
1837 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
1838#else
1839 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
1840#endif
1841 if( success )
1842 {
1843 SCIPdebugMsg(scip, " -> solution of first NLP was integral, feasible, and good enough\n");
1844 *result = SCIP_FOUNDSOL;
1845 }
1846
1847 return SCIP_OKAY;
1848 }
1849
1850 /* for guided diving: don't dive, if no feasible solutions exist */
1851 if( heurdata->varselrule == 'g' && SCIPgetNSols(scip) == 0 )
1852 return SCIP_OKAY;
1853
1854 /* for guided diving: get best solution that should guide the search; if this solution lives in the original variable space,
1855 * we cannot use it since it might violate the global bounds of the current problem
1856 */
1857 if( heurdata->varselrule == 'g' && SCIPsolIsOriginal(SCIPgetBestSol(scip)) )
1858 return SCIP_OKAY;
1859
1860 nlpstartsol = NULL;
1861 assert(nlpcandsfrac != NULL);
1862 assert(nlpcands != NULL);
1863 assert(nlpcandssol != NULL);
1864
1865 /* save solution of first NLP, if we may use it later */
1866 if( heurdata->nlpstart != 'n' )
1867 {
1868 SCIP_CALL( SCIPcreateNLPSol(scip, &nlpstartsol, heur) );
1869 SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
1870 }
1871
1872 /* calculate the objective search bound */
1873 if( SCIPgetNSolsFound(scip) == 0 )
1874 {
1875 if( heurdata->maxdiveubquotnosol > 0.0 )
1876 searchubbound = SCIPgetLowerbound(scip)
1877 + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1878 else
1879 searchubbound = SCIPinfinity(scip);
1880 if( heurdata->maxdiveavgquotnosol > 0.0 )
1881 searchavgbound = SCIPgetLowerbound(scip)
1882 + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1883 else
1884 searchavgbound = SCIPinfinity(scip);
1885 }
1886 else
1887 {
1888 if( heurdata->maxdiveubquot > 0.0 )
1889 searchubbound = SCIPgetLowerbound(scip)
1890 + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1891 else
1892 searchubbound = SCIPinfinity(scip);
1893 if( heurdata->maxdiveavgquot > 0.0 )
1894 searchavgbound = SCIPgetLowerbound(scip)
1895 + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1896 else
1897 searchavgbound = SCIPinfinity(scip);
1898 }
1899 searchbound = MIN(searchubbound, searchavgbound);
1900 if( SCIPisObjIntegral(scip) )
1901 searchbound = SCIPceil(scip, searchbound);
1902
1903 /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
1905 assert(maxdivedepth >= 0);
1906 maxdivedepth = MIN(maxdivedepth, maxdepth);
1907 maxdivedepth *= 10;
1908
1909 /* initialize local variables */
1910 backtrackdepth = -1;
1911 backtrackvar = NULL;
1912 backtrackvarval = 0.0;
1913 backtrackroundup = FALSE;
1914 bestsol = NULL;
1915 pseudocandsnlpsol = NULL;
1916 pseudocandslpsol = NULL;
1917 covervars = NULL;
1918 covercomputed = FALSE;
1919 varincover = NULL;
1920
1921 /* compute cover, if required */
1922 if( heurdata->prefercover || heurdata->solvesubmip )
1923 {
1924 SCIP_Real timelimit;
1925 SCIP_Real memorylimit;
1926
1927 /* get limits */
1928 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
1929 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
1930 if( !SCIPisInfinity(scip, timelimit) )
1931 timelimit -= SCIPgetSolvingTime(scip);
1932
1933 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1934 if( !SCIPisInfinity(scip, memorylimit) )
1935 {
1936 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1937 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1938 }
1939
1940 /* compute cover; use local bounds; only cover "and" and nonlinear constraints (no bounddisjunction or indicator),
1941 * including convex constraints */
1942 ncovervars = -1;
1944 if( memorylimit > 2.0*SCIPgetMemExternEstim(scip)/1048576.0 && timelimit > 0.05 )
1945 {
1946 SCIP_CALL( SCIPcomputeCoverUndercover(scip, &ncovervars, covervars, timelimit, memorylimit, SCIPinfinity(scip),
1947 FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 'u', &covercomputed) );
1948 }
1949
1950 if( covercomputed )
1951 {
1952 /* a cover can be empty, if the cover computation reveals that all nonlinear constraints are linear w.r.t. current variable fixations */
1953 assert(ncovervars >= 0);
1954
1955 /* create hash map */
1956 SCIP_CALL( SCIPhashmapCreate(&varincover, SCIPblkmem(scip), ncovervars) );
1957
1958 /* process variables in the cover */
1959 for( c = 0; c < ncovervars; c++ )
1960 {
1961 /* insert variable into hash map */
1962 if( SCIPvarGetType(covervars[c]) != SCIP_VARTYPE_CONTINUOUS )
1963 {
1964 assert(!SCIPhashmapExists(varincover, covervars[c]));
1965 SCIP_CALL( SCIPhashmapInsertInt(varincover, covervars[c], c+1) );
1966 }
1967
1968 /* catch bound change events of cover variables */
1969 assert(heurdata->eventhdlr != NULL);
1970 SCIP_CALL( SCIPcatchVarEvent(scip, covervars[c], SCIP_EVENTTYPE_BOUNDCHANGED, heurdata->eventhdlr,
1971 (SCIP_EVENTDATA*) heurdata, NULL) );
1972 assert(!SCIPisFeasEQ(scip, SCIPvarGetLbLocal(covervars[c]), SCIPvarGetUbLocal(covervars[c])));
1973 }
1974 }
1975 }
1976 else
1977 {
1978 covervars = NULL;
1979 ncovervars = 0;
1980 }
1981
1982 /* start diving */
1984
1985 /* enables collection of variable statistics during probing */
1987
1988 /* get NLP objective value*/
1989 objval = SCIPgetNLPObjval(scip);
1990
1991 SCIPdebugMsg(scip, "(node %" SCIP_LONGINT_FORMAT ") executing nlpdiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
1993
1994 /* store a copy of the best solution, if guided diving should be used */
1995 if( heurdata->varselrule == 'g' )
1996 {
1997 assert(SCIPgetNSols(scip) > 0);
1999
2001 }
2002
2003 /* if double diving should be used, create arrays to hold to entire LP and NLP solution */
2004 if( heurdata->varselrule == 'd' )
2005 {
2006 SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandslpsol, npseudocands) );
2007 SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandsnlpsol, npseudocands) );
2008 }
2009
2010 /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
2011 * - if possible, we dive at least with the depth 10
2012 * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
2013 */
2014 nlperror = FALSE;
2015 lperror = FALSE;
2016 cutoff = FALSE;
2017 divedepth = 0;
2018 lastnlpsolvedepth = 0;
2019 backtracked = FALSE; /* whether we are in backtracking */
2020 fixquot = heurdata->fixquot;
2021 nfeasnlps = 1;
2022 startnnlpcands = nnlpcands;
2023 solvesubmip = heurdata->solvesubmip;
2024
2025 while( !nlperror && !cutoff && (nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE || nlpsolstat == SCIP_NLPSOLSTAT_UNKNOWN) && nnlpcands > 0
2026 && (nfeasnlps < heurdata->maxfeasnlps
2027 || nnlpcands <= startnnlpcands - divedepth/2
2028 || (nfeasnlps < maxdivedepth && heurdata->nnlpiterations < maxnnlpiterations && objval < searchbound))
2029 && !SCIPisStopped(scip) )
2030 {
2031 SCIP_VAR* var;
2032 SCIP_Bool updatepscost;
2033
2034 /* open a new probing node if this will not exceed the maximal tree depth, otherwise stop here */
2036 {
2038 divedepth++;
2039 }
2040 else
2041 break;
2042
2043 bestcand = -1;
2044 bestcandmayround = TRUE;
2045 bestcandroundup = FALSE;
2046 bestboundval = SCIP_INVALID;
2047 updatepscost = TRUE;
2048 var = NULL;
2049
2050 /* find best candidate variable */
2051 switch( heurdata->varselrule )
2052 {
2053 case 'c':
2054 SCIP_CALL( chooseCoefVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2055 &bestcand, &bestcandmayround, &bestcandroundup) );
2056 if( bestcand >= 0 )
2057 {
2058 var = nlpcands[bestcand];
2059 bestboundval = nlpcandssol[bestcand];
2060 }
2061 break;
2062 case 'v':
2063 SCIP_CALL( chooseVeclenVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2064 &bestcand, &bestcandmayround, &bestcandroundup) );
2065 if( bestcand >= 0 )
2066 {
2067 var = nlpcands[bestcand];
2068 bestboundval = nlpcandssol[bestcand];
2069 }
2070 break;
2071 case 'p':
2072 SCIP_CALL( choosePscostVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2073 &bestcand, &bestcandmayround, &bestcandroundup) );
2074 if( bestcand >= 0 )
2075 {
2076 var = nlpcands[bestcand];
2077 bestboundval = nlpcandssol[bestcand];
2078 }
2079 break;
2080 case 'g':
2081 SCIP_CALL( chooseGuidedVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, bestsol, varincover, covercomputed,
2082 &bestcand, &bestcandmayround, &bestcandroundup) );
2083 if( bestcand >= 0 )
2084 {
2085 var = nlpcands[bestcand];
2086 bestboundval = nlpcandssol[bestcand];
2087 }
2088 break;
2089 case 'd':
2090 /* double diving only works if we have both relaxations at hand, otherwise we fall back to fractional diving */
2091 if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
2092 {
2093 SCIP_VAR** pseudocands;
2094
2095 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, &npseudocands, NULL) );
2096 assert(backtrackdepth > 0 || nnlpcands <= npseudocands);
2097 assert(SCIPgetNLPBranchCands(scip) <= npseudocands);
2098 SCIP_CALL( SCIPgetSolVals(scip, NULL, npseudocands, pseudocands, pseudocandslpsol) );
2099 SCIP_CALL( SCIPgetSolVals(scip, heurdata->sol, npseudocands, pseudocands, pseudocandsnlpsol) );
2100 SCIP_CALL( chooseDoubleVar(scip, heurdata, pseudocands, pseudocandsnlpsol, pseudocandslpsol, npseudocands,
2101 varincover, covercomputed, &bestcand, &bestboundval, &bestcandmayround, &bestcandroundup) );
2102 if( bestcand >= 0 )
2103 var = pseudocands[bestcand];
2104 break;
2105 }
2106 else
2107 updatepscost = FALSE;
2108 /*lint -fallthrough*/
2109 case 'f':
2110 SCIP_CALL( chooseFracVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2111 &bestcand, &bestcandmayround, &bestcandroundup) );
2112 if( bestcand >= 0 )
2113 {
2114 var = nlpcands[bestcand];
2115 bestboundval = nlpcandssol[bestcand];
2116 }
2117 break;
2118 default:
2119 SCIPerrorMessage("invalid variable selection rule\n");
2120 return SCIP_INVALIDDATA;
2121 }
2122
2123 /* if all candidates are roundable, try to round the solution
2124 * if var == NULL (i.e., bestcand == -1), then all solution candidates are outside bounds
2125 * this should only happen if they are slightly outside bounds (i.e., still within feastol, relative tolerance),
2126 * but far enough out to be considered as fractional (within feastol, but using absolute tolerance)
2127 * in this case, we also try our luck with rounding
2128 */
2129 if( (var == NULL || bestcandmayround) && backtrackdepth == -1 )
2130 {
2131 SCIP_Bool success;
2132
2133 /* create solution from diving NLP and try to round it */
2134 SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
2135
2136 if( success )
2137 {
2138 SCIPdebugMsg(scip, "nlpdiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2139
2140 /* try to add solution to SCIP */
2141#ifdef SCIP_DEBUG
2142 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, FALSE, TRUE, &success) );
2143#else
2144 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
2145#endif
2146
2147 /* check, if solution was feasible and good enough */
2148 if( success )
2149 {
2150 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2151 *result = SCIP_FOUNDSOL;
2152 }
2153 }
2154 }
2155
2156 /* if all variables have been found to be essentially integral (even though there is some numerical doubt, see comment above), then stop */
2157 if( var == NULL )
2158 break;
2159
2160 do
2161 {
2162 SCIP_Real frac;
2163 frac = SCIP_INVALID;
2164
2165 if( backtracked && backtrackdepth > 0 )
2166 {
2167 assert(backtrackvar != NULL);
2168
2169 /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2170 * occured or variable was fixed by propagation while backtracking => Abort diving!
2171 */
2172 if( SCIPvarGetLbLocal(backtrackvar) >= SCIPvarGetUbLocal(backtrackvar) - 0.5 )
2173 {
2174 SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2175 SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2176 cutoff = TRUE;
2177 break;
2178 }
2179 if( SCIPisFeasLT(scip, backtrackvarval, SCIPvarGetLbLocal(backtrackvar)) || SCIPisFeasGT(scip, backtrackvarval, SCIPvarGetUbLocal(backtrackvar)) )
2180 {
2181 SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2182 SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2183 assert(backtracked);
2184 break;
2185 }
2186
2187 /* round backtrack variable up or down */
2188 if( backtrackroundup )
2189 {
2190 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2191 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2192 SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2193 SCIPfeasCeil(scip, backtrackvarval), SCIPvarGetUbLocal(backtrackvar));
2194 SCIP_CALL( SCIPchgVarLbProbing(scip, backtrackvar, SCIPfeasCeil(scip, backtrackvarval)) );
2195 }
2196 else
2197 {
2198 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2199 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2200 SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2201 SCIPvarGetLbLocal(backtrackvar), SCIPfeasFloor(scip, backtrackvarval));
2202 SCIP_CALL( SCIPchgVarUbProbing(scip, backtrackvar, SCIPfeasFloor(scip, backtrackvarval)) );
2203 }
2204
2205 /* forget about backtrack variable */
2206 backtrackdepth = -1;
2207
2208 /* for pseudo cost computation */
2209 bestcandroundup = backtrackroundup;
2210 frac = SCIPfrac(scip, backtrackvarval);
2211 var = backtrackvar;
2212 }
2213 else
2214 {
2215 assert(var != NULL);
2216
2217 /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2218 * occured or variable was fixed by propagation while backtracking => Abort diving!
2219 */
2220 if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
2221 {
2222 SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2223 SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), bestboundval);
2224 cutoff = TRUE;
2225 break;
2226 }
2227 if( SCIPisFeasLT(scip, bestboundval, SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, bestboundval, SCIPvarGetUbLocal(var)) )
2228 {
2229 SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2230 SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), bestboundval);
2231 assert(backtracked);
2232 break;
2233 }
2234
2235 /* apply rounding of best candidate */
2236 if( bestcandroundup == !backtracked )
2237 {
2238 /* round variable up */
2239 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2240 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2241 SCIPvarGetName(var), bestcandmayround,
2242 bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2243 SCIPfeasCeil(scip, bestboundval), SCIPvarGetUbLocal(var));
2244 SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, bestboundval)) );
2245
2246 /* remember variable for backtracking, if we have none yet (e.g., we are just after NLP solve) or we are half way to the next NLP solve */
2247 if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2248 {
2249 backtrackdepth = divedepth;
2250 backtrackvar = var;
2251 backtrackvarval = bestboundval;
2252 backtrackroundup = FALSE;
2253 }
2254 }
2255 else
2256 {
2257 /* round variable down */
2258 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2259 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2260 SCIPvarGetName(var), bestcandmayround,
2261 bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2262 SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, bestboundval));
2263 SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, bestboundval)) );
2264
2265 /* remember variable for backtracking, if we have none yet (e.g., we are just after NLP solve) or we are half way to the next NLP solve */
2266 if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2267 {
2268 backtrackdepth = divedepth;
2269 backtrackvar = var;
2270 backtrackvarval = bestboundval;
2271 backtrackroundup = TRUE;
2272 }
2273 }
2274
2275 /* for pseudo-cost computation */
2276 if( updatepscost && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
2277 {
2278 if( heurdata->varselrule == 'd' )
2279 {
2280 assert(pseudocandsnlpsol != NULL);
2281 assert(0 <= bestcand && bestcand < npseudocands);
2282 frac = SCIPfrac(scip, pseudocandsnlpsol[bestcand]);
2283 }
2284 else
2285 frac = nlpcandsfrac[bestcand];
2286 }
2287 }
2288
2289 /* apply domain propagation */
2290 SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
2291 if( cutoff )
2292 {
2293 SCIPdebugMsg(scip, " *** cutoff detected in propagation at level %d\n", SCIPgetProbingDepth(scip));
2294 }
2295
2296 /* if all variables in the cover are fixed or there is no fractional variable in the cover,
2297 * then solve a sub-MIP
2298 */
2299 if( !cutoff && solvesubmip && covercomputed &&
2300 (heurdata->nfixedcovervars == ncovervars ||
2301 (heurdata->nfixedcovervars >= (ncovervars+1)/2 && !SCIPhashmapExists(varincover, var))) )
2302 {
2303 int probingdepth;
2304
2305 solvesubmip = FALSE;
2306 probingdepth = SCIPgetProbingDepth(scip);
2307 assert(probingdepth >= 1);
2308 assert(covervars != NULL);
2309
2310 if( heurdata->nfixedcovervars != ncovervars )
2311 {
2312 /* fix all remaining cover variables */
2313 for( c = 0; c < ncovervars && !cutoff ; c++ )
2314 {
2315 SCIP_Real lb;
2316 SCIP_Real ub;
2317 lb = SCIPvarGetLbLocal(covervars[c]);
2318 ub = SCIPvarGetUbLocal(covervars[c]);
2319 if( !SCIPisFeasEQ(scip, lb, ub) )
2320 {
2321 SCIP_Real nlpsolval;
2322
2323 /* adopt lpsolval w.r.t. intermediate bound changes by propagation */
2324 nlpsolval = SCIPvarGetNLPSol(covervars[c]);
2325 nlpsolval = MIN(nlpsolval,ub);
2326 nlpsolval = MAX(nlpsolval,lb);
2327 assert(SCIPvarGetType(covervars[c]) == SCIP_VARTYPE_CONTINUOUS || SCIPisFeasIntegral(scip, nlpsolval));
2328
2329 /* open a new probing node if this will not exceed the maximal tree depth,
2330 * otherwise fix all the remaining variables at the same probing node
2331 * @todo do we need a new probing node for each fixing? if one of these fixings leads to a cutoff
2332 * we backtrack to the last probing node before we started to fix the covervars (and we do
2333 * not solve the probing LP). thus, it would be less work load in SCIPendProbing
2334 * and SCIPbacktrackProbing.
2335 */
2337 {
2339 }
2340
2341 /* fix and propagate */
2342 assert(SCIPisLbBetter(scip, nlpsolval, lb, ub) || SCIPisUbBetter(scip, nlpsolval, lb, ub));
2343
2344 if( SCIPisLbBetter(scip, nlpsolval, lb, ub) )
2345 {
2346 SCIP_CALL( SCIPchgVarLbProbing(scip, covervars[c], nlpsolval) );
2347 /* if covervar was continuous implied integral and fractional, then nlpsolval may be below
2348 * lower bound now, so adjust to new bound
2349 */
2350 nlpsolval = MAX(nlpsolval, SCIPvarGetLbLocal(covervars[c])); /*lint !e666*/
2351 }
2352 if( SCIPisUbBetter(scip, nlpsolval, lb, ub) )
2353 {
2354 SCIP_CALL( SCIPchgVarUbProbing(scip, covervars[c], nlpsolval) );
2355 }
2356
2357 SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
2358 }
2359 }
2360 }
2361
2362 /* solve sub-MIP or return to standard diving */
2363 if( cutoff )
2364 {
2365 SCIP_CALL( SCIPbacktrackProbing(scip, probingdepth) );
2366 }
2367 else
2368 {
2369 SCIP_Bool success;
2370 success = FALSE;
2371
2372 SCIP_CALL( solveSubMIP(scip, heur, covervars, ncovervars, &success) );
2373 if( success )
2374 *result = SCIP_FOUNDSOL;
2375 backtracked = TRUE; /* to avoid backtracking */
2376 nnlpcands = 0; /* to force termination */
2377 cutoff = TRUE;
2378 }
2379 }
2380
2381 /* resolve the diving LP */
2382 if( !cutoff && !lperror && (heurdata->lp || heurdata->varselrule == 'd')
2384 {
2385 SCIP_CALL( SCIPsolveProbingLP(scip, 100, &lperror, &cutoff) );
2386
2387 /* get LP solution status, objective value, and fractional variables, that should be integral */
2388 lpsolstat = SCIPgetLPSolstat(scip);
2389 assert(cutoff || (lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT && lpsolstat != SCIP_LPSOLSTAT_INFEASIBLE &&
2391
2392 if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
2393 {
2394 nlpbranchcands = SCIPgetNLPBranchCands(scip);
2395
2396 /* get new objective value */
2397 oldobjval = objval;
2398 objval = SCIPgetLPObjval(scip);
2399
2400 /* update pseudo cost values */
2401 if( updatepscost && SCIPisGT(scip, objval, oldobjval) )
2402 {
2403 assert(frac != SCIP_INVALID); /*lint !e777*/
2404 if( bestcandroundup )
2405 {
2406 SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 1.0-frac, objval - oldobjval, 1.0) );
2407 }
2408 else
2409 {
2410 SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 0.0-frac, objval - oldobjval, 1.0) );
2411 }
2412 }
2413 }
2414 else
2415 {
2416 nlpbranchcands = 0;
2417 }
2418
2419 if( cutoff )
2420 {
2421 SCIPdebugMsg(scip, " *** cutoff detected in LP solving at level %d, lpsolstat = %d\n", SCIPgetProbingDepth(scip), lpsolstat);
2422 }
2423 }
2424 else
2425 lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2426
2427 /* check whether we want to solve the NLP, which is the case if
2428 * - we are in backtracking, or
2429 * - we have (actively) fixed/rounded fixquot*nnlpcands variables
2430 * - all fractional variables were rounded/fixed (due to fixing and domain propagation)
2431 */
2432 solvenlp = backtracked;
2433 if( !solvenlp && !cutoff )
2434 {
2435 solvenlp = (lastnlpsolvedepth < divedepth - fixquot * nnlpcands);
2436 if( !solvenlp )
2437 {
2438 /* check if fractional NLP variables are left (some may have been fixed by propagation) */
2439 for( c = 0; c < nnlpcands; ++c )
2440 {
2441 var = nlpcands[c];
2442 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
2443 continue;
2444 else
2445 break;
2446 }
2447 if( c == nnlpcands )
2448 solvenlp = TRUE;
2449 }
2450 }
2451
2452 nlpsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2453
2454 /* resolve the diving NLP */
2455 if( !cutoff && solvenlp )
2456 {
2457 SCIP_NLPTERMSTAT termstat;
2458 SCIP_NLPSTATISTICS nlpstatistics;
2459
2460 /* set start solution, if we are in backtracking (previous NLP solve was infeasible) */
2461 if( heurdata->nlpstart != 'n' && backtracked )
2462 {
2463 assert(nlpstartsol != NULL);
2464
2465 SCIPdebugMsg(scip, "setting NLP initial guess\n");
2466
2467 SCIP_CALL( SCIPsetNLPInitialGuessSol(scip, nlpstartsol) );
2468 }
2469
2470 /* solve NLP; allow at least MINNLPITER many iterations */
2472 .iterlimit = MAX(maxnnlpiterations - heurdata->nnlpiterations, MINNLPITER)) ); /*lint !e666*/
2473 SCIPstatistic( ++heurdata->nnlpsolves );
2474
2475 termstat = SCIPgetNLPTermstat(scip);
2476 if( termstat >= SCIP_NLPTERMSTAT_NUMERICERROR )
2477 {
2478 if( termstat >= SCIP_NLPTERMSTAT_LICENSEERROR )
2479 {
2481 "Error while solving NLP in nlpdiving heuristic; NLP solve terminated with code <%d>\n", termstat);
2482 }
2483 nlperror = TRUE;
2484 break;
2485 }
2486
2487 /* update iteration count */
2488 SCIP_CALL( SCIPgetNLPStatistics(scip, &nlpstatistics) );
2489 heurdata->nnlpiterations += nlpstatistics.niterations;
2490
2491 /* get NLP solution status, objective value, and fractional variables, that should be integral */
2492 nlpsolstat = SCIPgetNLPSolstat(scip);
2493 cutoff = (nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE);
2494
2495 if( cutoff )
2496 {
2497 SCIPdebugMsg(scip, " *** cutoff detected in NLP solving at level %d, nlpsolstat: %d\n", SCIPgetProbingDepth(scip), nlpsolstat);
2498 }
2499 else
2500 {
2501 SCIP_CALL( SCIPlinkNLPSol(scip, heurdata->sol) );
2502
2503 /* remember that we have solve NLP on this depth successfully */
2504 lastnlpsolvedepth = divedepth;
2505 /* forget previous backtrack variable, we will never go back to a depth before the current one */
2506 backtrackdepth = -1;
2507 /* store NLP solution for warmstarting, if nlpstart is 'f' */
2508 if( heurdata->nlpstart == 'f' )
2509 {
2510 assert(nlpstartsol != NULL);
2511
2512 /* copy NLP solution values into nlpstartsol, is there a better way to do this???? */
2513 SCIP_CALL( SCIPlinkNLPSol(scip, nlpstartsol) );
2514 SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
2515 }
2516 /* increase counter on number of NLP solves with feasible solution */
2517 ++nfeasnlps;
2518 }
2519 }
2520
2521 /* perform backtracking if a cutoff was detected */
2522 if( cutoff && !backtracked && heurdata->backtrack )
2523 {
2524 if( backtrackdepth == -1 )
2525 {
2526 /* backtrack one step */
2527 SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking one step\n", SCIPgetProbingDepth(scip));
2529
2530 /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2532
2534 }
2535 else
2536 {
2537 /* if we have a stored a depth for backtracking, go there */
2538 SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking to depth %d\n", SCIPgetProbingDepth(scip), backtrackdepth);
2539 SCIP_CALL( SCIPbacktrackProbing(scip, backtrackdepth-1) );
2540
2541 /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2543
2545 divedepth = backtrackdepth;
2546
2547 /* do not update pseudocosts if backtracking by more than one level */
2548 updatepscost = FALSE;
2549
2550 /* in case, we are feasible after backtracking, fix less variables at once in continuing diving
2551 * @todo should we remember the fixquot in heurdata for the next run?
2552 */
2553 fixquot *= 0.5;
2554 }
2555 /* remember that we are backtracking now */
2556 backtracked = TRUE;
2557 }
2558 else
2559 backtracked = FALSE;
2560 }
2561 while( backtracked );
2562
2563 if( !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2564 {
2565 /* get new fractional variables */
2566 SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
2567 }
2568 SCIPdebugMsg(scip, " -> nlpsolstat=%d, objval=%g/%g, nfrac nlp=%d lp=%d\n", nlpsolstat, objval, searchbound, nnlpcands, nlpbranchcands);
2569 }
2570
2571 /*lint --e{774}*/
2572 SCIPdebugMsg(scip, "NLP nlpdiving ABORT due to ");
2573 if( nlperror || (nlpsolstat > SCIP_NLPSOLSTAT_LOCINFEASIBLE && nlpsolstat != SCIP_NLPSOLSTAT_UNKNOWN) )
2574 {
2575 SCIPdebugMsgPrint(scip, "NLP bad status - nlperror: %ud nlpsolstat: %d \n", nlperror, nlpsolstat);
2576 SCIPstatistic( heurdata->nfailnlperror++ );
2577 }
2578 else if( SCIPisStopped(scip) || cutoff )
2579 {
2580 SCIPdebugMsgPrint(scip, "LIMIT hit - stop: %ud cutoff: %ud \n", SCIPisStopped(scip), cutoff);
2581 SCIPstatistic( heurdata->nfailcutoff++ );
2582 }
2583 else if(! (divedepth < 10
2584 || nnlpcands <= startnnlpcands - divedepth/2
2585 || (divedepth < maxdivedepth && heurdata->nnlpiterations < maxnnlpiterations && objval < searchbound) ) )
2586 {
2587 SCIPdebugMsgPrint(scip, "TOO DEEP - divedepth: %4d cands halfed: %d ltmaxdepth: %d ltmaxiter: %d bound: %d\n", divedepth,
2588 (nnlpcands > startnnlpcands - divedepth/2), (divedepth >= maxdivedepth), (heurdata->nnlpiterations >= maxnnlpiterations),
2589 (objval >= searchbound));
2590 SCIPstatistic( heurdata->nfaildepth++ );
2591 }
2592 else if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2593 {
2594 SCIPdebugMsgPrint(scip, "SUCCESS\n");
2595 }
2596 else
2597 {
2598 SCIPdebugMsgPrint(scip, "UNKNOWN, very mysterical reason\n"); /* see also special case var == NULL (bestcand == -1) after choose*Var above */
2599 }
2600
2601 /* check if a solution has been found */
2602 if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2603 {
2604 SCIP_Bool success;
2605
2606 /* create solution from diving NLP */
2607 SCIPdebugMsg(scip, "nlpdiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2608
2609 /* try to add solution to SCIP
2610 *
2611 * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
2612 * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
2613 * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
2614 */
2615#ifdef SCIP_DEBUG
2616 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
2617#else
2618 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
2619#endif
2620
2621 /* check, if solution was feasible and good enough */
2622 if( success )
2623 {
2624 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2625 *result = SCIP_FOUNDSOL;
2626 }
2627 else
2628 {
2629 SCIPdebugMsg(scip, " -> solution was not accepted\n");
2630 }
2631 }
2632
2633 /* end diving */
2635
2636 /* free hash map and drop variable bound change events */
2637 if( covercomputed )
2638 {
2639 assert(heurdata->eventhdlr != NULL);
2640 assert(heurdata->nfixedcovervars >= 0); /* variables might have been globally fixed in propagation */
2641 assert(varincover != NULL);
2642 assert(covervars != NULL);
2643
2644 SCIPhashmapFree(&varincover);
2645
2646 /* drop bound change events of cover variables */
2647 for( c = 0; c < ncovervars; c++ )
2648 {
2649 SCIP_CALL( SCIPdropVarEvent(scip, covervars[c], SCIP_EVENTTYPE_BOUNDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, -1) );
2650 }
2651 }
2652 else
2653 assert(varincover == NULL);
2654
2655 /* free NLP start solution */
2656 if( nlpstartsol != NULL )
2657 {
2658 SCIP_CALL( SCIPfreeSol(scip, &nlpstartsol) );
2659 }
2660
2661 /* free copied best solution */
2662 if( heurdata->varselrule == 'g' )
2663 {
2664 assert(bestsol != NULL);
2665 SCIP_CALL( SCIPfreeSol(scip, &bestsol) );
2666 }
2667 else
2668 assert(bestsol == NULL);
2669
2670 /* free arrays of LP and NLP solution */
2671 if( heurdata->varselrule == 'd' )
2672 {
2673 assert(pseudocandsnlpsol != NULL);
2674 assert(pseudocandsnlpsol != NULL);
2675 SCIPfreeBufferArray(scip, &pseudocandsnlpsol);
2676 SCIPfreeBufferArray(scip, &pseudocandslpsol);
2677 }
2678 else
2679 {
2680 assert(pseudocandsnlpsol == NULL);
2681 assert(pseudocandsnlpsol == NULL);
2682 }
2683
2684 /* free array of cover variables */
2685 if( heurdata->prefercover || heurdata->solvesubmip )
2686 {
2687 assert(covervars != NULL || !covercomputed);
2688 if( covervars != NULL )
2689 SCIPfreeBufferArray(scip, &covervars);
2690 }
2691 else
2692 assert(covervars == NULL);
2693
2694 if( *result == SCIP_FOUNDSOL )
2695 heurdata->nsuccess++;
2696
2697 SCIPdebugMsg(scip, "nlpdiving heuristic finished\n");
2698
2699 return SCIP_OKAY; /*lint !e438*/
2700}
2701
2702
2703/*
2704 * heuristic specific interface methods
2705 */
2706
2707/** creates the nlpdiving heuristic and includes it in SCIP */
2709 SCIP* scip /**< SCIP data structure */
2710 )
2711{
2712 SCIP_HEURDATA* heurdata;
2713 SCIP_HEUR* heur = NULL;
2714
2715 /* create heuristic data */
2716 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
2717 heurdata->inittiming = HEUR_TIMING;
2718
2719 /* include heuristic */
2721 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecNlpdiving, heurdata) );
2722
2723 assert(heur != NULL);
2724 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyNlpdiving) );
2725 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeNlpdiving) );
2726 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitNlpdiving) );
2727 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitNlpdiving) );
2728 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolNlpdiving) );
2729 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolNlpdiving) );
2730
2731 /* get event handler for bound change events */
2732 heurdata->eventhdlr = NULL;
2733 /* create event handler for bound change events */
2735 eventExecNlpdiving, NULL) );
2736 if ( heurdata->eventhdlr == NULL )
2737 {
2738 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
2739 return SCIP_PLUGINNOTFOUND;
2740 }
2741
2742 /* nlpdiving heuristic parameters */
2744 "heuristics/" HEUR_NAME "/minreldepth",
2745 "minimal relative depth to start diving",
2746 &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
2748 "heuristics/" HEUR_NAME "/maxreldepth",
2749 "maximal relative depth to start diving",
2750 &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
2752 "heuristics/" HEUR_NAME "/maxnlpiterabs",
2753 "minimial absolute number of allowed NLP iterations",
2754 &heurdata->maxnlpiterabs, FALSE, DEFAULT_MAXNLPITERABS, 0, INT_MAX, NULL, NULL) );
2756 "heuristics/" HEUR_NAME "/maxnlpiterrel",
2757 "additional allowed number of NLP iterations relative to successfully found solutions",
2758 &heurdata->maxnlpiterrel, FALSE, DEFAULT_MAXNLPITERREL, 0, INT_MAX, NULL, NULL) );
2760 "heuristics/" HEUR_NAME "/maxdiveubquot",
2761 "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
2762 &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
2764 "heuristics/" HEUR_NAME "/maxdiveavgquot",
2765 "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
2766 &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2768 "heuristics/" HEUR_NAME "/maxdiveubquotnosol",
2769 "maximal UBQUOT when no solution was found yet (0.0: no limit)",
2770 &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
2772 "heuristics/" HEUR_NAME "/maxdiveavgquotnosol",
2773 "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
2774 &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2776 "heuristics/" HEUR_NAME "/maxfeasnlps",
2777 "maximal number of NLPs with feasible solution to solve during one dive",
2778 &heurdata->maxfeasnlps, FALSE, DEFAULT_MAXFEASNLPS, 1, INT_MAX, NULL, NULL) );
2780 "heuristics/" HEUR_NAME "/backtrack",
2781 "use one level of backtracking if infeasibility is encountered?",
2782 &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
2784 "heuristics/" HEUR_NAME "/lp",
2785 "should the LP relaxation be solved before the NLP relaxation?",
2786 &heurdata->lp, TRUE, DEFAULT_LP, NULL, NULL) );
2788 "heuristics/" HEUR_NAME "/preferlpfracs",
2789 "prefer variables that are also fractional in LP solution?",
2790 &heurdata->preferlpfracs, TRUE, DEFAULT_PREFERLPFRACS, NULL, NULL) );
2792 "heuristics/" HEUR_NAME "/minsuccquot",
2793 "heuristic will not run if less then this percentage of calls succeeded (0.0: no limit)",
2794 &heurdata->minsuccquot, FALSE, DEFAULT_MINSUCCQUOT, 0.0, 1.0, NULL, NULL) );
2796 "heuristics/" HEUR_NAME "/fixquot",
2797 "percentage of fractional variables that should be fixed before the next NLP solve",
2798 &heurdata->fixquot, FALSE, DEFAULT_FIXQUOT, 0.0, 1.0, NULL, NULL) );
2800 "heuristics/" HEUR_NAME "/prefercover",
2801 "should variables in a minimal cover be preferred?",
2802 &heurdata->prefercover, FALSE, DEFAULT_PREFERCOVER, NULL, NULL) );
2804 "heuristics/" HEUR_NAME "/solvesubmip",
2805 "should a sub-MIP be solved if all cover variables are fixed?",
2806 &heurdata->solvesubmip, FALSE, DEFAULT_SOLVESUBMIP, NULL, NULL) );
2808 "heuristics/" HEUR_NAME "/nlpfastfail",
2809 "should the NLP solver stop early if it converges slow?",
2810 &heurdata->nlpfastfail, FALSE, DEFAULT_NLPFASTFAIL, NULL, NULL) );
2812 "heuristics/" HEUR_NAME "/nlpstart",
2813 "which point should be used as starting point for the NLP solver? ('n'one, last 'f'easible, from dive's'tart)",
2814 &heurdata->nlpstart, TRUE, DEFAULT_NLPSTART, "fns", NULL, NULL) );
2816 "heuristics/" HEUR_NAME "/varselrule",
2817 "which variable selection should be used? ('f'ractionality, 'c'oefficient, 'p'seudocost, 'g'uided, 'd'ouble, 'v'eclen)",
2818 &heurdata->varselrule, FALSE, DEFAULT_VARSELRULE, "fcpgdv", NULL, NULL) );
2819
2820 return SCIP_OKAY;
2821}
#define NULL
Definition: def.h:248
#define SCIP_PROBINGSCORE_PENALTYRATIO
Definition: def.h:303
#define SCIP_Longint
Definition: def.h:141
#define SCIP_MAXTREEDEPTH
Definition: def.h:297
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define ABS(x)
Definition: def.h:216
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip_copy.c:2961
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip_copy.c:3249
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:3292
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:402
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:370
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1242
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip_prob.c:1661
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
int SCIPgetNContImplVars(SCIP *scip)
Definition: scip_prob.c:2522
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip_prob.c:1801
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3179
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:4178
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPcomputeCoverUndercover(SCIP *scip, int *coversize, SCIP_VAR **cover, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Real objlimit, SCIP_Bool globalbounds, SCIP_Bool onlyconvexify, SCIP_Bool coverand, SCIP_Bool coverbd, SCIP_Bool coverind, SCIP_Bool covernl, char coveringobj, SCIP_Bool *success)
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip_param.c:219
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 SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:545
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:487
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip_param.c:904
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:307
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:956
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip_param.c:661
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 SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:429
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:985
SCIP_RETCODE SCIPincludeHeurNlpdiving(SCIP *scip)
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:304
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:436
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
Definition: scip_branch.c:741
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:413
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1391
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1217
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1415
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip_heur.c:247
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:167
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip_heur.c:122
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:183
SCIP_HEURTIMING SCIPheurGetTimingmask(SCIP_HEUR *heur)
Definition: heur.c:1497
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1603
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:215
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1613
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1507
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1593
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:231
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
SCIP_Real SCIPheurGetTime(SCIP_HEUR *heur)
Definition: heur.c:1655
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1378
SCIP_Longint SCIPgetLastDivenode(SCIP *scip)
Definition: scip_lp.c:2710
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:174
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:253
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip_lp.c:673
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip_mem.c:126
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip_mem.c:100
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#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
int SCIPgetNNlpis(SCIP *scip)
Definition: scip_nlpi.c:205
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip_nlp.c:574
#define SCIPsolveNLP(...)
Definition: scip_nlp.h:361
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition: scip_nlp.c:645
SCIP_RETCODE SCIPgetNLPFracVars(SCIP *scip, SCIP_VAR ***fracvars, SCIP_Real **fracvarssol, SCIP_Real **fracvarsfrac, int *nfracvars, int *npriofracvars)
Definition: scip_nlp.c:696
SCIP_RETCODE SCIPsetNLPInitialGuessSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_nlp.c:501
SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
Definition: scip_nlp.c:596
SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
Definition: scip_nlp.c:621
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip_nodesel.c:242
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip_probing.c:199
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_probing.c:346
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_probing.c:302
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip_probing.c:581
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip_probing.c:226
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip_probing.c:120
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip_probing.c:166
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip_probing.c:825
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip_probing.c:261
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip_sol.c:884
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:664
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2882
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1506
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:4140
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1846
SCIP_RETCODE SCIPlinkNLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1353
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip_sol.c:3123
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1662
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip_sol.c:2931
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip_sol.c:4012
SCIP_RETCODE SCIPtrySolFree(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:4109
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 SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip_sol.c:2132
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2635
SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
int SCIPgetMaxDepth(SCIP *scip)
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Real SCIPgetAvgLowerbound(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:378
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
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_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPsumepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:4484
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition: var.c:23498
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:4473
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:19115
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip_var.c:11188
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip_var.c:11122
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:24691
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
void SCIPenableVarHistory(SCIP *scip)
Definition: scip_var.c:11083
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10223
#define DEFAULT_MAXNLPITERREL
static SCIP_RETCODE chooseCoefVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
#define DEFAULT_MAXDIVEUBQUOT
static SCIP_DECL_HEUREXITSOL(heurExitsolNlpdiving)
static SCIP_RETCODE chooseGuidedVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_SOL *bestsol, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
static SCIP_DECL_HEURINIT(heurInitNlpdiving)
static void calcPscostQuot(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real primsol, SCIP_Real frac, int rounddir, SCIP_Real *pscostquot, SCIP_Bool *roundup, SCIP_Bool prefvar)
static SCIP_DECL_HEURFREE(heurFreeNlpdiving)
static SCIP_RETCODE chooseFracVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
static SCIP_RETCODE doSolveSubMIP(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **covervars, int ncovervars, SCIP_Bool *success)
#define MINNLPITER
#define HEUR_TIMING
static SCIP_RETCODE getNLPFracVars(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR ***nlpcands, SCIP_Real **nlpcandssol, SCIP_Real **nlpcandsfrac, int *nnlpcands)
#define HEUR_FREQOFS
#define HEUR_DESC
#define DEFAULT_PREFERCOVER
static SCIP_RETCODE chooseDoubleVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **pseudocands, SCIP_Real *pseudocandsnlpsol, SCIP_Real *pseudocandslpsol, int npseudocands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Real *bestboundval, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
static SCIP_DECL_HEURCOPY(heurCopyNlpdiving)
static SCIP_DECL_EVENTEXEC(eventExecNlpdiving)
#define DEFAULT_MAXDIVEAVGQUOT
#define DEFAULT_PREFERLPFRACS
static SCIP_RETCODE chooseVeclenVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
#define DEFAULT_MAXNLPITERABS
static SCIP_DECL_HEUREXEC(heurExecNlpdiving)
#define DEFAULT_BACKTRACK
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define DEFAULT_MAXRELDEPTH
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HASHMAP *varmap, SCIP_SOL *subsol, SCIP_Bool *success)
static SCIP_RETCODE choosePscostVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
#define HEUR_NAME
#define DEFAULT_LP
#define DEFAULT_SOLVESUBMIP
static SCIP_RETCODE solveSubMIP(SCIP *scip, SCIP_HEUR *heur, SCIP_VAR **covervars, int ncovervars, SCIP_Bool *success)
#define DEFAULT_VARSELRULE
#define DEFAULT_RANDSEED
#define DEFAULT_FIXQUOT
#define DEFAULT_NLPSTART
#define DEFAULT_NLPFASTFAIL
static SCIP_DECL_HEUREXIT(heurExitNlpdiving)
#define DEFAULT_MAXFEASNLPS
#define EVENTHDLR_DESC
#define DEFAULT_MINSUCCQUOT
#define HEUR_FREQ
#define DEFAULT_MINRELDEPTH
static SCIP_DECL_HEURINITSOL(heurInitsolNlpdiving)
#define HEUR_USESSUBSCIP
#define EVENTHDLR_NAME
NLP diving heuristic that chooses fixings w.r.t. the fractionalities.
NLP local search primal heuristic using sub-SCIPs.
Undercover primal heuristic for MINLPs.
memory allocation routines
public methods for managing events
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPstatisticMessage
Definition: pub_message.h:123
#define SCIPstatistic(x)
Definition: pub_message.h:120
public data structures and miscellaneous methods
public methods for primal CIP solutions
public methods for problem variables
public methods for branching rule plugins and branching
public methods for problem copies
public methods for event handler plugins and event handlers
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 nonlinear relaxation
public methods for NLPI solver interfaces
public methods for node selector plugins
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 random numbers
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for timing
public methods for the branch-and-bound tree
public methods for SCIP variables
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:127
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:78
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:123
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:156
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:80
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:52
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:43
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:45
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:47
@ SCIP_VERBLEVEL_MINIMAL
Definition: type_message.h:59
@ SCIP_NLPPARAM_FASTFAIL_CONSERVATIVE
Definition: type_nlpi.h:59
@ SCIP_NLPPARAM_FASTFAIL_AGGRESSIVE
Definition: type_nlpi.h:60
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:168
@ SCIP_NLPTERMSTAT_NUMERICERROR
Definition: type_nlpi.h:178
@ SCIP_NLPTERMSTAT_LICENSEERROR
Definition: type_nlpi.h:181
@ SCIP_NLPSOLSTAT_LOCINFEASIBLE
Definition: type_nlpi.h:163
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition: type_nlpi.h:162
@ SCIP_NLPSOLSTAT_UNKNOWN
Definition: type_nlpi.h:166
enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
Definition: type_nlpi.h:184
@ SCIP_PARAMSETTING_OFF
Definition: type_paramset.h:63
@ SCIP_PARAMSETTING_FAST
Definition: type_paramset.h:62
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DELAYED
Definition: type_result.h:43
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_FOUNDSOL
Definition: type_result.h:56
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
unsigned int SCIP_HEURTIMING
Definition: type_timing.h:103
#define SCIP_HEURTIMING_NONE
Definition: type_timing.h:79
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141