SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_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
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]))
207
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 {
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;
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);
276
279 bestobjgain = SCIPinfinity(scip);
280 bestfrac = SCIP_INVALID;
281
282 for( c = 0; c < nnlpcands; ++c )
283 {
284 SCIP_VAR* var;
290 SCIP_Real objgain;
291
292 var = nlpcands[c];
293
296 frac = nlpcandsfrac[c];
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 */
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
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 */
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;
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 */
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;
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);
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
458 SCIP_Real objdelta;
460 SCIP_Real score;
461
462 int nlocks;
463
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];
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;
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{
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);
545
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
564
565 var = nlpcands[c];
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 */
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
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 */
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;
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 */
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;
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);
718 assert(roundup != NULL);
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{
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);
809
812 bestpscostquot = -1.0;
813
814 for( c = 0; c < nnlpcands; ++c )
815 {
816 SCIP_VAR* var;
818
822 SCIP_Bool prefvar;
825
826 var = nlpcands[c];
829 primsol = nlpcandssol[c];
830 frac = nlpcandsfrac[c];
831 prefvar = covercomputed && heurdata->prefercover && SCIPhashmapExists(varincover, var);
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 */
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 )
850 else if( mayrounddown )
852 else
854
856
857 /* check, if candidate is new best candidate */
859 {
860 *bestcand = c;
865 }
866 }
867 }
868 else
869 {
870 /* the candidate may not be rounded: calculate pseudo cost quotient and preferred direction */
873
874 /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
876 {
877 *bestcand = c;
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;
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);
933
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;
946 SCIP_Real objgain;
947
951
952 var = nlpcands[c];
955 solval = nlpcandssol[c];
956 frac = nlpcandsfrac[c];
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 */
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 )
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 */
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;
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;
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);
1097 assert(pseudocandsnlpsol != NULL);
1098 assert(pseudocandslpsol != NULL);
1099 assert(covercomputed == (varincover != NULL));
1100 assert(bestcand != NULL);
1101 assert(bestcandmayround != NULL);
1103
1104 bestfrac = SCIP_INVALID;
1105
1106 for( c = 0; c < npseudocands; ++c )
1107 {
1108 SCIP_VAR* var;
1109 SCIP_Bool mayround;
1111
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
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
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;
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 */
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])));
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;
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(event != NULL);
1462
1464
1465 heurdata = (SCIP_HEURDATA*)eventdata;
1466 assert(heurdata != NULL);
1467 assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1468
1469 oldbound = SCIPeventGetOldbound(event);
1470 newbound = SCIPeventGetNewbound(event);
1471 var = SCIPeventGetVar(event);
1472
1473 eventtype = SCIPeventGetType(event);
1474 otherbound = (eventtype & SCIP_EVENTTYPE_LBCHANGED) ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
1475
1476 switch( eventtype )
1477 {
1480 /* if cover variable is now fixed */
1481 if( SCIPisFeasEQ(scip, newbound, otherbound) && !SCIPisFeasEQ(scip, oldbound, otherbound) )
1482 {
1483 assert(!SCIPisEQ(scip, oldbound, otherbound));
1484 ++(heurdata->nfixedcovervars);
1485 }
1486 break;
1489 /* if cover variable is now unfixed */
1490 if( SCIPisFeasEQ(scip, oldbound, otherbound) && !SCIPisFeasEQ(scip, newbound, otherbound) )
1491 {
1492 assert(!SCIPisEQ(scip, newbound, otherbound));
1493 --(heurdata->nfixedcovervars);
1494 }
1495 break;
1496 default:
1497 SCIPerrorMessage("invalid event type.\n");
1498 return SCIP_INVALIDDATA;
1499 }
1500 assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1501
1502 /* SCIPdebugMsg(scip, "changed bound of cover variable <%s> from %f to %f (nfixedcovervars: %d).\n", SCIPvarGetName(var),
1503 oldbound, newbound, heurdata->nfixedcovervars); */
1504
1505 return SCIP_OKAY;
1506}
1507
1508
1509/*
1510 * Callback methods
1511 */
1512
1513/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1514static
1515SCIP_DECL_HEURCOPY(heurCopyNlpdiving)
1516{ /*lint --e{715}*/
1517 assert(scip != NULL);
1518 assert(heur != NULL);
1519
1521
1522 /* call inclusion method of primal heuristic */
1524
1525 return SCIP_OKAY;
1526}
1527
1528/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1529static
1530SCIP_DECL_HEURFREE(heurFreeNlpdiving) /*lint --e{715}*/
1531{ /*lint --e{715}*/
1533
1534 assert(heur != NULL);
1536
1538
1539 /* free heuristic data */
1544
1546}
1547
1548
1549/** initialization method of primal heuristic (called after problem was transformed) */
1550static
1551SCIP_DECL_HEURINIT(heurInitNlpdiving) /*lint --e{715}*/
1552{ /*lint --e{715}*/
1554
1555 assert(heur != NULL);
1556
1558
1559 /* get heuristic data */
1560 heurdata = SCIPheurGetData(heur);
1561 assert(heurdata != NULL);
1562
1563 /* create working solution */
1565
1566 /* create random number generator */
1568
1569 /* initialize data */
1570 heurdata->nnlpiterations = 0;
1571 heurdata->nsuccess = 0;
1572 heurdata->nfixedcovervars = 0;
1574 heurdata->nnlpsolves = 0;
1575 heurdata->nfailcutoff = 0;
1576 heurdata->nfaildepth = 0;
1577 heurdata->nfailnlperror = 0;
1578 );
1579
1580 return SCIP_OKAY;
1581}
1582
1583
1584/** deinitialization method of primal heuristic (called before transformed problem is freed) */
1585static
1586SCIP_DECL_HEUREXIT(heurExitNlpdiving) /*lint --e{715}*/
1587{ /*lint --e{715}*/
1589
1590 assert(heur != NULL);
1591
1593
1594 /* get heuristic data */
1595 heurdata = SCIPheurGetData(heur);
1596 assert(heurdata != NULL);
1597
1598 /* free random number generator */
1600
1601 /* free working solution */
1603
1605 if( strstr(SCIPgetProbName(scip), "_covering") == NULL && SCIPheurGetNCalls(heur) > 0 )
1606 {
1607 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",
1609 heurdata->nnlpiterations, heurdata->nnlpsolves, heurdata->nnlpiterations/MAX(1.0,(SCIP_Real)heurdata->nnlpsolves),
1610 (100*heurdata->nsuccess) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailcutoff) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfaildepth) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailnlperror) / (int)SCIPheurGetNCalls(heur)
1611 );
1612 }
1613 );
1614
1615 return SCIP_OKAY;
1616}
1617
1618
1619/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1620static
1621SCIP_DECL_HEURINITSOL(heurInitsolNlpdiving)
1622{ /*lint --e{715}*/
1624
1625 assert(heur != NULL);
1626
1627 /* get heuristic data */
1628 heurdata = SCIPheurGetData(heur);
1629 assert(heurdata != NULL);
1630
1631 /* store nlpdiving timing */
1632 heurdata->inittiming = SCIPheurGetTimingmask(heur);
1633
1634 /* disable nlpdiving heuristic */
1637
1638 return SCIP_OKAY;
1639}
1640
1641
1642/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1643static
1644SCIP_DECL_HEUREXITSOL(heurExitsolNlpdiving)
1645{ /*lint --e{715}*/
1647
1648 assert(heur != NULL);
1649
1650 /* get heuristic data */
1651 heurdata = SCIPheurGetData(heur);
1652 assert(heurdata != NULL);
1653
1654 /* reset nlpdiving timing */
1655 SCIPheurSetTimingmask(heur, heurdata->inittiming);
1656
1657 return SCIP_OKAY;
1658}
1659
1660
1661/** execution method of primal heuristic */
1662static
1663SCIP_DECL_HEUREXEC(heurExecNlpdiving)
1664{ /*lint --e{715}*/
1666 SCIP_NLPSOLSTAT nlpsolstat;
1668 SCIP_SOL* nlpstartsol;
1669 SCIP_SOL* bestsol;
1671 SCIP_VAR** covervars;
1672 SCIP_Real* nlpcandssol;
1673 SCIP_Real* nlpcandsfrac;
1674 SCIP_Real* pseudocandslpsol;
1675 SCIP_Real* pseudocandsnlpsol;
1676 SCIP_HASHMAP* varincover;
1681 SCIP_Real oldobjval;
1682 SCIP_Real fixquot;
1683 SCIP_Real bestboundval;
1684 SCIP_Bool bestcandmayround;
1686 SCIP_Bool nlperror;
1690 SCIP_Bool solvenlp;
1691 SCIP_Bool covercomputed;
1692 SCIP_Bool solvesubmip;
1695 SCIP_VAR* backtrackvar; /* (first) variable to fix differently in backtracking */
1696 SCIP_Real backtrackvarval; /* (fractional) value of backtrack variable */
1697 SCIP_Bool backtrackroundup; /* whether variable should be rounded up in backtracking */
1698 int backtrackdepth; /* depth where to go when backtracking */
1699 int avgnnlpiterations;
1700 int maxnnlpiterations;
1701 int npseudocands;
1702 int nlpbranchcands;
1703 int ncovervars;
1704 int nnlpcands;
1705 int startnnlpcands;
1706 int depth;
1707 int maxdepth;
1708 int maxdivedepth;
1709 int divedepth;
1710 int lastnlpsolvedepth;
1711 int nfeasnlps;
1712 int bestcand;
1713 int c;
1714
1715 assert(scip != NULL);
1716 assert(result != NULL);
1718 assert(SCIPgetNNlpis(scip) >= 1);
1719
1721
1723
1724 /* do not call heuristic of node was already detected to be infeasible */
1725 if( nodeinfeasible )
1726 return SCIP_OKAY;
1727
1728 /* only call heuristic if the current node will not be cutoff, e.g., due to a (integer and NLP-)feasible LP solution */
1730 return SCIP_OKAY;
1731
1732 /* get heuristic's data */
1733 heurdata = SCIPheurGetData(heur);
1734 assert(heurdata != NULL);
1735
1736 /* do not call heuristic if it barely succeded */
1737 if( (SCIPheurGetNSolsFound(heur) + 1.0) / (SCIP_Real)(SCIPheurGetNCalls(heur) + 1.0) < heurdata->minsuccquot )
1738 return SCIP_OKAY;
1739
1741
1742 /* don't dive two times at the same node */
1744 return SCIP_OKAY;
1745
1747
1748 /* only try to dive if we are in the correct part of the tree, given by minreldepth and maxreldepth */
1751 maxdepth = MAX(maxdepth, 30);
1752 if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
1753 return SCIP_OKAY;
1754
1755 /* calculate the maximal number of NLP iterations until heuristic is aborted
1756 * maximal number is maxnlpiterabs plus a success-depending multiplier of maxnlpiterrel
1757 */
1758 ncalls = SCIPheurGetNCalls(heur);
1759 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
1760 maxnnlpiterations = heurdata->maxnlpiterabs;
1761 maxnnlpiterations += (int)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxnlpiterrel);
1762
1763 /* don't try to dive if we took too many NLP iterations during diving */
1764 if( heurdata->nnlpiterations >= maxnnlpiterations )
1765 return SCIP_OKAY;
1766
1767 /* allow at least a bit more than the so far average number of NLP iterations per dive */
1768 avgnnlpiterations = (int)(heurdata->nnlpiterations / MAX(ncalls, 1.0));
1769 maxnnlpiterations = (int)MAX((SCIP_Real) maxnnlpiterations, (SCIP_Real) heurdata->nnlpiterations + 1.2*avgnnlpiterations);
1770
1771 /* don't try to dive if there are no unfixed discrete variables */
1772 SCIP_CALL( SCIPgetPseudoBranchCands(scip, NULL, &npseudocands, NULL) );
1773 if( npseudocands == 0 )
1774 return SCIP_OKAY;
1775
1777
1778 /* set starting point to lp solution */
1780
1781 /* solve NLP relaxation if not solved already */
1782 nlpsolstat = SCIPgetNLPSolstat(scip);
1783 if( nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE )
1784 {
1785 SCIP_NLPSTATISTICS nlpstatistics;
1786
1788 .iterlimit = maxnnlpiterations - heurdata->nnlpiterations,
1789 .fastfail = heurdata->nlpfastfail ? SCIP_NLPPARAM_FASTFAIL_AGGRESSIVE : SCIP_NLPPARAM_FASTFAIL_CONSERVATIVE) ); /*lint !e666*/
1790 SCIPstatistic( ++heurdata->nnlpsolves );
1791
1792 /* update iteration count */
1794 {
1795 SCIP_CALL( SCIPgetNLPStatistics(scip, &nlpstatistics) );
1796 heurdata->nnlpiterations += nlpstatistics.niterations;
1797 }
1798
1799 nlpsolstat = SCIPgetNLPSolstat(scip);
1800
1801 /* give up, if no feasible solution found */
1802 if( nlpsolstat >= SCIP_NLPSOLSTAT_LOCINFEASIBLE )
1803 {
1804 SCIPdebugMsg(scip, "initial NLP infeasible or not solvable --> stop\n");
1805
1808 heurdata->nfailcutoff++;
1809 else
1810 heurdata->nfailnlperror++;
1811 )
1812
1813 return SCIP_OKAY;
1814 }
1815 }
1816
1817 /* get NLP solution */
1819
1820 /* get fractional variables that should be integral */
1821 SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
1822 assert(nnlpcands <= npseudocands);
1823
1824 /* get LP candidates if LP solution is optimal */
1827 nlpbranchcands = SCIPgetNLPBranchCands(scip);
1828 else
1829 nlpbranchcands = 0;
1830
1831 /* don't try to dive, if there are no fractional variables */
1832 if( nnlpcands == 0 )
1833 {
1834 SCIP_Bool success;
1835
1836 /* check, if solution was feasible and good enough
1837 *
1838 * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
1839 * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
1840 * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
1841 */
1842#ifdef SCIP_DEBUG
1843 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
1844#else
1845 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
1846#endif
1847 if( success )
1848 {
1849 SCIPdebugMsg(scip, " -> solution of first NLP was integral, feasible, and good enough\n");
1851 }
1852
1853 return SCIP_OKAY;
1854 }
1855
1856 /* for guided diving: don't dive, if no feasible solutions exist */
1857 if( heurdata->varselrule == 'g' && SCIPgetNSols(scip) == 0 )
1858 return SCIP_OKAY;
1859
1860 /* for guided diving: get best solution that should guide the search; if this solution lives in the original variable space,
1861 * we cannot use it since it might violate the global bounds of the current problem
1862 */
1863 if( heurdata->varselrule == 'g' && SCIPsolIsOriginal(SCIPgetBestSol(scip)) )
1864 return SCIP_OKAY;
1865
1866 nlpstartsol = NULL;
1867 assert(nlpcandsfrac != NULL);
1868 assert(nlpcands != NULL);
1869 assert(nlpcandssol != NULL);
1870
1871 /* save solution of first NLP, if we may use it later */
1872 if( heurdata->nlpstart != 'n' )
1873 {
1874 SCIP_CALL( SCIPcreateNLPSol(scip, &nlpstartsol, heur) );
1875 SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
1876 }
1877
1878 /* calculate the objective search bound */
1879 if( SCIPgetNSolsFound(scip) == 0 )
1880 {
1881 if( heurdata->maxdiveubquotnosol > 0.0 )
1883 + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1884 else
1886 if( heurdata->maxdiveavgquotnosol > 0.0 )
1888 + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1889 else
1891 }
1892 else
1893 {
1894 if( heurdata->maxdiveubquot > 0.0 )
1896 + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1897 else
1899 if( heurdata->maxdiveavgquot > 0.0 )
1901 + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1902 else
1904 }
1906 if( SCIPisObjIntegral(scip) )
1908
1909 /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
1911 assert(maxdivedepth >= 0);
1913 maxdivedepth *= 10;
1914
1915 /* initialize local variables */
1916 backtrackdepth = -1;
1917 backtrackvar = NULL;
1918 backtrackvarval = 0.0;
1919 backtrackroundup = FALSE;
1920 bestsol = NULL;
1921 pseudocandsnlpsol = NULL;
1922 pseudocandslpsol = NULL;
1923 covervars = NULL;
1924 covercomputed = FALSE;
1925 varincover = NULL;
1926
1927 /* compute cover, if required */
1928 if( heurdata->prefercover || heurdata->solvesubmip )
1929 {
1930 SCIP_Real timelimit;
1931 SCIP_Real memorylimit;
1932
1933 /* get limits */
1934 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
1935 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
1936 if( !SCIPisInfinity(scip, timelimit) )
1937 timelimit -= SCIPgetSolvingTime(scip);
1938
1939 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1940 if( !SCIPisInfinity(scip, memorylimit) )
1941 {
1942 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1943 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1944 }
1945
1946 /* compute cover; use local bounds; only cover "and" and nonlinear constraints (no bounddisjunction or indicator),
1947 * including convex constraints */
1948 ncovervars = -1;
1950 if( memorylimit > 2.0*SCIPgetMemExternEstim(scip)/1048576.0 && timelimit > 0.05 )
1951 {
1952 SCIP_CALL( SCIPcomputeCoverUndercover(scip, &ncovervars, covervars, timelimit, memorylimit, SCIPinfinity(scip),
1953 FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 'u', &covercomputed) );
1954 }
1955
1956 if( covercomputed )
1957 {
1958 /* a cover can be empty, if the cover computation reveals that all nonlinear constraints are linear w.r.t. current variable fixations */
1959 assert(ncovervars >= 0);
1960
1961 /* create hash map */
1962 SCIP_CALL( SCIPhashmapCreate(&varincover, SCIPblkmem(scip), ncovervars) );
1963
1964 /* process variables in the cover */
1965 for( c = 0; c < ncovervars; c++ )
1966 {
1967 /* insert variable into hash map */
1968 if( SCIPvarGetType(covervars[c]) != SCIP_VARTYPE_CONTINUOUS )
1969 {
1970 assert(!SCIPhashmapExists(varincover, covervars[c]));
1971 SCIP_CALL( SCIPhashmapInsertInt(varincover, covervars[c], c+1) );
1972 }
1973
1974 /* catch bound change events of cover variables */
1975 assert(heurdata->eventhdlr != NULL);
1978 assert(!SCIPisFeasEQ(scip, SCIPvarGetLbLocal(covervars[c]), SCIPvarGetUbLocal(covervars[c])));
1979 }
1980 }
1981 }
1982 else
1983 {
1984 covervars = NULL;
1985 ncovervars = 0;
1986 }
1987
1988 /* start diving */
1990
1991 /* enables collection of variable statistics during probing */
1993
1994 /* get NLP objective value*/
1996
1997 SCIPdebugMsg(scip, "(node %" SCIP_LONGINT_FORMAT ") executing nlpdiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
1999
2000 /* store a copy of the best solution, if guided diving should be used */
2001 if( heurdata->varselrule == 'g' )
2002 {
2003 assert(SCIPgetNSols(scip) > 0);
2005
2007 }
2008
2009 /* if double diving should be used, create arrays to hold to entire LP and NLP solution */
2010 if( heurdata->varselrule == 'd' )
2011 {
2012 SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandslpsol, npseudocands) );
2013 SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandsnlpsol, npseudocands) );
2014 }
2015
2016 /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
2017 * - if possible, we dive at least with the depth 10
2018 * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
2019 */
2020 nlperror = FALSE;
2021 lperror = FALSE;
2022 cutoff = FALSE;
2023 divedepth = 0;
2024 lastnlpsolvedepth = 0;
2025 backtracked = FALSE; /* whether we are in backtracking */
2026 fixquot = heurdata->fixquot;
2027 nfeasnlps = 1;
2028 startnnlpcands = nnlpcands;
2029 solvesubmip = heurdata->solvesubmip;
2030
2031 while( !nlperror && !cutoff && (nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE || nlpsolstat == SCIP_NLPSOLSTAT_UNKNOWN) && nnlpcands > 0
2032 && (nfeasnlps < heurdata->maxfeasnlps
2033 || nnlpcands <= startnnlpcands - divedepth/2
2034 || (nfeasnlps < maxdivedepth && heurdata->nnlpiterations < maxnnlpiterations && objval < searchbound))
2035 && !SCIPisStopped(scip) )
2036 {
2037 SCIP_VAR* var;
2038 SCIP_Bool updatepscost;
2039
2040 /* open a new probing node if this will not exceed the maximal tree depth, otherwise stop here */
2042 {
2044 divedepth++;
2045 }
2046 else
2047 break;
2048
2049 bestcand = -1;
2050 bestcandmayround = TRUE;
2052 bestboundval = SCIP_INVALID;
2053 updatepscost = TRUE;
2054 var = NULL;
2055
2056 /* find best candidate variable */
2057 switch( heurdata->varselrule )
2058 {
2059 case 'c':
2060 SCIP_CALL( chooseCoefVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2061 &bestcand, &bestcandmayround, &bestcandroundup) );
2062 if( bestcand >= 0 )
2063 {
2065 bestboundval = nlpcandssol[bestcand];
2066 }
2067 break;
2068 case 'v':
2069 SCIP_CALL( chooseVeclenVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2070 &bestcand, &bestcandmayround, &bestcandroundup) );
2071 if( bestcand >= 0 )
2072 {
2074 bestboundval = nlpcandssol[bestcand];
2075 }
2076 break;
2077 case 'p':
2078 SCIP_CALL( choosePscostVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2079 &bestcand, &bestcandmayround, &bestcandroundup) );
2080 if( bestcand >= 0 )
2081 {
2083 bestboundval = nlpcandssol[bestcand];
2084 }
2085 break;
2086 case 'g':
2087 SCIP_CALL( chooseGuidedVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, bestsol, varincover, covercomputed,
2088 &bestcand, &bestcandmayround, &bestcandroundup) );
2089 if( bestcand >= 0 )
2090 {
2092 bestboundval = nlpcandssol[bestcand];
2093 }
2094 break;
2095 case 'd':
2096 /* double diving only works if we have both relaxations at hand, otherwise we fall back to fractional diving */
2098 {
2100
2102 assert(backtrackdepth > 0 || nnlpcands <= npseudocands);
2103 assert(SCIPgetNLPBranchCands(scip) <= npseudocands);
2104 SCIP_CALL( SCIPgetSolVals(scip, NULL, npseudocands, pseudocands, pseudocandslpsol) );
2105 SCIP_CALL( SCIPgetSolVals(scip, heurdata->sol, npseudocands, pseudocands, pseudocandsnlpsol) );
2106 SCIP_CALL( chooseDoubleVar(scip, heurdata, pseudocands, pseudocandsnlpsol, pseudocandslpsol, npseudocands,
2107 varincover, covercomputed, &bestcand, &bestboundval, &bestcandmayround, &bestcandroundup) );
2108 if( bestcand >= 0 )
2110 break;
2111 }
2112 else
2113 updatepscost = FALSE;
2114 /*lint -fallthrough*/
2115 case 'f':
2116 SCIP_CALL( chooseFracVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2117 &bestcand, &bestcandmayround, &bestcandroundup) );
2118 if( bestcand >= 0 )
2119 {
2121 bestboundval = nlpcandssol[bestcand];
2122 }
2123 break;
2124 default:
2125 SCIPerrorMessage("invalid variable selection rule\n");
2126 return SCIP_INVALIDDATA;
2127 }
2128
2129 /* if all candidates are roundable, try to round the solution
2130 * if var == NULL (i.e., bestcand == -1), then all solution candidates are outside bounds
2131 * this should only happen if they are slightly outside bounds (i.e., still within feastol, relative tolerance),
2132 * but far enough out to be considered as fractional (within feastol, but using absolute tolerance)
2133 * in this case, we also try our luck with rounding
2134 */
2135 if( (var == NULL || bestcandmayround) && backtrackdepth == -1 )
2136 {
2137 SCIP_Bool success;
2138
2139 /* create solution from diving NLP and try to round it */
2140 SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
2141
2142 if( success )
2143 {
2144 SCIPdebugMsg(scip, "nlpdiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2145
2146 /* try to add solution to SCIP */
2147#ifdef SCIP_DEBUG
2148 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, FALSE, TRUE, &success) );
2149#else
2150 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
2151#endif
2152
2153 /* check, if solution was feasible and good enough */
2154 if( success )
2155 {
2156 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2158 }
2159 }
2160 }
2161
2162 /* if all variables have been found to be essentially integral (even though there is some numerical doubt, see comment above), then stop */
2163 if( var == NULL )
2164 break;
2165
2166 do
2167 {
2170
2171 if( backtracked && backtrackdepth > 0 )
2172 {
2173 assert(backtrackvar != NULL);
2174
2175 /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2176 * occurred or variable was fixed by propagation while backtracking => Abort diving!
2177 */
2178 if( SCIPvarGetLbLocal(backtrackvar) >= SCIPvarGetUbLocal(backtrackvar) - 0.5 )
2179 {
2180 SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2181 SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2182 cutoff = TRUE;
2183 break;
2184 }
2185 if( SCIPisFeasLT(scip, backtrackvarval, SCIPvarGetLbLocal(backtrackvar)) || SCIPisFeasGT(scip, backtrackvarval, SCIPvarGetUbLocal(backtrackvar)) )
2186 {
2187 SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2188 SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2190 break;
2191 }
2192
2193 /* round backtrack variable up or down */
2194 if( backtrackroundup )
2195 {
2196 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2197 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2198 SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2199 SCIPfeasCeil(scip, backtrackvarval), SCIPvarGetUbLocal(backtrackvar));
2200 SCIP_CALL( SCIPchgVarLbProbing(scip, backtrackvar, SCIPfeasCeil(scip, backtrackvarval)) );
2201 }
2202 else
2203 {
2204 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2205 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2206 SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2207 SCIPvarGetLbLocal(backtrackvar), SCIPfeasFloor(scip, backtrackvarval));
2208 SCIP_CALL( SCIPchgVarUbProbing(scip, backtrackvar, SCIPfeasFloor(scip, backtrackvarval)) );
2209 }
2210
2211 /* forget about backtrack variable */
2212 backtrackdepth = -1;
2213
2214 /* for pseudo cost computation */
2215 bestcandroundup = backtrackroundup;
2216 frac = SCIPfrac(scip, backtrackvarval);
2217 var = backtrackvar;
2218 }
2219 else
2220 {
2221 assert(var != NULL);
2222
2223 /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2224 * occurred or variable was fixed by propagation while backtracking => Abort diving!
2225 */
2227 {
2228 SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2230 cutoff = TRUE;
2231 break;
2232 }
2233 if( SCIPisFeasLT(scip, bestboundval, SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, bestboundval, SCIPvarGetUbLocal(var)) )
2234 {
2235 SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2238 break;
2239 }
2240
2241 /* apply rounding of best candidate */
2243 {
2244 /* round variable up */
2245 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2246 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2247 SCIPvarGetName(var), bestcandmayround,
2248 bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2249 SCIPfeasCeil(scip, bestboundval), SCIPvarGetUbLocal(var));
2251
2252 /* 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 */
2253 if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2254 {
2255 backtrackdepth = divedepth;
2256 backtrackvar = var;
2257 backtrackvarval = bestboundval;
2258 backtrackroundup = FALSE;
2259 }
2260 }
2261 else
2262 {
2263 /* round variable down */
2264 SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2265 divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2266 SCIPvarGetName(var), bestcandmayround,
2267 bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2268 SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, bestboundval));
2270
2271 /* 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 */
2272 if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2273 {
2274 backtrackdepth = divedepth;
2275 backtrackvar = var;
2276 backtrackvarval = bestboundval;
2277 backtrackroundup = TRUE;
2278 }
2279 }
2280
2281 /* for pseudo-cost computation */
2282 if( updatepscost && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
2283 {
2284 if( heurdata->varselrule == 'd' )
2285 {
2286 assert(pseudocandsnlpsol != NULL);
2287 assert(0 <= bestcand && bestcand < npseudocands);
2288 frac = SCIPfrac(scip, pseudocandsnlpsol[bestcand]);
2289 }
2290 else
2291 frac = nlpcandsfrac[bestcand];
2292 }
2293 }
2294
2295 /* apply domain propagation */
2297 if( cutoff )
2298 {
2299 SCIPdebugMsg(scip, " *** cutoff detected in propagation at level %d\n", SCIPgetProbingDepth(scip));
2300 }
2301
2302 /* if all variables in the cover are fixed or there is no fractional variable in the cover,
2303 * then solve a sub-MIP
2304 */
2305 if( !cutoff && solvesubmip && covercomputed &&
2306 (heurdata->nfixedcovervars == ncovervars ||
2307 (heurdata->nfixedcovervars >= (ncovervars+1)/2 && !SCIPhashmapExists(varincover, var))) )
2308 {
2309 int probingdepth;
2310
2311 solvesubmip = FALSE;
2312 probingdepth = SCIPgetProbingDepth(scip);
2313 assert(probingdepth >= 1);
2314 assert(covervars != NULL);
2315
2316 if( heurdata->nfixedcovervars != ncovervars )
2317 {
2318 /* fix all remaining cover variables */
2319 for( c = 0; c < ncovervars && !cutoff ; c++ )
2320 {
2321 SCIP_Real lb;
2322 SCIP_Real ub;
2323 lb = SCIPvarGetLbLocal(covervars[c]);
2324 ub = SCIPvarGetUbLocal(covervars[c]);
2325 if( !SCIPisFeasEQ(scip, lb, ub) )
2326 {
2327 SCIP_Real nlpsolval;
2328
2329 /* adopt lpsolval w.r.t. intermediate bound changes by propagation */
2330 nlpsolval = SCIPvarGetNLPSol(covervars[c]);
2331 nlpsolval = MIN(nlpsolval,ub);
2332 nlpsolval = MAX(nlpsolval,lb);
2334
2335 /* open a new probing node if this will not exceed the maximal tree depth,
2336 * otherwise fix all the remaining variables at the same probing node
2337 * @todo do we need a new probing node for each fixing? if one of these fixings leads to a cutoff
2338 * we backtrack to the last probing node before we started to fix the covervars (and we do
2339 * not solve the probing LP). thus, it would be less work load in SCIPendProbing
2340 * and SCIPbacktrackProbing.
2341 */
2343 {
2345 }
2346
2347 /* fix and propagate */
2348 assert(SCIPisLbBetter(scip, nlpsolval, lb, ub) || SCIPisUbBetter(scip, nlpsolval, lb, ub));
2349
2350 if( SCIPisLbBetter(scip, nlpsolval, lb, ub) )
2351 {
2352 SCIP_CALL( SCIPchgVarLbProbing(scip, covervars[c], nlpsolval) );
2353 /* if covervar was continuous implied integral and fractional, then nlpsolval may be below
2354 * lower bound now, so adjust to new bound
2355 */
2356 nlpsolval = MAX(nlpsolval, SCIPvarGetLbLocal(covervars[c])); /*lint !e666*/
2357 }
2358 if( SCIPisUbBetter(scip, nlpsolval, lb, ub) )
2359 {
2360 SCIP_CALL( SCIPchgVarUbProbing(scip, covervars[c], nlpsolval) );
2361 }
2362
2364 }
2365 }
2366 }
2367
2368 /* solve sub-MIP or return to standard diving */
2369 if( cutoff )
2370 {
2371 SCIP_CALL( SCIPbacktrackProbing(scip, probingdepth) );
2372 }
2373 else
2374 {
2375 SCIP_Bool success;
2376 success = FALSE;
2377
2378 SCIP_CALL( solveSubMIP(scip, heur, covervars, ncovervars, &success) );
2379 if( success )
2381 backtracked = TRUE; /* to avoid backtracking */
2382 nnlpcands = 0; /* to force termination */
2383 cutoff = TRUE;
2384 }
2385 }
2386
2387 /* resolve the diving LP */
2388 if( !cutoff && !lperror && (heurdata->lp || heurdata->varselrule == 'd')
2390 {
2392
2393 /* get LP solution status, objective value, and fractional variables, that should be integral */
2397
2399 {
2400 nlpbranchcands = SCIPgetNLPBranchCands(scip);
2401
2402 /* get new objective value */
2403 oldobjval = objval;
2405
2406 /* update pseudo cost values */
2407 if( updatepscost && SCIPisGT(scip, objval, oldobjval) )
2408 {
2409 assert(frac != SCIP_INVALID); /*lint !e777*/
2410 if( bestcandroundup )
2411 {
2412 SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 1.0-frac, objval - oldobjval, 1.0) );
2413 }
2414 else
2415 {
2416 SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 0.0-frac, objval - oldobjval, 1.0) );
2417 }
2418 }
2419 }
2420 else
2421 {
2422 nlpbranchcands = 0;
2423 }
2424
2425 if( cutoff )
2426 {
2427 SCIPdebugMsg(scip, " *** cutoff detected in LP solving at level %d, lpsolstat = %d\n", SCIPgetProbingDepth(scip), lpsolstat);
2428 }
2429 }
2430 else
2432
2433 /* check whether we want to solve the NLP, which is the case if
2434 * - we are in backtracking, or
2435 * - we have (actively) fixed/rounded fixquot*nnlpcands variables
2436 * - all fractional variables were rounded/fixed (due to fixing and domain propagation)
2437 */
2438 solvenlp = backtracked;
2439 if( !solvenlp && !cutoff )
2440 {
2441 solvenlp = (lastnlpsolvedepth < divedepth - fixquot * nnlpcands);
2442 if( !solvenlp )
2443 {
2444 /* check if fractional NLP variables are left (some may have been fixed by propagation) */
2445 for( c = 0; c < nnlpcands; ++c )
2446 {
2447 var = nlpcands[c];
2448 if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
2449 continue;
2450 else
2451 break;
2452 }
2453 if( c == nnlpcands )
2454 solvenlp = TRUE;
2455 }
2456 }
2457
2458 nlpsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2459
2460 /* resolve the diving NLP */
2461 if( !cutoff && solvenlp )
2462 {
2463 SCIP_NLPTERMSTAT termstat;
2464 SCIP_NLPSTATISTICS nlpstatistics;
2465
2466 /* set start solution, if we are in backtracking (previous NLP solve was infeasible) */
2467 if( heurdata->nlpstart != 'n' && backtracked )
2468 {
2469 assert(nlpstartsol != NULL);
2470
2471 SCIPdebugMsg(scip, "setting NLP initial guess\n");
2472
2473 SCIP_CALL( SCIPsetNLPInitialGuessSol(scip, nlpstartsol) );
2474 }
2475
2476 /* solve NLP; allow at least MINNLPITER many iterations */
2478 .iterlimit = MAX(maxnnlpiterations - heurdata->nnlpiterations, MINNLPITER)) ); /*lint !e666*/
2479 SCIPstatistic( ++heurdata->nnlpsolves );
2480
2481 termstat = SCIPgetNLPTermstat(scip);
2482 if( termstat >= SCIP_NLPTERMSTAT_NUMERICERROR )
2483 {
2484 if( termstat >= SCIP_NLPTERMSTAT_LICENSEERROR )
2485 {
2487 "Error while solving NLP in nlpdiving heuristic; NLP solve terminated with code <%d>\n", termstat);
2488 }
2489 nlperror = TRUE;
2490 break;
2491 }
2492
2493 /* update iteration count */
2494 SCIP_CALL( SCIPgetNLPStatistics(scip, &nlpstatistics) );
2495 heurdata->nnlpiterations += nlpstatistics.niterations;
2496
2497 /* get NLP solution status, objective value, and fractional variables, that should be integral */
2498 nlpsolstat = SCIPgetNLPSolstat(scip);
2499 cutoff = (nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE);
2500
2501 if( cutoff )
2502 {
2503 SCIPdebugMsg(scip, " *** cutoff detected in NLP solving at level %d, nlpsolstat: %d\n", SCIPgetProbingDepth(scip), nlpsolstat);
2504 }
2505 else
2506 {
2508
2509 /* remember that we have solve NLP on this depth successfully */
2510 lastnlpsolvedepth = divedepth;
2511 /* forget previous backtrack variable, we will never go back to a depth before the current one */
2512 backtrackdepth = -1;
2513 /* store NLP solution for warmstarting, if nlpstart is 'f' */
2514 if( heurdata->nlpstart == 'f' )
2515 {
2516 assert(nlpstartsol != NULL);
2517
2518 /* copy NLP solution values into nlpstartsol, is there a better way to do this???? */
2519 SCIP_CALL( SCIPlinkNLPSol(scip, nlpstartsol) );
2520 SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
2521 }
2522 /* increase counter on number of NLP solves with feasible solution */
2523 ++nfeasnlps;
2524 }
2525 }
2526
2527 /* perform backtracking if a cutoff was detected */
2528 if( cutoff && !backtracked && heurdata->backtrack )
2529 {
2530 if( backtrackdepth == -1 )
2531 {
2532 /* backtrack one step */
2533 SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking one step\n", SCIPgetProbingDepth(scip));
2535
2536 /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2538
2540 }
2541 else
2542 {
2543 /* if we have a stored a depth for backtracking, go there */
2544 SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking to depth %d\n", SCIPgetProbingDepth(scip), backtrackdepth);
2545 SCIP_CALL( SCIPbacktrackProbing(scip, backtrackdepth-1) );
2546
2547 /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2549
2551 divedepth = backtrackdepth;
2552
2553 /* do not update pseudocosts if backtracking by more than one level */
2554 updatepscost = FALSE;
2555
2556 /* in case, we are feasible after backtracking, fix less variables at once in continuing diving
2557 * @todo should we remember the fixquot in heurdata for the next run?
2558 */
2559 fixquot *= 0.5;
2560 }
2561 /* remember that we are backtracking now */
2562 backtracked = TRUE;
2563 }
2564 else
2566 }
2567 while( backtracked );
2568
2569 if( !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2570 {
2571 /* get new fractional variables */
2572 SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
2573 }
2574 SCIPdebugMsg(scip, " -> nlpsolstat=%d, objval=%g/%g, nfrac nlp=%d lp=%d\n", nlpsolstat, objval, searchbound, nnlpcands, nlpbranchcands);
2575 }
2576
2577 /*lint --e{774}*/
2578 SCIPdebugMsg(scip, "NLP nlpdiving ABORT due to ");
2579 if( nlperror || (nlpsolstat > SCIP_NLPSOLSTAT_LOCINFEASIBLE && nlpsolstat != SCIP_NLPSOLSTAT_UNKNOWN) )
2580 {
2581 SCIPdebugMsgPrint(scip, "NLP bad status - nlperror: %ud nlpsolstat: %d \n", nlperror, nlpsolstat);
2582 SCIPstatistic( heurdata->nfailnlperror++ );
2583 }
2584 else if( SCIPisStopped(scip) || cutoff )
2585 {
2586 SCIPdebugMsgPrint(scip, "LIMIT hit - stop: %ud cutoff: %ud \n", SCIPisStopped(scip), cutoff);
2587 SCIPstatistic( heurdata->nfailcutoff++ );
2588 }
2589 else if(! (divedepth < 10
2590 || nnlpcands <= startnnlpcands - divedepth/2
2592 {
2593 SCIPdebugMsgPrint(scip, "TOO DEEP - divedepth: %4d cands halfed: %d ltmaxdepth: %d ltmaxiter: %d bound: %d\n", divedepth,
2594 (nnlpcands > startnnlpcands - divedepth/2), (divedepth >= maxdivedepth), (heurdata->nnlpiterations >= maxnnlpiterations),
2595 (objval >= searchbound));
2596 SCIPstatistic( heurdata->nfaildepth++ );
2597 }
2598 else if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2599 {
2600 SCIPdebugMsgPrint(scip, "SUCCESS\n");
2601 }
2602 else
2603 {
2604 SCIPdebugMsgPrint(scip, "UNKNOWN, very mysterical reason\n"); /* see also special case var == NULL (bestcand == -1) after choose*Var above */
2605 }
2606
2607 /* check if a solution has been found */
2608 if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2609 {
2610 SCIP_Bool success;
2611
2612 /* create solution from diving NLP */
2613 SCIPdebugMsg(scip, "nlpdiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2614
2615 /* try to add solution to SCIP
2616 *
2617 * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
2618 * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
2619 * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
2620 */
2621#ifdef SCIP_DEBUG
2622 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
2623#else
2624 SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
2625#endif
2626
2627 /* check, if solution was feasible and good enough */
2628 if( success )
2629 {
2630 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2632 }
2633 else
2634 {
2635 SCIPdebugMsg(scip, " -> solution was not accepted\n");
2636 }
2637 }
2638
2639 /* end diving */
2641
2642 /* free hash map and drop variable bound change events */
2643 if( covercomputed )
2644 {
2645 assert(heurdata->eventhdlr != NULL);
2646 assert(heurdata->nfixedcovervars >= 0); /* variables might have been globally fixed in propagation */
2647 assert(varincover != NULL);
2648 assert(covervars != NULL);
2649
2650 SCIPhashmapFree(&varincover);
2651
2652 /* drop bound change events of cover variables */
2653 for( c = 0; c < ncovervars; c++ )
2654 {
2656 }
2657 }
2658 else
2659 assert(varincover == NULL);
2660
2661 /* free NLP start solution */
2662 if( nlpstartsol != NULL )
2663 {
2664 SCIP_CALL( SCIPfreeSol(scip, &nlpstartsol) );
2665 }
2666
2667 /* free copied best solution */
2668 if( heurdata->varselrule == 'g' )
2669 {
2670 assert(bestsol != NULL);
2671 SCIP_CALL( SCIPfreeSol(scip, &bestsol) );
2672 }
2673 else
2674 assert(bestsol == NULL);
2675
2676 /* free arrays of LP and NLP solution */
2677 if( heurdata->varselrule == 'd' )
2678 {
2679 assert(pseudocandsnlpsol != NULL);
2680 assert(pseudocandsnlpsol != NULL);
2681 SCIPfreeBufferArray(scip, &pseudocandsnlpsol);
2682 SCIPfreeBufferArray(scip, &pseudocandslpsol);
2683 }
2684 else
2685 {
2686 assert(pseudocandsnlpsol == NULL);
2687 assert(pseudocandsnlpsol == NULL);
2688 }
2689
2690 /* free array of cover variables */
2691 if( heurdata->prefercover || heurdata->solvesubmip )
2692 {
2693 assert(covervars != NULL || !covercomputed);
2694 if( covervars != NULL )
2695 SCIPfreeBufferArray(scip, &covervars);
2696 }
2697 else
2698 assert(covervars == NULL);
2699
2700 if( *result == SCIP_FOUNDSOL )
2701 heurdata->nsuccess++;
2702
2703 SCIPdebugMsg(scip, "nlpdiving heuristic finished\n");
2704
2705 return SCIP_OKAY; /*lint !e438*/
2706}
2707
2708
2709/*
2710 * heuristic specific interface methods
2711 */
2712
2713/** creates the nlpdiving heuristic and includes it in SCIP */
2715 SCIP* scip /**< SCIP data structure */
2716 )
2717{
2719 SCIP_HEUR* heur = NULL;
2720
2721 /* create heuristic data */
2723 heurdata->inittiming = HEUR_TIMING;
2724
2725 /* include heuristic */
2727 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecNlpdiving, heurdata) );
2728
2729 assert(heur != NULL);
2730 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyNlpdiving) );
2731 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeNlpdiving) );
2732 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitNlpdiving) );
2733 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitNlpdiving) );
2734 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolNlpdiving) );
2735 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolNlpdiving) );
2736
2737 /* get event handler for bound change events */
2738 heurdata->eventhdlr = NULL;
2739 /* create event handler for bound change events */
2741 eventExecNlpdiving, NULL) );
2742 if ( heurdata->eventhdlr == NULL )
2743 {
2744 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
2745 return SCIP_PLUGINNOTFOUND;
2746 }
2747
2748 /* nlpdiving heuristic parameters */
2750 "heuristics/" HEUR_NAME "/minreldepth",
2751 "minimal relative depth to start diving",
2752 &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
2754 "heuristics/" HEUR_NAME "/maxreldepth",
2755 "maximal relative depth to start diving",
2756 &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
2758 "heuristics/" HEUR_NAME "/maxnlpiterabs",
2759 "minimial absolute number of allowed NLP iterations",
2760 &heurdata->maxnlpiterabs, FALSE, DEFAULT_MAXNLPITERABS, 0, INT_MAX, NULL, NULL) );
2762 "heuristics/" HEUR_NAME "/maxnlpiterrel",
2763 "additional allowed number of NLP iterations relative to successfully found solutions",
2764 &heurdata->maxnlpiterrel, FALSE, DEFAULT_MAXNLPITERREL, 0, INT_MAX, NULL, NULL) );
2766 "heuristics/" HEUR_NAME "/maxdiveubquot",
2767 "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
2768 &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
2770 "heuristics/" HEUR_NAME "/maxdiveavgquot",
2771 "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
2772 &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2774 "heuristics/" HEUR_NAME "/maxdiveubquotnosol",
2775 "maximal UBQUOT when no solution was found yet (0.0: no limit)",
2776 &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
2778 "heuristics/" HEUR_NAME "/maxdiveavgquotnosol",
2779 "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
2780 &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2782 "heuristics/" HEUR_NAME "/maxfeasnlps",
2783 "maximal number of NLPs with feasible solution to solve during one dive",
2784 &heurdata->maxfeasnlps, FALSE, DEFAULT_MAXFEASNLPS, 1, INT_MAX, NULL, NULL) );
2786 "heuristics/" HEUR_NAME "/backtrack",
2787 "use one level of backtracking if infeasibility is encountered?",
2788 &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
2790 "heuristics/" HEUR_NAME "/lp",
2791 "should the LP relaxation be solved before the NLP relaxation?",
2792 &heurdata->lp, TRUE, DEFAULT_LP, NULL, NULL) );
2794 "heuristics/" HEUR_NAME "/preferlpfracs",
2795 "prefer variables that are also fractional in LP solution?",
2796 &heurdata->preferlpfracs, TRUE, DEFAULT_PREFERLPFRACS, NULL, NULL) );
2798 "heuristics/" HEUR_NAME "/minsuccquot",
2799 "heuristic will not run if less then this percentage of calls succeeded (0.0: no limit)",
2800 &heurdata->minsuccquot, FALSE, DEFAULT_MINSUCCQUOT, 0.0, 1.0, NULL, NULL) );
2802 "heuristics/" HEUR_NAME "/fixquot",
2803 "percentage of fractional variables that should be fixed before the next NLP solve",
2804 &heurdata->fixquot, FALSE, DEFAULT_FIXQUOT, 0.0, 1.0, NULL, NULL) );
2806 "heuristics/" HEUR_NAME "/prefercover",
2807 "should variables in a minimal cover be preferred?",
2808 &heurdata->prefercover, FALSE, DEFAULT_PREFERCOVER, NULL, NULL) );
2810 "heuristics/" HEUR_NAME "/solvesubmip",
2811 "should a sub-MIP be solved if all cover variables are fixed?",
2812 &heurdata->solvesubmip, FALSE, DEFAULT_SOLVESUBMIP, NULL, NULL) );
2814 "heuristics/" HEUR_NAME "/nlpfastfail",
2815 "should the NLP solver stop early if it converges slow?",
2816 &heurdata->nlpfastfail, FALSE, DEFAULT_NLPFASTFAIL, NULL, NULL) );
2818 "heuristics/" HEUR_NAME "/nlpstart",
2819 "which point should be used as starting point for the NLP solver? ('n'one, last 'f'easible, from dive's'tart)",
2820 &heurdata->nlpstart, TRUE, DEFAULT_NLPSTART, "fns", NULL, NULL) );
2822 "heuristics/" HEUR_NAME "/varselrule",
2823 "which variable selection should be used? ('f'ractionality, 'c'oefficient, 'p'seudocost, 'g'uided, 'd'ouble, 'v'eclen)",
2824 &heurdata->varselrule, FALSE, DEFAULT_VARSELRULE, "fcpgdv", NULL, NULL) );
2825
2826 return SCIP_OKAY;
2827}
#define EVENTHDLR_NAME
#define EVENTHDLR_DESC
#define DEFAULT_RANDSEED
#define NULL
Definition def.h:257
#define SCIP_PROBINGSCORE_PENALTYRATIO
Definition def.h:312
#define SCIP_Longint
Definition def.h:150
#define SCIP_MAXTREEDEPTH
Definition def.h:306
#define SCIP_REAL_MAX
Definition def.h:167
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define ABS(x)
Definition def.h:225
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define SCIP_CALL(x)
Definition def.h:364
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:2962
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition scip_copy.c:3250
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition scip_copy.c:3293
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_RETCODE SCIPfree(SCIP **scip)
SCIP_RETCODE SCIPcreate(SCIP **scip)
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,...)
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
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)
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
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 SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition heur.c:1368
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition scip_heur.c:122
SCIP_HEURTIMING SCIPheurGetTimingmask(SCIP_HEUR *heur)
Definition heur.c:1497
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition heur.c:1603
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:231
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition heur.c:1613
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition heur.c:1507
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition heur.c:1593
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:247
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:215
SCIP_Real SCIPheurGetTime(SCIP_HEUR *heur)
Definition heur.c:1655
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition heur.c:1467
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)
int SCIPgetProbingDepth(SCIP *scip)
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition scip_sol.c:882
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition scip_sol.c:662
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1504
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition sol.c:4155
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_sol.c:1844
SCIP_RETCODE SCIPlinkNLPSol(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1351
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition scip_sol.c:3128
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition scip_sol.c:1660
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition scip_sol.c:2936
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition scip_sol.c:4017
SCIP_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:4114
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition scip_sol.c:2134
SCIP_RETCODE SCIPsolve(SCIP *scip)
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)
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:4478
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition var.c:4467
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:19144
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:24266
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:24152
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:24723
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
void SCIPenableVarHistory(SCIP *scip)
Definition scip_var.c:11083
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition misc.c:10223
#define DEFAULT_MAXDIVEUBQUOT
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define DEFAULT_MAXDIVEAVGQUOT
#define DEFAULT_BACKTRACK
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define DEFAULT_MAXRELDEPTH
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
#define HEUR_NAME
#define HEUR_FREQ
#define DEFAULT_MINRELDEPTH
#define HEUR_USESSUBSCIP
int divedepth
int maxdivedepth
SCIP_Real searchavgbound
SCIP_VAR ** pseudocands
SCIP_Longint nsolsfound
SCIP_Bool lperror
SCIP_Longint ncalls
int c
SCIP_Real searchubbound
static SCIP_LPSOLSTAT lpsolstat
SCIP_Bool backtracked
heurdata nsuccess
SCIPendProbing(scip))
SCIP_Real searchbound
int maxdepth
int depth
SCIP_Bool cutoff
SCIP_Real objval
int nviolrows
static SCIP_SOL * sol
int nlpcands
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
#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)
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
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)
heurdata nfixedcovervars
heurdata nnlpiterations
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)
SCIPheurSetData(heur, NULL)
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
static SCIP_RETCODE getNLPFracVars(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR ***nlpcands, SCIP_Real **nlpcandssol, SCIP_Real **nlpcandsfrac, int *nnlpcands)
#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)
#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
SCIPfreeSol(scip, &heurdata->sol))
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_LP
#define DEFAULT_SOLVESUBMIP
static SCIP_RETCODE solveSubMIP(SCIP *scip, SCIP_HEUR *heur, SCIP_VAR **covervars, int ncovervars, SCIP_Bool *success)
#define DEFAULT_VARSELRULE
SCIPfreeRandom(scip, &heurdata->randnumgen)
#define DEFAULT_FIXQUOT
#define DEFAULT_NLPSTART
#define DEFAULT_NLPFASTFAIL
#define DEFAULT_MAXFEASNLPS
#define DEFAULT_MINSUCCQUOT
SCIPcreateSol(scip, &heurdata->sol, heur))
NLP diving heuristic that chooses fixings w.r.t. the fractionalities.
SCIP_Bool mayrounddown
SCIP_VAR * var
int bestcand
SCIP_Bool bestcandroundup
SCIP_Bool bestcandmayroundup
SCIP_Real primsol
SCIP_Bool bestcandmayrounddown
SCIP_Real frac
SCIP_Bool mayroundup
SCIP_Real bestpscostquot
SCIP_Real pscostquot
SCIP_Bool roundup
static SCIP_VAR ** vars
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
#define SCIPstatistic(x)
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
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#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_DECL_EVENTEXEC(x)
Definition type_event.h:259
#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
#define SCIP_DECL_HEURINITSOL(x)
Definition type_heur.h:132
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURINIT(x)
Definition type_heur.h:113
#define SCIP_DECL_HEUREXIT(x)
Definition type_heur.h:121
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXITSOL(x)
Definition type_heur.h:143
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
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
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
struct SCIP_NlpStatistics SCIP_NLPSTATISTICS
Definition type_nlpi.h:196
@ 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
@ SCIP_PARAMSETTING_FAST
@ 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
@ SCIP_PLUGINNOTFOUND
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
unsigned int SCIP_HEURTIMING
#define SCIP_HEURTIMING_NONE
Definition type_timing.h:79
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141