Scippy

SCIP

Solving Constraint Integer Programs

heur_subnlp.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-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_subnlp.c
17  * @ingroup DEFPLUGINS_HEUR
18  * @brief NLP local search primal heuristic using sub-SCIPs
19  * @author Stefan Vigerske
20  *
21  * @todo reconstruct sub-SCIP if problem has changed
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include "blockmemshell/memory.h"
27 #include "scip/nlpi_ipopt.h"
29 #include "scip/cons_setppc.h"
30 #include "scip/heur_subnlp.h"
31 #include "scip/pub_event.h"
32 #include "scip/pub_heur.h"
33 #include "scip/pub_message.h"
34 #include "scip/pub_misc.h"
35 #include "scip/pub_sol.h"
36 #include "scip/pub_var.h"
37 #include "scip/scip_branch.h"
38 #include "scip/scip_cons.h"
39 #include "scip/scip_copy.h"
40 #include "scip/scip_event.h"
41 #include "scip/scip_general.h"
42 #include "scip/scip_heur.h"
43 #include "scip/scip_lp.h"
44 #include "scip/scip_mem.h"
45 #include "scip/scip_message.h"
46 #include "scip/scip_nlp.h"
47 #include "scip/scip_nlpi.h"
48 #include "scip/scip_numerics.h"
49 #include "scip/scip_param.h"
50 #include "scip/scip_presol.h"
51 #include "scip/scip_pricer.h"
52 #include "scip/scip_prob.h"
53 #include "scip/scip_sol.h"
54 #include "scip/scip_solve.h"
55 #include "scip/scip_solvingstats.h"
56 #include "scip/scip_timing.h"
57 #include "scip/scip_var.h"
58 #include <string.h>
59 
60 #define HEUR_NAME "subnlp"
61 #define HEUR_DESC "primal heuristic that performs a local search in an NLP after fixing integer variables and presolving"
62 #define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
63 #define HEUR_PRIORITY -2000010
64 #define HEUR_FREQ 1
65 #define HEUR_FREQOFS 0
66 #define HEUR_MAXDEPTH -1
67 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
68 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? we set this to FALSE because we want this heuristic to also run within other heuristics */
69 
70 /*
71  * Data structures
72  */
73 
74 /** primal heuristic data */
75 struct SCIP_HeurData
76 {
77  SCIP* subscip; /**< copy of CIP where presolving and NLP solving is done */
78  SCIP_Bool triedsetupsubscip; /**< whether we have tried to setup a sub-SCIP */
79  SCIP_Bool subscipisvalid; /**< whether all constraints have been copied */
80  SCIP_Bool continuous; /**< whether problem was continuous when sub-SCIP was created */
81  int nseriousnlpierror; /**< number of consecutive serious NLP solver failures (memout, ...) */
82  SCIP_EVENTHDLR* eventhdlr; /**< event handler for global bound change events */
83 
84  int nvars; /**< number of active transformed variables in SCIP */
85  int nsubvars; /**< number of original variables in sub-SCIP */
86  SCIP_VAR** var_subscip2scip; /**< mapping variables in sub-SCIP to SCIP variables */
87  SCIP_VAR** var_scip2subscip; /**< mapping variables in SCIP to sub-SCIP variables */
88 
89  SCIP_SOL* startcand; /**< candidate for start point for heuristic */
90  SCIP_Real startcandviol; /**< violation of start point candidate w.r.t. constraint that reported this candidate */
91  SCIP_SOL* lastsol; /**< pointer to last found solution (or NULL if none), not captured, thus may be dangling */
92 
93  int nlpverblevel; /**< verbosity level of NLP solver */
94  SCIP_Real opttol; /**< optimality tolerance to use for NLP solves */
95  SCIP_Real feastolfactor; /**< factor on SCIP feasibility tolerance for NLP solves if resolving when NLP solution not feasible in CIP */
96  SCIP_Real feastol; /**< feasibility tolerance for NLP solves */
97  SCIP_Bool tighterfeastolfailed;/**< whether we tried to use a tighter feasibility tolerance but the NLP solution was still not accepted */
98  int maxpresolverounds; /**< limit on number of presolve rounds in sub-SCIP */
99  int presolveemphasis; /**< presolve emphasis in sub-SCIP */
100  SCIP_Bool setcutoff; /**< whether to set cutoff in sub-SCIP to current primal bound */
101  SCIP_Bool forbidfixings; /**< whether to add constraints that forbid specific fixations that turned out to be infeasible */
102  SCIP_Bool keepcopy; /**< whether to keep SCIP copy or to create new copy each time heuristic is applied */
103  SCIP_Real expectinfeas; /**< when to tell NLP solver that an infeasible NLP is not unexpected */
104 
105  SCIP_Longint iterused; /**< number of iterations used so far (+ number of heuristic runs + number of presolve runs in subscip) */
106  SCIP_Longint iterusedokay; /**< number of iterations used so far when NLP stopped with status okay */
107  SCIP_Longint iterusediterlim; /**< maximal number of iterations used when NLP stopped due to iteration limit */
108  int nnlpsolves; /**< number of NLP solves */
109  int nnlpsolvesokay; /**< number of NLP solves with status okay */
110  int nnlpsolvesiterlim; /**< number of NLP solves that hit an iteration limit */
111  int nnlpsolvesinfeas; /**< number of NLP solves with status okay and infeasible */
112  int nodesoffset; /**< number of nodes added to the actual number of nodes when computing itercontingent */
113  SCIP_Real nodesfactor; /**< factor to apply to number of nodes in SCIP to compute initial itercontingent */
114  SCIP_Real successrateexp; /**< exponent for power of success rate to be multiplied with itercontingent */
115  int iterinit; /**< number of iterations used for initial NLP solves */
116  int ninitsolves; /**< number of successful NLP solves until switching to iterlimit guess and using success rate */
117  int itermin; /**< minimal number of iterations for NLP solves */
118 };
119 
120 
121 /*
122  * Local methods
123  */
124 
125 /** indicates whether the heuristic should be running, i.e., whether we expect something nonlinear after fixing all discrete variables */
126 static
128  SCIP* scip, /**< SCIP data structure */
129  SCIP_Bool* runheur /**< buffer to store whether to run heuristic */
130  )
131 {
132  assert(scip != NULL);
133  assert(runheur != NULL);
134 
135  /* do not run heuristic if no NLP solver is available */
136  if( SCIPgetNNlpis(scip) <= 0 )
137  {
138  *runheur = FALSE;
139  return SCIP_OKAY;
140  }
141 
142  /* do not run heuristic if no NLP */
143  if( !SCIPisNLPConstructed(scip) )
144  {
145  *runheur = FALSE;
146  return SCIP_OKAY;
147  }
148 
149  /* do not run heuristic if no continuous nonlinear variables in NLP */
151 
152  return SCIP_OKAY;
153 }
154 
155 /** free sub-SCIP data structure */
156 static
158  SCIP* scip, /**< SCIP data structure */
159  SCIP_HEURDATA* heurdata /**< heuristic data structure */
160  )
161 {
162  SCIP_VAR** subvars;
163  int nsubvars;
164  int i;
165  SCIP_VAR* var;
166  SCIP_VAR* subvar;
167 
168  assert(scip != NULL);
169  assert(heurdata != NULL);
170 
171  assert(heurdata->subscip != NULL);
172 
173  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, NULL, NULL, NULL, NULL) );
174  assert(nsubvars == heurdata->nsubvars);
175 
176  /* drop global bound change events
177  * release variables in SCIP and sub-SCIP
178  */
179  for( i = 0; i < heurdata->nsubvars; ++i )
180  {
181  subvar = subvars[i];
182  assert(subvar != NULL);
183  assert(SCIPvarGetProbindex(subvar) == i);
184 
185  var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
186  assert(var != NULL);
187  assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
188  assert(!SCIPvarIsActive(var) || heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == subvar);
189 
190  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, -1) );
191 
192  SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &subvar) );
193  SCIP_CALL( SCIPreleaseVar(scip, &var) );
194  }
195 
196  /* free variable mappings subscip -> scip and scip -> subscip */
197  SCIPfreeBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars);
198  SCIPfreeBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars);
199  heurdata->nsubvars = 0;
200  heurdata->nvars = 0;
201 
202  /* free sub-SCIP */
203  SCIP_CALL( SCIPfree(&heurdata->subscip) );
204 
205  return SCIP_OKAY;
206 }
207 
208 /** creates copy of CIP from problem in SCIP */
209 static
211  SCIP* scip, /**< SCIP data structure */
212  SCIP_HEURDATA* heurdata /**< heuristic data structure */
213  )
214 {
215  int nvars;
216  SCIP_VAR** vars;
217  SCIP_VAR** subvars;
218  SCIP_VAR* var;
219  SCIP_VAR* subvar;
220  SCIP_Bool success;
221  char probname[SCIP_MAXSTRLEN];
222  int i;
223  SCIP_HASHMAP* varsmap;
224  SCIP_HASHMAP* conssmap;
225 
226  assert(heurdata != NULL);
227  assert(heurdata->subscip == NULL);
228 
229  heurdata->triedsetupsubscip = TRUE;
230 
231  /* initializing the subproblem */
232  SCIP_CALL( SCIPcreate(&heurdata->subscip) );
233 
234  /* create sub-SCIP copy of CIP */
235 
236  /* copy interesting plugins */
237  success = TRUE;
238  SCIP_CALL( SCIPcopyPlugins(scip, heurdata->subscip,
239  FALSE, /* readers */
240  FALSE, /* pricers */
241  TRUE, /* conshdlrs */
242  FALSE, /* conflicthdlrs */
243  TRUE, /* presolvers */
244  FALSE, /* relaxators */
245  FALSE, /* separators */
246  FALSE, /* cutselectors */
247  TRUE, /* propagators */
248  FALSE, /* heuristics */
249  TRUE, /* eventhandler */
250  TRUE, /* nodeselectors (SCIP gives an error if there is none) */
251  FALSE, /* branchrules */
252  TRUE, /* displays */
253  FALSE, /* tables */
254  FALSE, /* dialogs */
255  TRUE, /* expression handlers */
256  TRUE, /* nlpis */
257  TRUE, /* message handler */
258  &success) );
259  if( !success )
260  {
261  SCIPdebugMsg(scip, "failed to copy some plugins to sub-SCIP, continue anyway\n");
262  }
263 
264  /* check if we still have NLPI's in subscip */
265  if( SCIPgetNNlpis(heurdata->subscip) <= 0 )
266  {
267  SCIPdebugMsg(scip, "none of the NLPIs from main SCIP copied into sub-SCIP, give up heuristic.\n");
268  SCIP_CALL( SCIPfree(&heurdata->subscip) );
269 
270  return SCIP_OKAY;
271  }
272 
273  /* copy parameter settings */
274  SCIP_CALL( SCIPcopyParamSettings(scip, heurdata->subscip) );
275 
276  /* create problem in sub-SCIP */
277  /* get name of the original problem and add "subnlp" */
278  (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_subnlp", SCIPgetProbName(scip));
279  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
280  SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
281  SCIP_CALL( SCIPhashmapCreate(&conssmap, SCIPblkmem(scip), SCIPgetNConss(scip)) );
282  SCIP_CALL( SCIPcopyProb(scip, heurdata->subscip, varsmap, conssmap, TRUE, probname) );
283 
284  /* copy all variables */
285  SCIP_CALL( SCIPcopyVars(scip, heurdata->subscip, varsmap, conssmap, NULL, NULL, 0, TRUE) );
286 
287  /* copy as many constraints as possible */
288  SCIP_CALL( SCIPcopyConss(scip, heurdata->subscip, varsmap, conssmap, TRUE, FALSE, &heurdata->subscipisvalid) );
289  SCIPhashmapFree(&conssmap);
290  if( !heurdata->subscipisvalid )
291  {
292  SCIPdebugMsg(scip, "failed to copy some constraints to sub-SCIP, continue anyway\n");
293  }
294 
295  /* create arrays translating scip transformed vars to subscip original vars, and vice versa
296  * capture variables in SCIP and sub-SCIP
297  * catch global bound change events
298  */
299 
300  SCIP_CALL( SCIPgetVarsData(heurdata->subscip, &subvars, &heurdata->nsubvars, NULL, NULL, NULL, NULL) );
301 
302  SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars) );
303 
304  heurdata->nvars = nvars;
305  SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars) );
306 
307  /* we need to get all subscip variables, also those which are copies of fixed variables from the main scip
308  * therefore we iterate over the hashmap
309  */
310  for( i = 0; i < SCIPhashmapGetNEntries(varsmap); ++i )
311  {
312  SCIP_HASHMAPENTRY* entry;
313  entry = SCIPhashmapGetEntry(varsmap, i);
314  if( entry != NULL )
315  {
316  var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
317  subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
318  assert(subvar != NULL);
319  assert(SCIPvarGetProbindex(subvar) >= 0);
320  assert(SCIPvarGetProbindex(subvar) <= heurdata->nsubvars);
321 
322  if( SCIPvarIsActive(var) )
323  {
324  assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
325  assert(heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == NULL); /* assert that we have no mapping for this var yet */
326  heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] = subvar;
327  }
328 
329  assert(heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] == NULL); /* assert that we have no mapping for this subvar yet */
330  heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] = var;
331  }
332  }
333 
334  for( i = 0; i < heurdata->nsubvars; ++i )
335  {
336  subvar = SCIPgetVars(heurdata->subscip)[i];
337  assert(SCIPvarGetProbindex(subvar) == i);
338  var = heurdata->var_subscip2scip[i];
339 
340  SCIP_CALL( SCIPcaptureVar(scip, var) );
341  SCIP_CALL( SCIPcaptureVar(heurdata->subscip, subvar) );
342 
343  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetLbGlobal(subvar)));
344  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), SCIPvarGetUbGlobal(subvar)));
345 
346  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, NULL) );
347  }
348 
349 #ifndef NDEBUG
350  for( i = 0; i < heurdata->nvars; ++i )
351  {
352  assert(heurdata->var_scip2subscip[i] == NULL || (SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)vars[i]) == heurdata->var_scip2subscip[i]);
353  }
354  for( i = 0; i < heurdata->nsubvars; ++i )
355  {
356  assert(heurdata->var_subscip2scip[i] != NULL);
357  assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)heurdata->var_subscip2scip[i]) == subvars[i]);
358  }
359 #endif
360 
361  /* do not need hashmap anymore */
362  SCIPhashmapFree(&varsmap);
363 
364  /* do not abort subproblem on CTRL-C */
365  SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "misc/catchctrlc", FALSE) );
366 
367  /* disable keeping solutions from one subscip solve for next solve (with usually different fixings) */
368  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "limits/maxorigsol", 0) );
369 
370 #ifdef SCIP_DEBUG
371  /* for debugging, enable SCIP output */
372  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 5) );
373 #else
374  /* disable output to console */
375  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 0) );
376 #endif
377 
378  /* reset some limits to default values, in case users changed them in main scip (SCIPcopy copies parameter values :-() */
379  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/absgap") );
380  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/bestsol") );
381  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/gap") );
382  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/restarts") );
383  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/solutions") );
384  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/time") );
385  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/totalnodes") );
386 
387  /* we remember here which way (continuous or not) we went, in case all binary and integer vars get fixed in root */
388  heurdata->continuous = SCIPgetNBinVars(heurdata->subscip) == 0 && SCIPgetNIntVars(heurdata->subscip) == 0;
389  if( !heurdata->continuous )
390  {
391  /* set presolve maxrounds and emphasis; always disable components presolver
392  * heuristics and separators were not copied into subscip, so should not need to switch off
393  */
394  if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrounds") )
395  {
396  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", heurdata->maxpresolverounds) );
397  }
398  SCIP_CALL( SCIPsetPresolving(heurdata->subscip, (SCIP_PARAMSETTING)heurdata->presolveemphasis, TRUE) );
399  if( !SCIPisParamFixed(heurdata->subscip, "constraints/components/maxprerounds") )
400  {
401  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "constraints/components/maxprerounds", 0) );
402  }
403  }
404  else
405  {
406  /* for continuous problems, disable presolve and move subscip into a stage where it has a NLP
407  * the only reason why we don't solve the NLP in the main SCIP is that we want global variable bounds for the NLP
408  */
409  SCIP_RETCODE retcode;
410 
411  SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
412 
413  SCIP_CALL( SCIPsetPresolving(heurdata->subscip, SCIP_PARAMSETTING_OFF, TRUE) );
414  SCIP_CALL( SCIPpresolve(heurdata->subscip) );
415 
416  if( SCIPgetStage(heurdata->subscip) != SCIP_STAGE_PRESOLVED || SCIPgetNVars(heurdata->subscip) == 0 )
417  {
418  /* presolve found problem infeasible, solved it, or stopped due to some limit
419  * all a bit strange, since problem should be the same as original, presolve was disabled, and we didn't set any limits
420  * we will give up and not run the heuristic
421  */
422  SCIP_CALL( freeSubSCIP(scip, heurdata) );
423  return SCIP_OKAY;
424  }
425 
426  /* do initial solve, i.e., "solve" root node with node limit 0 (should do scip.c::initSolve and then stop immediately in solve.c::SCIPsolveCIP) */
427  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
428  retcode = SCIPsolve(heurdata->subscip);
429 
430  /* errors in solving the subproblem should not kill the overall solving process
431  * hence, the return code is caught and a warning is printed
432  */
433  if( retcode != SCIP_OKAY )
434  {
435  SCIPwarningMessage(scip, "Error while initializing subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
436  SCIP_CALL( freeSubSCIP(scip, heurdata) );
437  return SCIP_OKAY;
438  }
439 
440  /* If we are in stage "solved" (strange) or have no NLP (also strange), then do not run heuristic, too */
441  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
442  {
443  SCIP_CALL( freeSubSCIP(scip, heurdata) );
444  return SCIP_OKAY;
445  }
446 
447  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVING);
448  assert(SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_NODELIMIT);
449  assert(SCIPisNLPConstructed(heurdata->subscip));
450  }
451 
452  return SCIP_OKAY;
453 }
454 
455 /** process variable global bound change event */
456 static
457 SCIP_DECL_EVENTEXEC(processVarEvent)
458 {
459  SCIP_HEURDATA* heurdata;
460  SCIP_VAR* var;
461  SCIP_VAR* subvar;
462  int idx;
463 
464  assert(scip != NULL);
465  assert(event != NULL);
466  assert(eventdata != NULL);
467  assert(eventhdlr != NULL);
468 
469  heurdata = (SCIP_HEURDATA*)eventdata;
470  assert(heurdata != NULL);
471 
472  var = SCIPeventGetVar(event);
473  assert(var != NULL);
474 
475  idx = SCIPvarGetProbindex(var);
476  /* if event corresponds to an active variable, we can easily look up the corresponding subvar
477  * if it is an inactive variable that has been copied to the subproblem,
478  * then we need to check the subscip2scip mapping
479  * @todo we could do this faster if we keep the variables mapping from SCIPcopy around
480  */
481  if( idx >= 0 )
482  {
483  assert(idx < heurdata->nvars);
484 
485  subvar = heurdata->var_scip2subscip[idx];
486  }
487  else
488  {
489  for( idx = 0; idx < heurdata->nsubvars; ++idx )
490  {
491  if( heurdata->var_subscip2scip[idx] == var )
492  break;
493  }
494  assert(idx < heurdata->nsubvars);
495  subvar = SCIPgetVars(heurdata->subscip)[idx];
496  }
497  assert(subvar != NULL);
498 
500  {
501  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
502  }
503 
505  {
506  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
507  }
508 
509  return SCIP_OKAY;
510 }
511 
512 /* creates a SCIP_SOL in our SCIP space out of the solution from NLP solver in sub-SCIP */
513 static
515  SCIP* scip, /**< SCIP data structure */
516  SCIP_HEUR* heur, /**< heuristic data structure */
517  SCIP_SOL** sol, /**< buffer to store solution value; if pointing to NULL, then a new solution is created, otherwise values in the given one are overwritten */
518  SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
519  )
520 {
521  SCIP_HEURDATA* heurdata;
522  SCIP_VAR** vars;
523  int nvars;
524  SCIP_VAR* var;
525  SCIP_VAR* subvar;
526  SCIP_Real solval;
527  int i;
528 
529  assert(scip != NULL);
530  assert(heur != NULL);
531  assert(sol != NULL);
532 
533  heurdata = SCIPheurGetData(heur);
534  assert(heurdata != NULL);
535  assert(SCIPhasNLPSolution(heurdata->subscip));
536 
537  if( *sol == NULL )
538  {
539  SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
540  }
541  else
542  {
543  SCIPsolSetHeur(*sol, authorheur);
544  }
545 
546  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
547 
548  assert(nvars >= heurdata->nvars);
549  for( i = 0; i < heurdata->nvars; ++i )
550  {
551  var = vars[i];
552  assert(var != NULL);
553  assert(SCIPvarIsActive(var)); /* SCIPgetVarsData should have given us only active vars */
554 
555  subvar = heurdata->var_scip2subscip[i];
556  if( subvar == NULL )
557  solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
558  else
559  solval = SCIPvarGetNLPSol(subvar);
560 
561  assert(solval != SCIP_INVALID); /*lint !e777*/
562  SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
563  }
564 
565  for( ; i < nvars; ++i )
566  {
567  var = vars[i];
568  assert(var != NULL);
569  assert(SCIPvarIsActive(var)); /* SCIPgetVarsData should have given us only active vars */
570 
571  solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
572  SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
573  }
574 
575  return SCIP_OKAY;
576 }
577 
578 /** creates SCIP solution from NLP and tries adding to SCIP or only checks feasibility */
579 static
581  SCIP* scip, /**< original SCIP data structure */
582  SCIP_HEUR* heur, /**< heuristic data structure */
583  SCIP_HEUR* authorheur, /**< the heuristic that should be the author of solution, if any */
584  SCIP_RESULT* result, /**< buffer to store result FOUNDSOL if a solution has been found and accepted */
585  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
586 )
587 {
588  SCIP_HEURDATA* heurdata;
589 
590  assert(scip != NULL);
591  assert(heur != NULL);
592  assert(result != NULL);
593 
594  heurdata = SCIPheurGetData(heur);
595  assert(heurdata != NULL);
596 
597  assert(SCIPhasNLPSolution(heurdata->subscip));
598 
599  if( resultsol == NULL )
600  {
601  /* resultsol NULL means we should try adding the sol to SCIP */
602  if( SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip)) )
603  {
604  /* solution is feasible and should improve upper bound, so try adding it to SCIP */
605  SCIP_SOL* sol;
606  SCIP_Bool stored;
607 
608  sol = NULL;
609  SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
610 
611  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
612 #ifdef SCIP_DEBUG
613  /* print the infeasibilities to stdout */
614  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
615 #else
616  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
617 #endif
618 
619  if( stored )
620  {
621  /* SCIP stored solution (yippi!), so we are done */
622  if( heurdata->nlpverblevel >= 1 )
623  {
624  SCIPinfoMessage(scip, NULL, "SCIP stored solution from NLP solve\n");
625  }
626  else
627  {
628  SCIPdebugMsg(scip, "SCIP stored solution from NLP solve\n");
629  }
630 
631  *result = SCIP_FOUNDSOL;
632  }
633  else
634  {
635  if( heurdata->nlpverblevel >= 1 )
636  {
637  SCIPinfoMessage(scip, NULL, "solution reported by NLP solver not stored by SCIP\n");
638  }
639  else
640  {
641  SCIPdebugMsg(scip, "solution reported by NLP solver not stored by SCIP\n");
642  }
643  }
644  }
645  else if( heurdata->nlpverblevel >= 1 )
646  {
647  SCIPinfoMessage(scip, NULL, "subnlp solution objval %e is above the primal bound %e\n",
648  SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip));
649  }
650  }
651  else
652  {
653  /* only create a solution and pass it back in resultsol, do not add to SCIP */
654  SCIP_Bool feasible;
655 
656  SCIP_CALL( createSolFromNLP(scip, heur, &resultsol, authorheur) );
657 
658  heurdata->lastsol = resultsol;
659 #ifdef SCIP_DEBUG
660  /* print the infeasibilities to stdout */
661  SCIP_CALL( SCIPcheckSol(scip, resultsol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
662 #else
663  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
664 #endif
665  if( feasible )
666  {
667  /* SCIP find solution feasible, so we are done */
668  if( heurdata->nlpverblevel >= 1 )
669  {
670  SCIPinfoMessage(scip, NULL, "solution reported by NLP solver feasible for SCIP\n");
671  }
672  else
673  {
674  SCIPdebugMsg(scip, "solution reported by NLP solver feasible for SCIP\n");
675  }
676  *result = SCIP_FOUNDSOL;
677  }
678  else
679  {
680  if( heurdata->nlpverblevel >= 1 )
681  {
682  SCIPinfoMessage(scip, NULL, "solution reported by NLP solver not feasible for SCIP\n");
683  }
684  else
685  {
686  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP\n");
687  }
688  }
689  }
690 
691  return SCIP_OKAY;
692 }
693 
694 /* creates a SCIP_SOL in our SCIP space out of the SCIP_SOL from a sub-SCIP */
695 static
697  SCIP* scip, /**< SCIP data structure */
698  SCIP_HEUR* heur, /**< heuristic data structure */
699  SCIP_SOL** sol, /**< buffer to store solution value; if pointing to NULL, then a new solution is created, otherwise values in the given one are overwritten */
700  SCIP_SOL* subsol, /**< solution of sub-SCIP */
701  SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
702  )
703 {
704  SCIP_HEURDATA* heurdata;
705  SCIP_VAR** vars;
706  int nvars;
707  SCIP_VAR* var;
708  SCIP_VAR* subvar;
709  SCIP_Real solval;
710  int i;
711 
712  assert(scip != NULL);
713  assert(heur != NULL);
714  assert(sol != NULL);
715  assert(subsol != NULL);
716 
717  heurdata = SCIPheurGetData(heur);
718  assert(heurdata != NULL);
719 
720  if( *sol == NULL )
721  {
722  SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
723  }
724  else
725  {
726  SCIPsolSetHeur(*sol, authorheur);
727  }
728 
729  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
730 
731  assert(nvars >= heurdata->nvars);
732  for( i = 0; i < heurdata->nvars; ++i )
733  {
734  var = vars[i];
735  assert(var != NULL);
736  assert(SCIPvarIsActive(var));
737 
738  subvar = heurdata->var_scip2subscip[i];
739  if( subvar == NULL )
740  solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
741  else
742  solval = SCIPgetSolVal(heurdata->subscip, subsol, subvar);
743 
744  assert(solval != SCIP_INVALID); /*lint !e777*/
745  SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
746  }
747 
748  for( ; i < nvars; ++i )
749  {
750  var = vars[i];
751  assert(var != NULL);
752  assert(SCIPvarIsActive(var));
753 
754  solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
755  SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
756  }
757 
758  return SCIP_OKAY;
759 }
760 
761 /** finds an iteration limit */ /*lint --e{715}*/
762 static
764  SCIP* scip, /**< original SCIP data structure */
765  SCIP_HEURDATA* heurdata /**< heuristic data */
766  )
767 {
768  /* if we hit more often an iterlimit than we were successful (termstatus=okay), then allow for more iterations:
769  * take twice the maximal iterusage on solves that hit the iterlimit
770  */
771  if( heurdata->nnlpsolvesiterlim > heurdata->nnlpsolvesokay )
772  return MAX(heurdata->itermin, 2 * heurdata->iterusediterlim); /*lint !e712*/
773 
774  /* if we had sufficiently many successful solves, then take twice the average of previous iterusages on successful solves */
775  if( heurdata->nnlpsolvesokay >= heurdata->ninitsolves )
776  return MAX(heurdata->itermin, 2 * heurdata->iterusedokay / heurdata->nnlpsolvesokay); /*lint !e712*/
777 
778  /* if we had too few successful solves, then still ensure that we allow for at least iterinit iterations */
779  if( heurdata->nnlpsolvesokay > 0 )
780  return MAX3(heurdata->itermin, heurdata->iterinit, 2 * heurdata->iterusedokay / heurdata->nnlpsolvesokay); /*lint !e712*/
781 
782  /* if we had no successful solve so far and none that hit an iterlimit, e.g., we are at the first NLP solve, then use iterinit */
783  return MAX(heurdata->itermin, heurdata->iterinit);
784 }
785 
786 /** solves the subNLP specified in subscip */
787 static
789  SCIP* scip, /**< original SCIP data structure */
790  SCIP_HEUR* heur, /**< heuristic data structure */
791  SCIP_RESULT* result, /**< buffer to store result, DIDNOTFIND, FOUNDSOL, or CUTOFF */
792  SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
793  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
794  )
795 {
796  SCIP_HEURDATA* heurdata = SCIPheurGetData(heur);
797  SCIP_RETCODE retcode;
798  SCIP_Real* startpoint;
799  SCIP_VAR* var;
800  SCIP_VAR* subvar;
801  int i;
802  SCIP_HEUR* authorheur; /* the heuristic which will be the author of a solution, if found */
803  SCIP_Real timelimit;
804  SCIP_Bool expectinfeas;
805  SCIP_NLPSTATISTICS nlpstatistics;
806 
807  assert(scip != NULL);
808  assert(heur != NULL);
809  assert(heurdata != NULL);
810  assert(result != NULL);
811  assert(SCIPisTransformed(heurdata->subscip));
812 
813  /* get remaining SCIP solve time; if no time left, then stop */
814  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
815  if( !SCIPisInfinity(scip, timelimit) )
816  {
817  timelimit -= SCIPgetSolvingTime(scip);
818  if( timelimit <= 0.0 )
819  return SCIP_OKAY;
820  }
821  /* set timelimit for NLP solve and in case presolve is unexpectedly expensive */
822  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/time", timelimit) );
823 
824  /* if the refpoint comes from a heuristic, then make it the author of a found solution,
825  * otherwise let the subNLP heuristic claim authorship
826  * TODO: I doubt that this has much effect; for the statistics, the number of solutions found by a heuristic
827  * seems to be computed as the increase in number of solutions before and after a heuristic is run
828  * check this and maybe change
829  */
830  if( refpoint == NULL || SCIPsolGetHeur(refpoint) == NULL )
831  authorheur = heur;
832  else
833  authorheur = SCIPsolGetHeur(refpoint);
834 
835  if( !heurdata->continuous )
836  {
837  /* presolve sub-SCIP
838  * set node limit to 1 so that presolve can go
839  */
840  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
841  SCIP_CALL( SCIPpresolve(heurdata->subscip) );
842 
843  /* count one presolve round as on NLP iteration for now
844  * plus one extra for all the setup cost
845  * this is mainly to avoid that the primal heuristics runs all the time on instances that are solved in the subscip-presolve
846  */
847  heurdata->iterused += 1 + SCIPgetNPresolRounds(scip); /*lint !e776*/
848 
849  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED )
850  {
851  /* presolve probably found the subproblem infeasible */
852  SCIPdebugMsg(scip, "SCIP returned from presolve in stage solved with status %d and %d sols\n", SCIPgetStatus(heurdata->subscip), SCIPgetNSols(heurdata->subscip));
853  /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
854  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
855  *result = SCIP_CUTOFF;
856  }
857  else if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING )
858  {
859  /* presolve was stopped because some still existing limit was hit (e.g., memory) */
860  SCIPdebugMsg(scip, "SCIP returned from presolve in stage presolving with status %d and %d sols\n", SCIPgetStatus(heurdata->subscip), SCIPgetNSols(heurdata->subscip));
861  /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
862  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
863  *result = SCIP_CUTOFF;
864  }
865  else
866  {
867  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVED);
868 
869  if( SCIPgetNVars(heurdata->subscip) > 0 )
870  {
871  /* do initial solve, i.e., "solve" root node with node limit 0 (should do scip.c::initSolve and then stop immediately in solve.c::SCIPsolveCIP) */
872  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
873  retcode = SCIPsolve(heurdata->subscip);
874 
875  /* If no NLP was constructed, then there were no nonlinearities after presolve.
876  * So we increase the nodelimit to 1 and hope that SCIP will find some solution to this probably linear subproblem.
877  */
878  if( retcode == SCIP_OKAY && SCIPgetStage(heurdata->subscip) != SCIP_STAGE_SOLVED && !SCIPisNLPConstructed(heurdata->subscip) )
879  {
880  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
881  retcode = SCIPsolve(heurdata->subscip);
882  }
883  }
884  else
885  {
886  /* If all variables were removed by presolve, but presolve did not end with status SOLVED,
887  * then we run solve, still with nodelimit=1, and hope to find some (maybe trivial) solution.
888  */
889  retcode = SCIPsolve(heurdata->subscip);
890  }
891 
892  /* errors in solving the subproblem should not kill the overall solving process
893  * hence, the return code is caught and a warning is printed
894  */
895  if( retcode != SCIP_OKAY )
896  {
897  SCIPwarningMessage(scip, "Error while solving subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
898  return SCIP_OKAY;
899  }
900  }
901 
902  /* we should either have variables, or the problem was trivial, in which case it should have been presolved or solved */
903  assert(SCIPgetNVars(heurdata->subscip) > 0 || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
904 
905  SCIPdebug( SCIP_CALL( SCIPprintStatistics(heurdata->subscip, NULL) ); )
906 
907  /* if sub-SCIP found solutions already, then pass them to main scip */
908  for( i = 0; i < SCIPgetNSols(heurdata->subscip); ++i )
909  {
910  if( resultsol == NULL )
911  {
912  SCIP_Bool stored;
913  SCIP_SOL* sol;
914 
915  sol = NULL;
916  SCIP_CALL( createSolFromSubScipSol(scip, heur, &sol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
917 
918  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
919  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
920  if( stored )
921  {
922  if( heurdata->nlpverblevel >= 1 )
923  {
924  SCIPinfoMessage(scip, NULL, "SCIP stored solution from sub-SCIP root node\n");
925  }
926  else
927  {
928  SCIPdebugMsg(scip, "SCIP stored solution from sub-SCIP root node\n");
929  }
930  *result = SCIP_FOUNDSOL;
931  break;
932  }
933  else
934  {
935  if( heurdata->nlpverblevel >= 1 )
936  {
937  SCIPinfoMessage(scip, NULL, "SCIP did not store sub-SCIP optimal solution\n");
938  }
939  else
940  {
941  SCIPdebugMsg(scip, "SCIP did not store sub-SCIP optimal solution\n");
942  }
943  }
944  }
945  else
946  {
947  SCIP_Bool feasible;
948 
949  SCIP_CALL( createSolFromSubScipSol(scip, heur, &resultsol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
950 
951  heurdata->lastsol = resultsol;
952  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
953  if( feasible )
954  {
955  if( heurdata->nlpverblevel >= 1 )
956  {
957  SCIPinfoMessage(scip, NULL, "SCIP solution from sub-SCIP root node is feasible\n");
958  }
959  else
960  {
961  SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is feasible\n");
962  }
963  *result = SCIP_FOUNDSOL;
964  break;
965  }
966  else
967  {
968  if( heurdata->nlpverblevel >= 1 )
969  {
970  SCIPinfoMessage(scip, NULL, "SCIP solution from sub-SCIP root node is not feasible\n");
971  }
972  else
973  {
974  SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is not feasible\n");
975  }
976  }
977  }
978  }
979 
980  /* if subscip is infeasible here, we signal this to the caller */
981  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
982  {
983  if( heurdata->nlpverblevel >= 1 )
984  {
985  SCIPinfoMessage(scip, NULL, "sub-SCIP detected infeasibility\n");
986  }
987  else
988  {
989  SCIPdebugMsg(scip, "sub-SCIP detected infeasibility\n");
990  }
991 
992  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
993  *result = SCIP_CUTOFF;
994  return SCIP_OKAY;
995  }
996 
997  /* if we stopped for some other reason, or there is no NLP, we also stop */
998  if( SCIPgetStage(heurdata->subscip) <= SCIP_STAGE_PRESOLVED || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
999  return SCIP_OKAY;
1000 
1001  /* in most cases, the status should be nodelimit
1002  * in some cases, if the sub-SCIP is very easy, it may report optimal, so we do not need invoke an NLP solver
1003  * if the presolve found the problem infeasible, then there is no use in solving an NLP
1004  * if the user interrupted or a timelimit was reached, then we should also stop here
1005  * unbounded is very unlikely to happen, in most cases, it should have been concluded in the main scip already
1006  */
1007  switch( SCIPgetStatus(heurdata->subscip) )
1008  {
1009  case SCIP_STATUS_NODELIMIT:
1010  break; /* this is the status that is most likely happening */
1013  case SCIP_STATUS_GAPLIMIT:
1014  case SCIP_STATUS_SOLLIMIT:
1016  /* these should not happen, but if one does, it's safe to return */
1017  SCIPABORT(); /*lint -fallthrough*/
1018  case SCIP_STATUS_OPTIMAL:
1021  case SCIP_STATUS_TIMELIMIT:
1022  case SCIP_STATUS_MEMLIMIT:
1023  case SCIP_STATUS_UNBOUNDED:
1024  case SCIP_STATUS_INFORUNBD:
1025  return SCIP_OKAY;
1026  default:
1027  SCIPerrorMessage("unexpected status of sub-SCIP: <%d>\n", SCIPgetStatus(heurdata->subscip));
1028  return SCIP_ERROR;
1029  } /*lint !e788*/
1030  }
1031  else
1032  {
1033  /* for continuous problem, createSubSCIP() should have put us into a state where we can invoke the NLP solver */
1034  assert(SCIPisNLPConstructed(heurdata->subscip));
1035  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVING);
1036  assert(SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_NODELIMIT);
1037  }
1038 
1039  /* set starting values (=refpoint, if not NULL; otherwise LP solution (or pseudo solution)) */
1040  SCIP_CALL( SCIPallocBufferArray(scip, &startpoint, SCIPgetNNLPVars(heurdata->subscip)) );
1041 
1042  if( heurdata->nlpverblevel >= 3 )
1043  {
1044  SCIPinfoMessage(scip, NULL, "set NLP starting point\n");
1045  }
1046 
1047  for( i = 0; i < SCIPgetNNLPVars(heurdata->subscip); ++i )
1048  {
1049  SCIP_Real scalar;
1050  SCIP_Real constant;
1051 
1052  subvar = SCIPgetNLPVars(heurdata->subscip)[i];
1053 
1054  /* gets corresponding original variable */
1055  scalar = 1.0;
1056  constant = 0.0;
1057  SCIP_CALL( SCIPvarGetOrigvarSum(&subvar, &scalar, &constant) );
1058  if( subvar == NULL )
1059  {
1060  startpoint[i] = constant;
1061 
1062  if( heurdata->nlpverblevel >= 3 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1063  {
1064  SCIPinfoMessage(scip, NULL, "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1065  }
1066 
1067  continue;
1068  }
1069 
1070  assert(SCIPvarGetProbindex(subvar) >= 0);
1071  assert(SCIPvarGetProbindex(subvar) < heurdata->nsubvars);
1072  var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
1073  if( var == NULL || REALABS(SCIPgetSolVal(scip, refpoint, var)) > 1.0e+12 )
1074  startpoint[i] = MIN(MAX(0.0, SCIPvarGetLbGlobal(subvar)), SCIPvarGetUbGlobal(subvar)); /*lint !e666*/
1075  else
1076  /* scalar*subvar+constant corresponds to nlpvar[i], so nlpvar[i] gets value scalar*varval+constant */
1077  startpoint[i] = scalar * SCIPgetSolVal(scip, refpoint, var) + constant;
1078 
1079  if( heurdata->nlpverblevel >= 3 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1080  {
1081  SCIPinfoMessage(scip, NULL, "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1082  }
1083  }
1084  SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, startpoint) );
1085 
1086  SCIPfreeBufferArray(scip, &startpoint);
1087 
1088  *result = SCIP_DIDNOTFIND;
1089 
1090  /* if we had many (fraction > expectinfeas) infeasible NLPs, then tell NLP solver to expect an infeasible problem */
1091  expectinfeas = FALSE;
1092  if( heurdata->expectinfeas == 0.0 ) /* to keep original behavior on default settings */
1093  expectinfeas = TRUE;
1094  else if( heurdata->nnlpsolvesokay > heurdata->ninitsolves && heurdata->nnlpsolvesinfeas > heurdata->expectinfeas * heurdata->nnlpsolvesokay )
1095  expectinfeas = TRUE;
1096 
1097  /* let the NLP solver do its magic */
1098  SCIPdebugMsg(scip, "start NLP solve with iteration limit %d\n", calcIterLimit(scip, heurdata));
1099  SCIP_CALL( SCIPsolveNLP(heurdata->subscip,
1100  .iterlimit = calcIterLimit(scip, heurdata),
1101  .opttol = heurdata->opttol,
1102  .feastol = heurdata->feastol,
1103  .verblevel = (unsigned short)heurdata->nlpverblevel,
1104  .expectinfeas = expectinfeas
1105  ) ); /*lint !e666*/
1106 
1107  SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
1108  SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
1109 
1110  /* add NLP solve statistics from subscip to main SCIP, so they show up in final statistics
1111  * for continuous problems, we also ask to reset statistics, since we do not retransform subSCIP in the next run (which would reset all stats)
1112  * (merging statistics once in exitsol is too late, since they may be printed before)
1113  */
1114  SCIPmergeNLPIStatistics(heurdata->subscip, scip, heurdata->continuous);
1115 
1116  if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_OUTOFMEMORY )
1117  {
1118  /* oops, something did not go well at all */
1119  if( heurdata->nlpverblevel >= 1 )
1120  {
1121  SCIPinfoMessage(scip, NULL, "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d.\n",
1122  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip));
1123  }
1124 
1125  ++(heurdata->nseriousnlpierror);
1127  "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d. This was the %d%s successive time.\n",
1128  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip), heurdata->nseriousnlpierror,
1129  heurdata->nseriousnlpierror == 1 ? "st" : heurdata->nseriousnlpierror == 2 ? "nd" : heurdata->nseriousnlpierror == 3 ? "rd" : "th");
1130  if( heurdata->nseriousnlpierror >= 5 )
1131  {
1132  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Will not run subNLP heuristic again for this run.\n");
1133  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1134  }
1135  return SCIP_OKAY;
1136  }
1137  heurdata->nseriousnlpierror = 0;
1138 
1139  SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, &nlpstatistics) );
1140 
1141  SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds; violation cons %g, bounds %g\n",
1142  nlpstatistics.niterations, nlpstatistics.totaltime, nlpstatistics.consviol, nlpstatistics.boundviol);
1143 
1144  heurdata->iterused += nlpstatistics.niterations;
1145  ++heurdata->nnlpsolves;
1146  if( SCIPgetNLPTermstat(heurdata->subscip) == SCIP_NLPTERMSTAT_OKAY )
1147  {
1148  ++heurdata->nnlpsolvesokay;
1149  heurdata->iterusedokay += nlpstatistics.niterations;
1150 
1151  if( (SCIPgetNLPSolstat(heurdata->subscip) == SCIP_NLPSOLSTAT_GLOBINFEASIBLE) || (SCIPgetNLPSolstat(heurdata->subscip) == SCIP_NLPSOLSTAT_LOCINFEASIBLE) )
1152  ++heurdata->nnlpsolvesinfeas;
1153  }
1154  else if( SCIPgetNLPTermstat(heurdata->subscip) == SCIP_NLPTERMSTAT_ITERLIMIT )
1155  {
1156  ++heurdata->nnlpsolvesiterlim;
1157  heurdata->iterusediterlim = MAX(heurdata->iterusediterlim, nlpstatistics.niterations);
1158  }
1159 
1160  if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
1161  return SCIP_OKAY;
1162 
1163  /* create SCIP solution, check whether feasible, and try adding to SCIP (if resultsol==NULL) */
1164  SCIP_CALL( processNLPSol(scip, heur, authorheur, result, resultsol) );
1165 
1166  if( *result == SCIP_FOUNDSOL || !SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip)) )
1167  return SCIP_OKAY;
1168 
1169  /* if solution was not added to SCIP, then either
1170  * - the objective function value was not good enough,
1171  * - the NLP was missing some constraints of the original CIP, or
1172  * - the solution is feasible for the presolved CIP, but slightly infeasible for the unpresolved problem
1173  *
1174  * The first case we can check easily (see if() above).
1175  * For the last case, we try whether tightening the feasibility tolerance for the NLP solve may help.
1176  * If that doesn't help, we guess that we are in the second case and will not try a tighter feastol anymore.
1177  */
1178 
1179  /* if we tried with a tighter feastol before, but solution was still not accepted, then don't try again */
1180  if( heurdata->tighterfeastolfailed )
1181  return SCIP_OKAY;
1182 
1183  /* if resolve with tighter feastol is disabled, then don't do anything */
1184  if( heurdata->feastolfactor == 1.0 )
1185  return SCIP_OKAY;
1186 
1187  /* if we have already used a tighter feastol, then give up */
1188  if( heurdata->feastol < SCIPfeastol(scip) )
1189  return SCIP_OKAY;
1190 
1191  /* if original CIP is continuous, then we have not done any presolve, so it shouldn't have caused problems */
1192  if( heurdata->continuous )
1193  return SCIP_OKAY;
1194 
1195  /* if solution is NLP-feasible for a tightened tolerance already, then there is no use in resolving with that tighter feastol */
1196  if( MAX(nlpstatistics.consviol, nlpstatistics.boundviol) <= heurdata->feastolfactor * heurdata->feastol )
1197  return SCIP_OKAY;
1198 
1199  /* let the NLP solver redo its magic
1200  * as iterlimit, we use the number of iterations it took for the first solve, or itermin
1201  */
1202  SCIPdebugMsg(scip, "start NLP solve with iteration limit %d\n", calcIterLimit(scip, heurdata));
1203  SCIP_CALL( SCIPsolveNLP(heurdata->subscip,
1204  .iterlimit = MAX(heurdata->itermin, nlpstatistics.niterations),
1205  .opttol = heurdata->opttol,
1206  .feastol = heurdata->feastolfactor * heurdata->feastol,
1207  .verblevel = (unsigned short)heurdata->nlpverblevel,
1208  .warmstart = TRUE
1209  ) ); /*lint !e666*/
1210 
1211  SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
1212  SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
1213 
1214  /* add NLP solve statistics from subscip to main SCIP again, so they show up in final statistics */
1215  SCIPmergeNLPIStatistics(heurdata->subscip, scip, heurdata->continuous);
1216 
1217  /* some serious problem: just pretend it didn't happen */
1218  if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_OUTOFMEMORY )
1219  return SCIP_OKAY;
1220 
1221  SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, &nlpstatistics) );
1222  SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds; violation cons %g, bounds %g\n",
1223  nlpstatistics.niterations, nlpstatistics.totaltime, nlpstatistics.consviol, nlpstatistics.boundviol);
1224 
1225  /* we account only the extra iterations for this unusual NLP solve, but don't add anything else to our statistics (nnlpsolved, etc) */
1226  heurdata->iterused += nlpstatistics.niterations;
1227 
1228  /* if failed to get a feasible NLP solution now, then nothing to do */
1229  if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
1230  return SCIP_OKAY;
1231 
1232  SCIP_CALL( processNLPSol(scip, heur, authorheur, result, resultsol) );
1233 
1234  /* if successful, then use tighter feastol for all NLP solves from now on
1235  * if still not accepted, then don't try this again
1236  * (maybe the NLP is incomplete; we could give up on running this heur completely, but for now let the successrate factor in heurExec take care of running it less often)
1237  */
1238  if( *result == SCIP_FOUNDSOL )
1239  heurdata->feastol *= heurdata->feastolfactor;
1240  else
1241  heurdata->tighterfeastolfailed = TRUE;
1242 
1243  return SCIP_OKAY;
1244 }
1245 
1246 
1247 /** adds a set covering or bound disjunction constraint to the original problem */
1248 static
1250  SCIP* scip, /**< SCIP data structure */
1251  SCIP_HEURDATA* heurdata /**< heuristic data */
1252  )
1253 {
1254  SCIP_VAR** subvars;
1255  int nsubvars;
1256  int nsubbinvars;
1257  int nsubintvars;
1258  SCIP_VAR* var;
1259  SCIP_VAR* subvar;
1260  SCIP_CONS* cons;
1261  SCIP_VAR** consvars;
1262  int nconsvars;
1263  char name[SCIP_MAXSTRLEN];
1264  int i;
1265  SCIP_Real fixval;
1266 
1267  assert(scip != NULL);
1268 
1269  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1270  assert(nsubvars == heurdata->nsubvars);
1271 
1272  if( nsubbinvars == 0 && nsubintvars == 0 )
1273  {
1274  /* If we did not fix any discrete variables but found the "sub"CIP infeasible, then also the CIP is infeasible. */
1275  SCIPdebugMsg(scip, "heur_subnlp found subCIP infeasible after fixing no variables, something is strange here...\n");
1276  return SCIP_OKAY;
1277  }
1278 
1279  /* initialize */
1280  cons = NULL;
1281  consvars = NULL;
1282 
1283  /* create constraint name */
1284  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "subnlp_cutoff");
1285 
1286  /* if all discrete variables in the CIP are binary, then we create a set covering constraint
1287  * sum_{x_i fixed at 0} x_i + sum_{x_i fixed at 1} ~x_i >= 1
1288  */
1289  if( nsubintvars == 0 )
1290  {
1291  /* allocate memory for constraint variables */
1292  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars) );
1293 
1294  /* get fixations of discrete variables
1295  * to be sure, we take the values that were put into the subCIP before
1296  */
1297  nconsvars = 0;
1298  for( i = nsubbinvars - 1; i >= 0; --i )
1299  {
1300  subvar = subvars[i];
1301  assert(SCIPvarGetProbindex(subvar) == i);
1302 
1303  var = heurdata->var_subscip2scip[i];
1304  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1305  if( var == NULL )
1306  continue;
1307 
1308  fixval = SCIPvarGetLbGlobal(subvar);
1309  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1310  assert(fixval == 0.0 || fixval == 1.0); /* we have rounded values before fixing */
1311 
1312  if( fixval == 0.0 )
1313  {
1314  /* variable fixed at lower bound */
1315  consvars[nconsvars] = var;
1316  }
1317  else
1318  {
1319  SCIP_CALL( SCIPgetNegatedVar(scip, var, &consvars[nconsvars]) );
1320  }
1321 
1322  ++nconsvars;
1323  }
1324 
1325  /* create conflict constraint
1326  * In undercover, ConsLogicor is used, since then the inequality is not added to the LP.
1327  * However, I may want to use Setcover to avoid that the same fixing is computed by some LP based heuristic again.
1328  */
1329  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nconsvars, consvars,
1331  }
1332  else
1333  {
1334  /* if there are also integer variable, then create a bound disjunction constraint
1335  * x_1 >= fixval_1 + 1 || x_1 <= fixval_1 - 1 || x_2 >= fixval_2 + 1 || x_2 <= fixval_2 - 1 || ...
1336  */
1337  SCIP_BOUNDTYPE* boundtypes;
1338  SCIP_Real* bounds;
1339 
1340  /* allocate memory for constraint variables, boundtypes, and bounds
1341  * (there should be at most two literals for each integer variable)
1342  */
1343  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars + 2*nsubintvars) );
1344  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nsubbinvars + 2*nsubintvars) );
1345  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nsubbinvars + 2*nsubintvars) );
1346 
1347  /* get fixations of discrete variables
1348  * to be sure, we take the values that were put into the subCIP before
1349  */
1350  nconsvars = 0;
1351  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1352  {
1353  subvar = subvars[i];
1354  assert(SCIPvarGetProbindex(subvar) == i);
1355 
1356  var = heurdata->var_subscip2scip[i];
1357  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1358 
1359  if( var == NULL )
1360  continue;
1361 
1362  fixval = SCIPvarGetLbGlobal(subvar);
1363  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1364  assert(SCIPceil(scip, fixval - 0.5) == fixval); /* we have rounded values before fixing */ /*lint !e777*/
1365  assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY || SCIPvarGetLbGlobal(var) == fixval || SCIPvarGetUbGlobal(var) == fixval); /* for binaries, the fixval should be either 0.0 or 1.0 */ /*lint !e777*/
1366 
1367  if( SCIPvarGetLbGlobal(var) < fixval )
1368  {
1369  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1370 
1371  /* literal x_i <= fixval-1 */
1372  boundtypes[nconsvars] = SCIP_BOUNDTYPE_UPPER;
1373  bounds[nconsvars] = fixval - 1.0;
1374  consvars[nconsvars] = var;
1375  ++nconsvars;
1376  }
1377 
1378  if( SCIPvarGetUbGlobal(var) > fixval )
1379  {
1380  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1381 
1382  /* literal x_i >= fixval+1 */
1383  boundtypes[nconsvars] = SCIP_BOUNDTYPE_LOWER;
1384  bounds[nconsvars] = fixval + 1.0;
1385  consvars[nconsvars] = var;
1386  ++nconsvars;
1387  }
1388  }
1389 
1390  /* create conflict constraint */
1391  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, nconsvars, consvars, boundtypes, bounds,
1393 
1394  SCIPfreeBufferArray(scip, &bounds);
1395  SCIPfreeBufferArray(scip, &boundtypes);
1396  SCIPfreeBufferArray(scip, &consvars);
1397  }
1398 
1399  /* add and release constraint if created successfully */
1400  if( cons != NULL )
1401  {
1402  SCIPdebugMsg(scip, "adding constraint to forbid fixation in main problem\n");
1403  /* SCIPdebugPrintCons(scip, cons, NULL); */
1404  SCIP_CALL( SCIPaddCons(scip, cons) );
1405  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1406  }
1407 
1408  /* free memory */
1409  SCIPfreeBufferArrayNull(scip, &consvars);
1410 
1411  return SCIP_OKAY;
1412 }
1413 
1414 
1415 /*
1416  * Callback methods of primal heuristic
1417  */
1418 
1419 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1420 static
1421 SCIP_DECL_HEURCOPY(heurCopySubNlp)
1422 { /*lint --e{715}*/
1423  assert(scip != NULL);
1424  assert(heur != NULL);
1425  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1426 
1427  /* call inclusion method of primal heuristic */
1429 
1430  return SCIP_OKAY;
1431 }
1432 
1433 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1434 static
1435 SCIP_DECL_HEURFREE(heurFreeSubNlp)
1436 {
1437  SCIP_HEURDATA* heurdata;
1438  assert(scip != NULL);
1439  assert(heur != NULL);
1440 
1441  heurdata = SCIPheurGetData(heur);
1442  assert(heurdata != NULL);
1443  assert(heurdata->subscip == NULL);
1444  assert(heurdata->var_subscip2scip == NULL);
1445  assert(heurdata->var_scip2subscip == NULL);
1446  assert(heurdata->startcand == NULL);
1447 
1448  SCIPfreeBlockMemory(scip, &heurdata);
1449 
1450  return SCIP_OKAY;
1451 }
1452 
1453 /** initialization method of primal heuristic (called after problem was transformed) */
1454 static
1455 SCIP_DECL_HEURINIT(heurInitSubNlp)
1456 { /*lint --e{715}*/
1457  SCIP_HEURDATA* heurdata;
1458 
1459  assert(scip != NULL);
1460  assert(heur != NULL);
1461 
1462  heurdata = SCIPheurGetData(heur);
1463  assert(heurdata != NULL);
1464  assert(heurdata->subscip == NULL);
1465 
1466  /* reset or initialize some flags and counters */
1467  heurdata->feastol = SCIPfeastol(scip);
1468  heurdata->tighterfeastolfailed = FALSE;
1469  heurdata->triedsetupsubscip = FALSE;
1470  heurdata->nseriousnlpierror = 0;
1471  heurdata->iterused = 0;
1472  heurdata->iterusedokay = 0;
1473  heurdata->iterusediterlim = 0;
1474  heurdata->nnlpsolves = 0;
1475  heurdata->nnlpsolvesokay = 0;
1476  heurdata->nnlpsolvesiterlim = 0;
1477  heurdata->nnlpsolvesinfeas = 0;
1478 
1479  return SCIP_OKAY;
1480 }
1481 
1482 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1483 static
1484 SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
1485 {
1486  assert(scip != NULL);
1487  assert(heur != NULL);
1488 
1489  /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
1490  if( SCIPheurGetFreqofs(heur) == 0 )
1492 
1493  return SCIP_OKAY;
1494 }
1495 
1496 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1497 static
1498 SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
1499 {
1500  SCIP_HEURDATA* heurdata;
1501  assert(scip != NULL);
1502  assert(heur != NULL);
1503 
1504  /* get heuristic's data */
1505  heurdata = SCIPheurGetData(heur);
1506  assert(heurdata != NULL);
1507 
1508  if( heurdata->subscip != NULL )
1509  {
1510  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1511  heurdata->triedsetupsubscip = FALSE;
1512  }
1513 
1514  /* free start candidate */
1515  if( heurdata->startcand != NULL )
1516  {
1517  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
1518  }
1519 
1521 
1522  return SCIP_OKAY;
1523 }
1524 
1525 
1526 /** execution method of primal heuristic */
1527 static
1528 SCIP_DECL_HEUREXEC(heurExecSubNlp)
1529 { /*lint --e{666,715}*/
1530  SCIP_HEURDATA* heurdata;
1531  SCIP_Bool runheur;
1532  SCIP_Real itercontingent;
1533 
1534  assert(scip != NULL);
1535  assert(heur != NULL);
1536 
1537  /* obviously, we did not do anything yet */
1538  *result = SCIP_DIDNOTRUN;
1539 
1540  /* get heuristic's data */
1541  heurdata = SCIPheurGetData(heur);
1542  assert(heurdata != NULL);
1543 
1544  /* if triedsetupsubscip and keepcopy and subscip == NULL, then we tried to setup a subSCIP before, but failed due to some serious error
1545  * thus, we should do not need to try again
1546  *
1547  * otherwise, we continue and let SCIPapplyHeurSubNlp try to create subscip
1548  */
1549  if( heurdata->subscip == NULL && heurdata->keepcopy && heurdata->triedsetupsubscip )
1550  return SCIP_OKAY;
1551 
1552  /* before we run the heuristic for the first time, check whether we want to run the heuristic at all */
1553  if( SCIPheurGetNCalls(heur) == 0 )
1554  {
1555  SCIP_CALL( runHeuristic(scip, &runheur) );
1556  if( !runheur )
1557  return SCIP_OKAY;
1558  }
1559 
1560  if( heurdata->startcand == NULL )
1561  {
1562  /* if no start candidate is given, we consider the LP solution of the current node */
1563 
1564  /* however, if the node was already detected to be infeasible, then there is no point to look at its LP solution */
1565  if( nodeinfeasible )
1566  return SCIP_OKAY;
1567 
1568  /* at least if we are not called the first time, we call the heuristic only if an optimal LP solution is available
1569  * if we are called the first time and the LP is unbounded, then we are quite desperate and still give the NLP a try
1570  */
1572  {
1574  {
1575  *result = SCIP_DELAYED;
1576  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and no LP solution available; LP status = %d\n", SCIPgetLPSolstat(scip));
1577  return SCIP_OKAY;
1578  }
1579  else
1580  {
1581  SCIPdebugMsg(scip, "LP is unbounded in root node, so we are quite desperate; run NLP heuristic and pray\n");
1582  }
1583  }
1584  else if( SCIPgetNLPBranchCands(scip) > 0 )
1585  {
1586  /* only call heuristic, if there are no fractional variables */
1587  *result = SCIP_DELAYED;
1588  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and current LP solution is fractional\n");
1589  return SCIP_OKAY;
1590  }
1592  {
1593  /* only call heuristic, if there is still room for improvement in the current node */
1594  SCIPdebugMsg(scip, "NLP heuristic delayed because lower and upper bound coincide in current node\n");
1595  return SCIP_OKAY;
1596  }
1597  SCIPdebugMsg(scip, "using current LP solution as startcand\n");
1598  }
1599  else
1600  {
1601  SCIPdebugMsg(scip, "have startcand from heur %s\n", SCIPsolGetHeur(heurdata->startcand) ? SCIPheurGetName(SCIPsolGetHeur(heurdata->startcand)) : "NULL");
1602  }
1603 
1604  /* check if enough nodes have been processed so that we want to run the heuristic again */
1605 
1606  /* compute the contingent on number of iterations that the NLP solver is allowed to use
1607  * we make it depending on the current number of processed nodes
1608  */
1609  itercontingent = heurdata->nodesfactor * (SCIPgetNNodes(scip) + heurdata->nodesoffset);
1610  /* weight by previous success of heuristic if we have been running already
1611  * require at least ninitsolves many runs that didn't run into the NLP iterlimit
1612  * (so if we are still in the phase of finding a good iterlimit, do not consider success rate so far)
1613  */
1614  if( heurdata->successrateexp > 0.0 && SCIPheurGetNCalls(heur) - heurdata->nnlpsolvesiterlim >= heurdata->ninitsolves )
1615  itercontingent *= pow((SCIPheurGetNSolsFound(heur) + 1.0) / (SCIPheurGetNCalls(heur) + 1.0), heurdata->successrateexp);
1616  /* subtract the number of iterations used for all NLP solves so far */
1617  itercontingent -= heurdata->iterused;
1618 
1619  /* check whether the itercontingent is sufficient for the iteration limit we would use */
1620  if( itercontingent < calcIterLimit(scip, heurdata) )
1621  {
1622  /* not enough iterations left to start NLP solver */
1623  SCIPdebugMsg(scip, "skip NLP heuristic; contingent=%f; iterlimit=%d; success ratio=%g\n",
1624  itercontingent, calcIterLimit(scip, heurdata), pow((SCIPheurGetNSolsFound(heur) + 1.0) / (SCIPheurGetNCalls(heur) + 1.0), heurdata->successrateexp));
1625  return SCIP_OKAY;
1626  }
1627 
1628  /* so far we have not found any solution, but now we are willing to search for one */
1629  *result = SCIP_DIDNOTFIND;
1630 
1631  if( heurdata->nlpverblevel >= 1 )
1632  {
1633  SCIPinfoMessage(scip, NULL, "calling subnlp heuristic\n");
1634  }
1635 
1636  SCIP_CALL( SCIPapplyHeurSubNlp(scip, heur, result, heurdata->startcand, NULL) );
1637 
1638  /* SCIP does not like cutoff as return, so we say didnotfind, since we did not find a solution */
1639  if( *result == SCIP_CUTOFF )
1640  *result = SCIP_DIDNOTFIND;
1641 
1642  /* forget startcand */
1643  if( heurdata->startcand != NULL )
1644  {
1645  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
1646  }
1647 
1648  /* reset timing, if it was changed temporary (at the root node) */
1649  if( heurtiming != HEUR_TIMING )
1651 
1652  return SCIP_OKAY;
1653 }
1654 
1655 
1656 /*
1657  * primal heuristic specific interface methods
1658  */
1659 
1660 /** creates the NLP local search primal heuristic and includes it in SCIP */
1662  SCIP* scip /**< SCIP data structure */
1663  )
1664 {
1665  SCIP_HEURDATA* heurdata;
1666  SCIP_HEUR* heur;
1667 
1668  /* create Nlp primal heuristic data */
1669  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1670  BMSclearMemory(heurdata);
1671 
1672  /* include variable event handler */
1673  heurdata->eventhdlr = NULL;
1674  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, HEUR_NAME, "propagates a global bound change to the sub-SCIP",
1675  processVarEvent, NULL) );
1676  assert(heurdata->eventhdlr != NULL);
1677 
1678  /* include primal heuristic */
1679  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1681  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecSubNlp, heurdata) );
1682 
1683  assert(heur != NULL);
1684 
1685  /* set non-NULL pointers to callback methods */
1686  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopySubNlp) );
1687  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeSubNlp) );
1688  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitSubNlp) );
1689  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolSubNlp) );
1690  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolSubNlp) );
1691 
1692  /* add Nlp primal heuristic parameters */
1693  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpverblevel",
1694  "verbosity level of NLP solver",
1695  &heurdata->nlpverblevel, FALSE, 0, 0, USHRT_MAX, NULL, NULL) );
1696 
1697  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nodesoffset",
1698  "number of nodes added to the current number of nodes when computing itercontingent (higher value runs heuristic more often in early search)",
1699  &heurdata->nodesoffset, FALSE, 1600, 0, INT_MAX, NULL, NULL) );
1700 
1701  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesfactor",
1702  "factor on number of nodes in SCIP (plus nodesoffset) to compute itercontingent (higher value runs heuristics more frequently)",
1703  &heurdata->nodesfactor, FALSE, 0.3, 0.0, SCIPinfinity(scip), NULL, NULL) );
1704 
1705  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/successrateexp",
1706  "exponent for power of success rate to be multiplied with itercontingent (lower value decreases impact of success rate)",
1707  &heurdata->successrateexp, FALSE, 1.0, 0.0, DBL_MAX, NULL, NULL) );
1708 
1709  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/iterinit",
1710  "number of iterations used for initial NLP solves",
1711  &heurdata->iterinit, FALSE, 300, 0, INT_MAX, NULL, NULL) );
1712 
1713  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/ninitsolves",
1714  "number of successful NLP solves until switching to iterlimit guess and using success rate",
1715  &heurdata->ninitsolves, FALSE, 2, 0, INT_MAX, NULL, NULL) );
1716 
1717  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/itermin",
1718  "minimal number of iterations for NLP solves",
1719  &heurdata->itermin, FALSE, 20, 0, INT_MAX, NULL, NULL) );
1720 
1721  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/opttol",
1722  "absolute optimality tolerance to use for NLP solves",
1723  &heurdata->opttol, TRUE, SCIPdualfeastol(scip), 0.0, 1.0, NULL, NULL) );
1724 
1725  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/feastolfactor",
1726  "factor on SCIP feasibility tolerance for NLP solves if resolving when NLP solution not feasible in CIP",
1727  &heurdata->feastolfactor, FALSE, 0.1, 0.0, 1.0, NULL, NULL) );
1728 
1729  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxpresolverounds",
1730  "limit on number of presolve rounds in sub-SCIP (-1 for unlimited, 0 for no presolve)",
1731  &heurdata->maxpresolverounds, FALSE, -1, -1, INT_MAX, NULL, NULL) );
1732 
1733  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/presolveemphasis",
1734  "presolve emphasis in sub-SCIP (0: default, 1: aggressive, 2: fast, 3: off)",
1735  &heurdata->presolveemphasis, FALSE, (int)SCIP_PARAMSETTING_FAST, (int)SCIP_PARAMSETTING_DEFAULT, (int)SCIP_PARAMSETTING_OFF, NULL, NULL) );
1736 
1737  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/setcutoff",
1738  "whether to set cutoff in sub-SCIP to current primal bound",
1739  &heurdata->setcutoff, FALSE, TRUE, NULL, NULL) );
1740 
1741  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/forbidfixings",
1742  "whether to add constraints that forbid specific fixings that turned out to be infeasible",
1743  &heurdata->forbidfixings, FALSE, FALSE, NULL, NULL) );
1744 
1745  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/keepcopy",
1746  "whether to keep SCIP copy or to create new copy each time heuristic is applied",
1747  &heurdata->keepcopy, TRUE, TRUE, NULL, NULL) );
1748 
1749  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/expectinfeas",
1750  "percentage of NLP solves with infeasible status required to tell NLP solver to expect an infeasible NLP",
1751  &heurdata->expectinfeas, FALSE, 0.0, 0.0, 1.0, NULL, NULL) );
1752 
1753  return SCIP_OKAY;
1754 }
1755 
1756 /** main procedure of the subNLP heuristic */
1758  SCIP* scip, /**< original SCIP data structure */
1759  SCIP_HEUR* heur, /**< heuristic data structure */
1760  SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found, no solution found, or fixing is infeasible (cutoff) */
1761  SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
1762  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
1763  )
1764 {
1765  SCIP_HEURDATA* heurdata;
1766  SCIP_VAR* var;
1767  SCIP_VAR* subvar;
1768  int i;
1769  SCIP_Real cutoff = SCIPinfinity(scip);
1770 
1771  assert(scip != NULL);
1772  assert(heur != NULL);
1773 
1774  /* get heuristic's data */
1775  heurdata = SCIPheurGetData(heur);
1776  assert(heurdata != NULL);
1777 
1778  /* try to setup NLP if not tried before */
1779  if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
1780  {
1781  SCIP_CALL( createSubSCIP(scip, heurdata) );
1782  }
1783 
1784  *result = SCIP_DIDNOTRUN;
1785 
1786  /* if subSCIP could not be created, then do not run */
1787  if( heurdata->subscip == NULL )
1788  return SCIP_OKAY;
1789 
1790  assert(heurdata->nsubvars > 0);
1791  assert(heurdata->var_subscip2scip != NULL);
1792 
1793  /* fix discrete variables in sub-SCIP */
1794  if( !heurdata->continuous )
1795  {
1796  SCIP_Real fixval;
1797  SCIP_VAR** subvars;
1798  int nsubvars;
1799  int nsubbinvars;
1800  int nsubintvars;
1801  SCIP_Bool infeas;
1802  SCIP_Bool tightened;
1803 
1804  /* transform sub-SCIP, so variable fixing are easily undone by free-transform */
1805  assert(!SCIPisTransformed(heurdata->subscip));
1806  SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
1807 
1808  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1809  assert(nsubvars == heurdata->nsubvars);
1810 
1811  /* fix discrete variables to values in startpoint */
1812  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1813  {
1814  subvar = subvars[i];
1815  assert(SCIPvarGetProbindex(subvar) == i);
1816 
1817  var = heurdata->var_subscip2scip[i];
1818  assert(var != NULL);
1819 
1820  /* at this point, variables in subscip and in our scip should have same bounds */
1821  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
1822  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
1823 
1824  fixval = SCIPgetSolVal(scip, refpoint, var);
1825 
1826  /* only run heuristic on integer feasible points (unless we are on an unbounded LP) */
1827  if( !SCIPisFeasIntegral(scip, fixval) )
1828  {
1829  if( refpoint != NULL || SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
1830  {
1831  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
1832  goto CLEANUP;
1833  }
1834  }
1835  /* if we do not really have a startpoint, then we should take care that we do not fix variables to very large values
1836  * thus, we set to 0.0 here and project on bounds below
1837  */
1838  if( REALABS(fixval) > 1E+10 && refpoint == NULL && SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1839  fixval = 0.0;
1840 
1841  /* fixing variables to infinity causes problems, we should not have been passed such a solution as refpoint */
1842  assert(!SCIPisInfinity(scip, REALABS(fixval)));
1843 
1844  /* round fractional variables to the nearest integer */
1845  fixval = SCIPround(scip, fixval);
1846 
1847  /* adjust value to the global bounds of the corresponding SCIP variable */
1848  fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
1849  fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
1850 
1851  /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
1852  SCIP_CALL( SCIPtightenVarLb(heurdata->subscip, subvar, fixval, TRUE, &infeas, &tightened) );
1853  if( !infeas )
1854  {
1855  SCIP_CALL( SCIPtightenVarUb(heurdata->subscip, subvar, fixval, TRUE, &infeas, &tightened) );
1856  }
1857  if( infeas )
1858  {
1859  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not feasible: fixing var <%s> to value %g is infeasible\n", SCIPvarGetName(var), fixval);
1860  goto CLEANUP;
1861  }
1862  }
1863 
1864  /* if there is already a solution, possibly add an objective cutoff in sub-SCIP
1865  * we do this here only for problems with discrete variables, since the cutoff may be useful when presolving the subscip
1866  * for the NLP solver, a cutoff is useless at best
1867  */
1868  if( SCIPgetNSols(scip) > 0 && heurdata->setcutoff )
1869  {
1870  cutoff = SCIPgetUpperbound(scip);
1871  assert( !SCIPisInfinity(scip, cutoff) );
1872 
1873  SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
1874  SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
1875  }
1876  }
1877  else
1878  {
1879  /* for continuous problems, we should already be in the transformed stage */
1880  assert(SCIPisTransformed(heurdata->subscip));
1881  }
1882 
1883  /* solve the subNLP and try to add solution to SCIP */
1884  SCIP_CALL( solveSubNLP(scip, heur, result, refpoint, resultsol) );
1885 
1886  if( heurdata->subscip == NULL )
1887  {
1888  /* something horrible must have happened that we decided to give up completely on this heuristic */
1889  *result = SCIP_DIDNOTFIND;
1890  return SCIP_OKAY;
1891  }
1892 
1893  if( *result == SCIP_CUTOFF )
1894  {
1895  if( heurdata->subscipisvalid && SCIPgetNActivePricers(scip) == 0 )
1896  {
1897  /* if the subNLP is valid and turned out to be globally infeasible (i.e., proven by SCIP), then we forbid this fixation in the main problem */
1898  if( SCIPisInfinity(scip, cutoff) && heurdata->forbidfixings )
1899  {
1900  SCIP_CALL( forbidFixation(scip, heurdata) );
1901  }
1902  }
1903  else
1904  {
1905  /* if the subNLP turned out to be globally infeasible but we are not sure that we have a valid copy, we change to DIDNOTFIND */
1906  *result = SCIP_DIDNOTFIND;
1907  }
1908  }
1909 
1910  CLEANUP:
1911  if( !heurdata->continuous )
1912  {
1913  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1914  }
1915 
1916  /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
1917  * also if keepcopy is disabled, then destroy subSCIP
1918  */
1919  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
1920  {
1921  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1922  heurdata->triedsetupsubscip = FALSE;
1923  }
1924 
1925  return SCIP_OKAY;
1926 }
1927 
1928 /** updates the starting point for the NLP heuristic
1929  *
1930  * Is called by a constraint handler that handles nonlinear constraints when a check on feasibility of a solution fails.
1931  */
1933  SCIP* scip, /**< SCIP data structure */
1934  SCIP_HEUR* heur, /**< NLP heuristic */
1935  SCIP_SOL* solcand, /**< solution candidate */
1936  SCIP_Real violation /**< constraint violation of solution candidate */
1937  )
1938 {
1939  SCIP_HEURDATA* heurdata;
1940 
1941  assert(scip != NULL);
1942  assert(heur != NULL);
1943  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1944  assert(solcand != NULL);
1945  assert(SCIPisPositive(scip, violation));
1946 
1947  /* too early or the game is over already: no more interest in starting points */
1948  if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
1949  return SCIP_OKAY;
1950 
1951  heurdata = SCIPheurGetData(heur);
1952  assert(heurdata != NULL);
1953 
1954  if( heurdata->subscip == NULL )
1955  {
1956  /* if we do not have a sub-SCIP, but tried to set one up before or will never create a subSCIP, then do not need a starting point */
1957  SCIP_Bool runheur;
1958  if( heurdata->triedsetupsubscip )
1959  return SCIP_OKAY;
1960  if( SCIPheurGetFreq(heur) < 0 )
1961  return SCIP_OKAY;
1962  SCIP_CALL( runHeuristic(scip, &runheur) );
1963  if( !runheur )
1964  return SCIP_OKAY;
1965  }
1966 
1967  /* if the solution is the one we created (last), then it is useless to use it as starting point again
1968  * (we cannot check SCIPsolGetHeur()==heur, as subnlp may not be registered as author of the solution)
1969  */
1970  if( heurdata->lastsol == solcand )
1971  return SCIP_OKAY;
1972 
1973  SCIPdebugMsg(scip, "consider solution candidate with violation %g and objective %g from %s\n",
1974  violation, SCIPgetSolTransObj(scip, solcand), SCIPsolGetHeur(solcand) ? SCIPheurGetName(SCIPsolGetHeur(solcand)) : "tree");
1975 
1976  /* if we have no point yet, or the new point has a lower constraint violation, or it has a better objective function value, then take the new point */
1977  if( heurdata->startcand == NULL || violation < heurdata->startcandviol ||
1978  SCIPisRelGT(scip, SCIPgetSolTransObj(scip, heurdata->startcand), SCIPgetSolTransObj(scip, solcand)) )
1979  {
1980  if( heurdata->startcand != NULL )
1981  {
1982  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
1983  }
1984  SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->startcand, solcand) );
1985  SCIP_CALL( SCIPunlinkSol(scip, heurdata->startcand) );
1986  heurdata->startcandviol = violation;
1987 
1988  /* remember which heuristic proposed the candidate */
1989  SCIPsolSetHeur(heurdata->startcand, SCIPgetSolHeur(scip, solcand));
1990  }
1991 
1992  return SCIP_OKAY;
1993 }
1994 
1995 /** gets startpoint candidate to be used in next call to NLP heuristic, or NULL if none */
1997  SCIP* scip, /**< original SCIP data structure */
1998  SCIP_HEUR* heur /**< heuristic data structure */
1999  )
2000 {
2001  SCIP_HEURDATA* heurdata;
2002 
2003  assert(scip != NULL);
2004  assert(heur != NULL);
2005  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2006 
2007  heurdata = SCIPheurGetData(heur);
2008  assert(heurdata != NULL);
2009 
2010  return heurdata->startcand;
2011 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip_heur.c:233
static SCIP_RETCODE solveSubNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
Definition: heur_subnlp.c:788
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:101
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2081
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:71
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3510
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4940
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:369
static SCIP_RETCODE createSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:210
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:101
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5200
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for SCIP parameter handling
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:356
public methods for memory management
static SCIP_DECL_HEURINIT(heurInitSubNlp)
Definition: heur_subnlp.c:1455
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:345
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17910
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:298
#define SCIP_MAXSTRLEN
Definition: def.h:293
SCIP_RETCODE SCIPincludeHeurSubNlp(SCIP *scip)
Definition: heur_subnlp.c:1661
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:88
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17966
SCIP_RETCODE SCIPcreateConsSetcover(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9317
public solving methods
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:95
public methods for timing
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip_nlp.c:532
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3500
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1245
static SCIP_RETCODE createSolFromNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_HEUR *authorheur)
Definition: heur_subnlp.c:514
SCIP_Real SCIPdualfeastol(SCIP *scip)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:1865
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip_sol.c:2254
#define FALSE
Definition: def.h:87
public methods for presolving plugins
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3014
SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
Definition: heur_subnlp.c:1757
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:339
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
#define TRUE
Definition: def.h:86
#define SCIPdebug(x)
Definition: pub_message.h:84
#define HEUR_FREQ
Definition: heur_subnlp.c:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:923
int SCIPheurGetFreqofs(SCIP_HEUR *heur)
Definition: heur.c:1547
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17600
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:66
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:67
#define HEUR_FREQOFS
Definition: heur_subnlp.c:65
public methods for problem variables
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5317
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:99
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:108
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2356
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3201
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:283
Constraint handler for the set partitioning / packing / covering constraints .
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:566
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:419
public methods for SCIP variables
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip_param.c:594
SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip_copy.c:266
static SCIP_RETCODE createSolFromSubScipSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_SOL *subsol, SCIP_HEUR *authorheur)
Definition: heur_subnlp.c:696
static SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
Definition: heur_subnlp.c:1498
static SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
Definition: heur_subnlp.c:1484
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:111
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5029
#define SCIPdebugMsg
Definition: scip_message.h:69
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:74
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:2550
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
SCIP_SOL * SCIPgetStartCandidateHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:1996
public methods for numerical tolerances
SCIP_Bool SCIPisRelGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
enum SCIP_ParamSetting SCIP_PARAMSETTING
Definition: type_paramset.h:56
static SCIP_DECL_HEUREXEC(heurExecSubNlp)
Definition: heur_subnlp.c:1528
public methods for querying solving statistics
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1066
int SCIPgetNNlpis(SCIP *scip)
Definition: scip_nlpi.c:190
#define HEUR_DESC
Definition: heur_subnlp.c:61
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17920
public methods for NLPI solver interfaces
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip_nlp.c:192
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip_sol.c:609
SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
Definition: scip_nlp.c:554
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:217
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2613
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1441
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip_param.c:210
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2769
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3481
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3489
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:169
#define HEUR_DISPCHAR
Definition: heur_subnlp.c:62
public methods for event handler plugins and event handlers
SCIP_RETCODE SCIPhasNLPContinuousNonlinearity(SCIP *scip, SCIP_Bool *result)
Definition: scip_nlp.c:116
static SCIP_RETCODE forbidFixation(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:1249
SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global)
Definition: scip_copy.c:1169
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:128
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:420
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:474
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip_solve.c:2443
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:48
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_RETCODE freeSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:157
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:164
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17251
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3048
SCIP_Real totaltime
Definition: type_nlpi.h:191
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2604
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1482
SCIP_RETCODE SCIPsetNLPInitialGuess(SCIP *scip, SCIP_Real *initialguess)
Definition: scip_nlp.c:432
#define REALABS(x)
Definition: def.h:201
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1526
SCIP_Real SCIPgetLocalDualbound(SCIP *scip)
Definition: scip_prob.c:3565
public methods for problem copies
public methods for primal CIP solutions
#define SCIP_CALL(x)
Definition: def.h:384
#define HEUR_TIMING
Definition: heur_subnlp.c:67
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:216
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1567
public methods for primal heuristic plugins and divesets
#define HEUR_PRIORITY
Definition: heur_subnlp.c:63
public methods for constraint handler plugins and constraints
Ipopt NLP interface.
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1212
public data structures and miscellaneous methods
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip_solve.c:3432
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1044
SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: scip_sol.c:3440
#define SCIP_Bool
Definition: def.h:84
SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
Definition: scip_nlp.c:579
static SCIP_DECL_HEURFREE(heurFreeSubNlp)
Definition: heur_subnlp.c:1435
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:159
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1021
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip_prob.c:1421
SCIP_Real boundviol
Definition: type_nlpi.h:195
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18297
#define HEUR_MAXDEPTH
Definition: heur_subnlp.c:66
SCIP_RETCODE SCIPcopyConss(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool *valid)
Definition: scip_copy.c:1716
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2649
#define MAX(x, y)
Definition: tclique_def.h:83
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:3231
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:478
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:976
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:391
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2205
#define HEUR_USESSUBSCIP
Definition: heur_subnlp.c:68
int SCIPgetNPresolRounds(SCIP *scip)
Definition: scip_presol.c:279
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE runHeuristic(SCIP *scip, SCIP_Bool *runheur)
Definition: heur_subnlp.c:127
#define BMSclearMemory(ptr)
Definition: memory.h:122
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:111
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12773
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2036
public methods for the LP relaxation, rows and columns
public methods for variable pricer plugins
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1991
public methods for nonlinear relaxation
SCIP_Real consviol
Definition: type_nlpi.h:194
SCIP_Bool SCIPhasNLPSolution(SCIP *scip)
Definition: scip_nlp.c:629
public methods for branching rule plugins and branching
SCIP_RETCODE SCIPcopyProb(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, const char *name)
Definition: scip_copy.c:518
public methods for managing events
general public methods
public methods for solutions
static SCIP_DECL_HEURCOPY(heurCopySubNlp)
Definition: heur_subnlp.c:1421
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3041
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
public methods for message output
NLP local search primal heuristic using sub-SCIPs.
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:185
#define HEUR_NAME
Definition: heur_subnlp.c:60
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1946
SCIP_HEUR * SCIPgetSolHeur(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1675
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1211
#define SCIP_Real
Definition: def.h:177
public methods for message handling
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1481
#define SCIP_INVALID
Definition: def.h:197
#define SCIP_Longint
Definition: def.h:162
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1577
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1181
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17416
static DPSUBSOL ** subsol
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip_solve.c:358
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition: scip_nlp.c:603
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
void SCIPmergeNLPIStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool reset)
Definition: scip_copy.c:1321
static SCIP_RETCODE processNLPSol(SCIP *scip, SCIP_HEUR *heur, SCIP_HEUR *authorheur, SCIP_RESULT *result, SCIP_SOL *resultsol)
Definition: heur_subnlp.c:580
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:153
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17976
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
Definition: heur_subnlp.c:1932
SCIP_Real SCIPgetUpperbound(SCIP *scip)
public methods for primal heuristics
static SCIP_DECL_EVENTEXEC(processVarEvent)
Definition: heur_subnlp.c:457
SCIPallocBlockMemory(scip, subsol))
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:67
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1352
constraint handler for bound disjunction constraints
#define SCIPsolveNLP(...)
Definition: scip_nlp.h:331
SCIP_RETCODE SCIPresetParam(SCIP *scip, const char *name)
Definition: scip_param.c:805
SCIP_Longint SCIPgetNNodes(SCIP *scip)
#define SCIPABORT()
Definition: def.h:356
public methods for global and local (sub)problems
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1352
static int calcIterLimit(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:763
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:130
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:536
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1524
SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
Definition: scip_nlp.c:170
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:48
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17580
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:315
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:319
memory allocation routines