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-2017 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_subnlp.c
17  * @brief NLP local search primal heuristic using sub-SCIPs
18  * @author Stefan Vigerske
19  *
20  * @todo set cutoff or similar in NLP
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 #include <string.h>
27 
28 #include "scip/heur_subnlp.h"
29 #include "nlpi/nlpi.h"
30 #include "scip/cons_linear.h"
31 #include "scip/cons_varbound.h"
32 #include "scip/cons_logicor.h"
33 #include "scip/cons_setppc.h"
34 #include "scip/cons_knapsack.h"
36 
37 #define HEUR_NAME "subnlp"
38 #define HEUR_DESC "primal heuristic that performs a local search in an NLP after fixing integer variables and presolving"
39 #define HEUR_DISPCHAR 'q'
40 #define HEUR_PRIORITY -2000000
41 #define HEUR_FREQ 1
42 #define HEUR_FREQOFS 0
43 #define HEUR_MAXDEPTH -1
44 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
45 #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 */
46 
47 /*
48  * Data structures
49  */
50 
51 /** primal heuristic data */
52 struct SCIP_HeurData
53 {
54  SCIP* subscip; /**< copy of CIP where presolving and NLP solving is done */
55  SCIP_Bool triedsetupsubscip; /**< whether we have tried to setup a sub-SCIP */
56  SCIP_Bool subscipisvalid; /**< whether all constraints have been copied */
57  int nseriousnlpierror; /**< number of consecutive serious NLP solver failures (memout, ...) */
58  SCIP_EVENTHDLR* eventhdlr; /**< event handler for global bound change events */
59 
60  int nvars; /**< number of active transformed variables in SCIP */
61  int nsubvars; /**< number of original variables in sub-SCIP */
62  SCIP_VAR** var_subscip2scip; /**< mapping variables in sub-SCIP to SCIP variables */
63  SCIP_VAR** var_scip2subscip; /**< mapping variables in SCIP to sub-SCIP variables */
64 
65  SCIP_SOL* startcand; /**< candidate for start point for heuristic */
66  SCIP_Real startcandviol; /**< violation of start point candidate w.r.t. constraint that reported this candidate */
67  SCIP_SOL* lastsol; /**< pointer to last found solution (or NULL if none), not captured, thus may be dangling */
68 
69  SCIP_NLPSTATISTICS* nlpstatistics; /**< statistics from NLP solver */
70  SCIP_Bool comblinearconsadded;/**< whether the linear constraint adding method has been called for combinatorial constraints already */
71  SCIP_Bool contlinearconsadded;/**< whether the linear constraint adding method has been called for continuous constraints already */
72 
73  int nlpverblevel; /**< verbosity level of NLP solver */
74  int nlpiterlimit; /**< iteration limit of NLP solver; 0 for off */
75  SCIP_Real nlptimelimit; /**< time limit of NLP solver; 0 for off */
76  SCIP_Real resolvetolfactor; /**< factor for feasibility tolerance when resolving NLP due to disagreement of feasibility */
77  SCIP_Bool resolvefromscratch; /**< whether a resolve of an NLP due to disagreement of feasibility should be from the original starting point or the infeasible solution */
78  char* nlpoptfile; /**< name of NLP solver specific option file */
79  SCIP_Real minimprove; /**< desired minimal improvement in objective function value when running heuristic */
80  int maxpresolverounds; /**< limit on number of presolve rounds in sub-SCIP */
81  SCIP_Bool forbidfixings; /**< whether to add constraints that forbid specific fixations that turned out to be infeasible */
82  SCIP_Bool keepcopy; /**< whether to keep SCIP copy or to create new copy each time heuristic is applied */
83 
84  SCIP_Longint iterused; /**< number of iterations used so far */
85  int iteroffset; /**< number of iterations added to the contingent of the total number of iterations */
86  SCIP_Real iterquot; /**< contingent of NLP iterations in relation to the number of nodes in SCIP */
87  int itermin; /**< minimal number of iterations required to start local search */
88  SCIP_Bool runalways; /**< whether to run NLP heuristic always (independent of iteroffset,iterquot,itermin) */
89  int nsolfound; /**< number of solutions found in this run (because we give authorship of solutions we found to the heuristic that proposed the starting point) */
90 };
91 
92 
93 /*
94  * Local methods
95  */
96 
97 /** indicates whether the heuristic should be running, i.e., whether we expect something nonlinear after fixing all discrete variables */
98 static
100  SCIP* scip /**< SCIP data structure */
101  )
102 {
103  assert(scip != NULL);
104 
105  /* do not run heuristic if no NLP solver is available */
106  if( SCIPgetNNlpis(scip) <= 0 )
107  return FALSE;
108 
109  /* do not run heuristic if no continuous nonlinear variables are present */
111  return FALSE;
112 
113  return TRUE;
114 }
115 
116 /** creates copy of CIP from problem in SCIP */
117 static
119  SCIP* scip, /**< SCIP data structure */
120  SCIP_HEURDATA* heurdata /**< heuristic data structure */
121  )
122 {
123  int nvars;
124  SCIP_VAR** vars;
125  SCIP_VAR** subvars;
126  SCIP_VAR* var;
127  SCIP_VAR* subvar;
128  SCIP_Bool success;
129  char probname[SCIP_MAXSTRLEN];
130  int i;
131  SCIP_HASHMAP* varsmap;
132  SCIP_HASHMAP* conssmap;
133 #ifdef SCIP_DEBUG
134  static const SCIP_Bool copydisplays = TRUE;
135  static const SCIP_Bool copyreader = TRUE;
136 #else
137  static const SCIP_Bool copydisplays = FALSE;
138  static const SCIP_Bool copyreader = FALSE;
139 #endif
140 
141  assert(heurdata != NULL);
142  assert(heurdata->subscip == NULL);
143 
144  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
145 
146  heurdata->triedsetupsubscip = TRUE;
147 
148  /* initializing the subproblem */
149  SCIP_CALL( SCIPcreate(&heurdata->subscip) );
150 
151  /* create variable hash mapping scip -> subscip */
152  SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
153 
154  /* create sub-SCIP copy of CIP */
155 
156  /* copy interesting plugins */
157  success = TRUE;
158  SCIP_CALL( SCIPcopyPlugins(scip, heurdata->subscip,
159  copyreader, /* readers */
160  FALSE, /* pricers */
161  TRUE, /* conshdlrs */
162  FALSE, /* conflicthdlrs */
163  TRUE, /* presolvers */
164  FALSE, /* relaxators */
165  FALSE, /* separators */
166  TRUE, /* propagators */
167  FALSE, /* heuristics */
168  TRUE, /* eventhandler */
169  TRUE, /* nodeselectors (SCIP gives an error if there is none) */
170  FALSE, /* branchrules */
171  copydisplays, /* displays */
172  FALSE, /* dialogs */
173  TRUE, /* nlpis */
174  TRUE, /* message handler */
175  &success) );
176  if( !success )
177  {
178  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "In heur_subnlp: failed to copy some plugins to sub-SCIP, continue anyway\n");
179  }
180 
181  /* check if we still have NLPI's in subscip */
182  if( SCIPgetNNlpis(heurdata->subscip) <= 0 )
183  {
184  SCIPdebugMsg(scip, "some NLPIs from main SCIP did not copy into sub-SCIP, give up heuristic.\n");
185  SCIP_CALL( SCIPfree(&heurdata->subscip) );
186  SCIPhashmapFree(&varsmap);
187 
188  return SCIP_OKAY;
189  }
190 
191  /* copy parameter settings */
192  SCIP_CALL( SCIPcopyParamSettings(scip, heurdata->subscip) );
193 
194  /* create problem in sub-SCIP */
195  /* get name of the original problem and add "subnlp" */
196  (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_subnlp", SCIPgetProbName(scip));
197  SCIP_CALL( SCIPcreateProb(heurdata->subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
198 
199  /* copy all variables */
200  SCIP_CALL( SCIPcopyVars(scip, heurdata->subscip, varsmap, NULL, NULL, NULL, 0, TRUE) );
201 
202  /* copy as many constraints as possible */
203  SCIP_CALL( SCIPhashmapCreate(&conssmap, SCIPblkmem(scip), SCIPgetNConss(scip)) );
204  SCIP_CALL( SCIPcopyConss(scip, heurdata->subscip, varsmap, conssmap, TRUE, FALSE, &heurdata->subscipisvalid) );
205  SCIPhashmapFree(&conssmap);
206  if( !heurdata->subscipisvalid )
207  {
208  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "In heur_subnlp: failed to copy some constraints to sub-SCIP, continue anyway\n");
209  SCIPdebugMsg(scip, "In heur_subnlp: failed to copy some constraints to sub-SCIP, continue anyway\n");
210  }
211 
212  /* create arrays translating scip transformed vars to subscip original vars, and vice versa
213  * capture variables in SCIP and sub-SCIP
214  * catch global bound change events
215  */
216 
217  SCIP_CALL( SCIPgetVarsData(heurdata->subscip, &subvars, &heurdata->nsubvars, NULL, NULL, NULL, NULL) );
218 
219  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars) );
220 #ifndef NDEBUG
221  BMSclearMemoryArray(heurdata->var_subscip2scip, heurdata->nsubvars);
222 #endif
223 
224  heurdata->nvars = nvars;
225  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars) );
226 #ifndef NDEBUG
227  BMSclearMemoryArray(heurdata->var_scip2subscip, heurdata->nvars);
228 #endif
229 
230  /* we need to get all subscip variables, also those which are copies of fixed variables from the main scip
231  * therefore we iterate over the hashmap
232  */
233  for( i = 0; i < SCIPhashmapGetNEntries(varsmap); ++i )
234  {
235  SCIP_HASHMAPENTRY* entry;
236  entry = SCIPhashmapGetEntry(varsmap, i);
237  if( entry != NULL )
238  {
239  var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
240  subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
241 
242  assert(SCIPvarGetProbindex(subvar) >= 0);
243  assert(SCIPvarGetProbindex(subvar) <= heurdata->nsubvars);
244 
245  if( SCIPvarIsActive(var) )
246  {
247  assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
248  assert(heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == NULL); /* assert that we have no mapping for this var yet */
249  heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] = subvar;
250  }
251 
252  assert(heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] == NULL); /* assert that we have no mapping for this subvar yet */
253  heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] = var;
254 
255  SCIP_CALL( SCIPcaptureVar(scip, var) );
256  SCIP_CALL( SCIPcaptureVar(heurdata->subscip, subvar) );
257 
258  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetLbGlobal(subvar)));
259  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), SCIPvarGetUbGlobal(subvar)));
260 
261  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, NULL) );
262  }
263  }
264 
265 #ifndef NDEBUG
266  for( i = 0; i < heurdata->nvars; ++i )
267  {
268  assert(heurdata->var_scip2subscip[i] != NULL);
269  assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)vars[i]) == heurdata->var_scip2subscip[i]);
270  }
271  for( i = 0; i < heurdata->nsubvars; ++i )
272  {
273  assert(heurdata->var_subscip2scip[i] != NULL);
274  assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)heurdata->var_subscip2scip[i]) == subvars[i]);
275  }
276 #endif
277 
278  /* do not need hashmap anymore */
279  SCIPhashmapFree(&varsmap);
280 
281  /* initialize data structure for NLP solve statistics */
282  SCIP_CALL( SCIPnlpStatisticsCreate(&heurdata->nlpstatistics) );
283 
284  /* do not abort subproblem on CTRL-C */
285  SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "misc/catchctrlc", FALSE) );
286 
287  /* disable keeping solutions from one subscip solve for next solve (with usually different fixings) */
288  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "limits/maxorigsol", 0) );
289 
290  /* disable output to console */
291  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 0) );
292 
293  /* reset some limits to default values, in case users changed them in main scip (SCIPcopy copies parameter values :-() */
294  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/absgap") );
295  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/bestsol") );
296  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/gap") );
297  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/restarts") );
298  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/solutions") );
299  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/time") );
300  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/totalnodes") );
301 
302  /* disable restarts (not sure they could be triggered on continuous problems anyway)
303  * keep normal presolving, but disable components presolver
304  * heuristics and separators were not copied into subscip, so should not need to switch off
305  */
306  if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrounds") )
307  {
308  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", heurdata->maxpresolverounds) );
309  }
310  if( !SCIPisParamFixed(heurdata->subscip, "constraints/components/maxprerounds") )
311  {
312  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "constraints/components/maxprerounds", 0) );
313  }
314  if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrestarts") )
315  {
316  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrestarts", 0) );
317  }
318 
319 #ifdef SCIP_DEBUG
320  /* for debugging, enable SCIP output */
321  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 5) );
322 #endif
323 
324  return SCIP_OKAY;
325 }
326 
327 /** free sub-SCIP data structure */
328 static
330  SCIP* scip, /**< SCIP data structure */
331  SCIP_HEURDATA* heurdata /**< heuristic data structure */
332  )
333 {
334  SCIP_VAR** subvars;
335  int nsubvars;
336  int i;
337  SCIP_VAR* var;
338  SCIP_VAR* subvar;
339 
340  assert(scip != NULL);
341  assert(heurdata != NULL);
342 
343  assert(heurdata->subscip != NULL);
344 
345  /* free NLP statistics */
346  if( heurdata->nlpstatistics != NULL )
347  SCIPnlpStatisticsFree(&heurdata->nlpstatistics);
348  assert(heurdata->nlpstatistics == NULL);
349 
350  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, NULL, NULL, NULL, NULL) );
351  assert(nsubvars == heurdata->nsubvars);
352 
353  /* drop global bound change events
354  * release variables in SCIP and sub-SCIP
355  */
356  for( i = 0; i < heurdata->nsubvars; ++i )
357  {
358  subvar = subvars[i];
359  assert(subvar != NULL);
360  assert(SCIPvarGetProbindex(subvar) == i);
361 
362  var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
363  assert(var != NULL);
364  assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
365  assert(!SCIPvarIsActive(var) || heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == subvar);
366 
367  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, -1) );
368 
369  SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &subvar) );
370  SCIP_CALL( SCIPreleaseVar(scip, &var) );
371  }
372 
373  /* free variable mappings subscip -> scip and scip -> subscip */
374  SCIPfreeBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars);
375  SCIPfreeBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars);
376  heurdata->nsubvars = 0;
377  heurdata->nvars = 0;
378 
379  /* free sub-SCIP */
380  SCIP_CALL( SCIPfree(&heurdata->subscip) );
381 
382  return SCIP_OKAY;
383 }
384 
385 /** process variable global bound change event */
386 static
387 SCIP_DECL_EVENTEXEC(processVarEvent)
388 {
389  SCIP_HEURDATA* heurdata;
390  SCIP_VAR* var;
391  SCIP_VAR* subvar;
392  int idx;
393 
394  assert(scip != NULL);
395  assert(event != NULL);
396  assert(eventdata != NULL);
397  assert(eventhdlr != NULL);
398 
399  heurdata = (SCIP_HEURDATA*)eventdata;
400  assert(heurdata != NULL);
401 
402  var = SCIPeventGetVar(event);
403  assert(var != NULL);
404 
405  idx = SCIPvarGetProbindex(var);
406  /* if event corresponds to an active variable, we can easily look up the corresponding subvar
407  * if it is an inactive variable that has been copied to the subproblem,
408  * then we need to check the subscip2scip mapping
409  * @todo we could do this faster if we keep the variables mapping from SCIPcopy around
410  */
411  if( idx >= 0 )
412  {
413  assert(idx < heurdata->nvars);
414 
415  subvar = heurdata->var_scip2subscip[idx];
416  }
417  else
418  {
419  for( idx = 0; idx < heurdata->nsubvars; ++idx )
420  {
421  if( heurdata->var_subscip2scip[idx] == var )
422  break;
423  }
424  assert(idx < heurdata->nsubvars);
425  subvar = SCIPgetVars(heurdata->subscip)[idx];
426  }
427  assert(subvar != NULL);
428 
430  {
431  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
432  }
433 
435  {
436  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
437  }
438 
439  return SCIP_OKAY;
440 }
441 
442 /** adds linear constraints from a SCIP instance to its NLP */
443 static
445  SCIP* scip, /**< SCIP data structure */
446  SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
447  SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
448  SCIP_Bool addcontconss /**< whether to add continuous linear constraints to NLP */
449  )
450 {
451  SCIP_CONS** conss;
452  int nconss;
453  SCIP_NLROW* nlrow;
454  int i;
455  int j;
456  SCIP_Bool iscombinatorial;
457  int nvars;
458  SCIP_VAR** vars;
459 
460  assert(scip != NULL);
461  assert(conshdlr != NULL);
462 
463  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
464  conss = SCIPconshdlrGetConss(conshdlr);
465 
466  if( nconss == 0 )
467  return SCIP_OKAY;
468 
469  for( i = 0; i < nconss; ++i )
470  {
471  /* skip local and redundant constraints */
472  if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
473  continue;
474 
475  /* under some circumstances, this method may be called even though the problem has been shown to be infeasible in presolve already
476  * this infeasibility may come from a linear constraint with lhs > rhs
477  * the NLP does not allow such constraints, so we skip them here
478  */
479  if( !SCIPisRelLE(scip, SCIPgetLhsLinear(scip, conss[i]), SCIPgetRhsLinear(scip, conss[i])) )
480  continue;
481 
482  nvars = SCIPgetNVarsLinear(scip, conss[i]);
483  vars = SCIPgetVarsLinear(scip, conss[i]);
484 
485  /* check if constraint should be added, only need this check if we do not wanna any constraint anyway */
486  if( !addcombconss || !addcontconss )
487  {
488  iscombinatorial = TRUE;
489 
490  for( j = 0; j < nvars; ++j )
491  if( SCIPvarGetType(vars[j]) >= SCIP_VARTYPE_CONTINUOUS )
492  {
493  iscombinatorial = FALSE;
494  break;
495  }
496 
497  /* skip constraint, if not of interest */
498  if( (iscombinatorial && !addcombconss) || (!iscombinatorial && !addcontconss) )
499  continue;
500  }
501 
502  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
503  SCIPgetNVarsLinear(scip, conss[i]), SCIPgetVarsLinear(scip, conss[i]), SCIPgetValsLinear(scip, conss[i]),
504  0, NULL, 0, NULL, NULL,
505  SCIPgetLhsLinear(scip, conss[i]), SCIPgetRhsLinear(scip, conss[i]),
507 
508  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
509  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
510  }
511 
512  return SCIP_OKAY;
513 }
514 
515 /** adds variable bound constraints from a SCIP instance to its NLP */
516 static
518  SCIP* scip, /**< SCIP data structure */
519  SCIP_CONSHDLR* conshdlr, /**< constraint handler for linear constraints */
520  SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
521  SCIP_Bool addcontconss /**< whether to add continuous linear constraints to NLP */
522  )
523 {
524  SCIP_CONS** conss;
525  int nconss;
526  SCIP_NLROW* nlrow;
527  int i;
528  SCIP_VAR* vars[2];
529  SCIP_Real coefs[2];
530  SCIP_Bool iscombinatorial;
531 
532  assert(scip != NULL);
533  assert(conshdlr != NULL);
534 
535  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
536  conss = SCIPconshdlrGetConss(conshdlr);
537 
538  if( nconss == 0 )
539  return SCIP_OKAY;
540 
541  for( i = 0; i < nconss; ++i )
542  {
543  /* skip local and redundant constraints */
544  if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
545  continue;
546 
547  vars[0] = SCIPgetVarVarbound(scip, conss[i]);
548  vars[1] = SCIPgetVbdvarVarbound(scip, conss[i]);
549 
550  iscombinatorial = SCIPvarGetType(vars[0]) < SCIP_VARTYPE_CONTINUOUS && SCIPvarGetType(vars[1]) < SCIP_VARTYPE_CONTINUOUS;
551 
552  /* skip constraint, if not of interest */
553  if( (iscombinatorial && !addcombconss) || (!iscombinatorial && !addcontconss) )
554  continue;
555 
556  coefs[0] = 1.0;
557  coefs[1] = SCIPgetVbdcoefVarbound(scip, conss[i]);
558 
559  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
560  2, vars, coefs,
561  0, NULL, 0, NULL, NULL,
562  SCIPgetLhsVarbound(scip, conss[i]), SCIPgetRhsVarbound(scip, conss[i]),
564 
565  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
566  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
567  }
568 
569  return SCIP_OKAY;
570 }
571 
572 /** adds logic-or constraints to NLP */
573 static
575  SCIP* scip, /**< SCIP data structure */
576  SCIP_CONSHDLR* conshdlr /**< constraint handler for linear constraints */
577  )
578 {
579  SCIP_CONS** conss;
580  int nconss;
581  SCIP_NLROW* nlrow;
582  int i;
583  int j;
584  SCIP_Real* coefs;
585  int coefssize;
586  int nvars;
587 
588  assert(scip != NULL);
589  assert(conshdlr != NULL);
590 
591  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
592  if( !nconss )
593  return SCIP_OKAY;
594 
595  conss = SCIPconshdlrGetConss(conshdlr);
596 
597  coefs = NULL;
598  coefssize = 0;
599 
600  for( i = 0; i < nconss; ++i )
601  {
602  /* skip local and redundant constraints */
603  if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
604  continue;
605 
606  nvars = SCIPgetNVarsLogicor(scip, conss[i]);
607 
608  if( coefssize < nvars )
609  {
610  if( coefs == NULL )
611  {
612  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
613  }
614  else
615  {
616  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
617  }
618  for( j = coefssize; j < nvars; ++j )
619  coefs[j] = 1.0;
620  coefssize = nvars;
621  }
622 
623  /* logic or constraints: 1 <= sum_j x_j */
624 
625  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
626  nvars, SCIPgetVarsLogicor(scip, conss[i]), coefs,
627  0, NULL, 0, NULL, NULL,
628  1.0, SCIPinfinity(scip),
630 
631  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
632  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
633  }
634 
635  SCIPfreeBufferArrayNull(scip, &coefs);
636 
637  return SCIP_OKAY;
638 }
639 
640 /** adds setppc constraints to NLP */
641 static
643  SCIP* scip, /**< SCIP data structure */
644  SCIP_CONSHDLR* conshdlr /**< constraint handler for linear constraints */
645  )
646 {
647  SCIP_CONS** conss;
648  int nconss;
649  SCIP_NLROW* nlrow;
650  int i;
651  int j;
652  SCIP_Real* coefs;
653  int coefssize;
654  int nvars;
655  SCIP_Real lhs;
656  SCIP_Real rhs;
657 
658  assert(scip != NULL);
659  assert(conshdlr != NULL);
660 
661  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
662  if( !nconss )
663  return SCIP_OKAY;
664 
665  conss = SCIPconshdlrGetConss(conshdlr);
666 
667  coefs = NULL;
668  coefssize = 0;
669 
670  for( i = 0; i < nconss; ++i )
671  {
672  /* skip local and redundant constraints */
673  if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
674  continue;
675 
676  nvars = SCIPgetNVarsSetppc(scip, conss[i]);
677 
678  if( coefssize < nvars )
679  {
680  if( coefs == NULL )
681  {
682  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
683  }
684  else
685  {
686  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
687  }
688  for( j = coefssize; j < nvars; ++j )
689  coefs[j] = 1.0;
690  coefssize = nvars;
691  }
692 
693  /* setppc constraint: 1 ~ sum_j x_j */
694 
695  switch( SCIPgetTypeSetppc(scip, conss[i]) )
696  {
698  lhs = 1.0;
699  rhs = 1.0;
700  break;
701 
703  lhs = -SCIPinfinity(scip);
704  rhs = 1.0;
705  break;
706 
708  lhs = 1.0;
709  rhs = SCIPinfinity(scip);
710  break;
711 
712  default:
713  SCIPerrorMessage("unexpected setppc type\n");
714  return SCIP_ERROR;
715  }
716 
717  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
718  nvars, SCIPgetVarsSetppc(scip, conss[i]), coefs,
719  0, NULL, 0, NULL, NULL,
720  lhs, rhs,
722 
723  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
724  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
725  }
726 
727  SCIPfreeBufferArrayNull(scip, &coefs);
728 
729  return SCIP_OKAY;
730 }
731 
732 /** adds knapsack constraints to NLP */
733 static
735  SCIP* scip, /**< SCIP data structure */
736  SCIP_CONSHDLR* conshdlr /**< constraint handler for linear constraints */
737  )
738 {
739  SCIP_CONS** conss;
740  int nconss;
741  SCIP_NLROW* nlrow;
742  int i;
743  int j;
744  SCIP_Real* coefs;
745  int coefssize;
746  int nvars;
747 
748  assert(scip != NULL);
749  assert(conshdlr != NULL);
750 
751  nconss = SCIPconshdlrGetNActiveConss(conshdlr);
752  if( !nconss )
753  return SCIP_OKAY;
754 
755  conss = SCIPconshdlrGetConss(conshdlr);
756  assert(conss != NULL);
757 
758  coefs = NULL;
759  coefssize = 0;
760 
761  for( i = 0; i < nconss; ++i )
762  {
763  SCIP_Longint* weights;
764 
765  /* skip local and redundant constraints */
766  if( !SCIPconsIsEnabled(conss[i]) || !SCIPconsIsChecked(conss[i]) )
767  continue;
768 
769  nvars = SCIPgetNVarsKnapsack(scip, conss[i]);
770 
771  if( coefssize < nvars )
772  {
773  if( coefs == NULL )
774  {
775  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
776  }
777  else
778  {
779  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, nvars) );
780  }
781  coefssize = nvars;
782  }
783 
784  weights = SCIPgetWeightsKnapsack(scip, conss[i]);
785  for( j = 0; j < nvars; ++j )
786  coefs[j] = (SCIP_Real)weights[j]; /*lint !e613*/
787 
788  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[i]), 0.0,
789  nvars, SCIPgetVarsKnapsack(scip, conss[i]), coefs,
790  0, NULL, 0, NULL, NULL,
791  -SCIPinfinity(scip), (SCIP_Real)SCIPgetCapacityKnapsack(scip, conss[i]),
793 
794  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
795  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
796  }
797 
798  SCIPfreeBufferArrayNull(scip, &coefs);
799 
800  return SCIP_OKAY;
801 }
802 
803 /** adds combinatorial and/or continuous variants of linear constraints from a SCIP instance to its NLP */
804 static
806  SCIP* scip, /**< SCIP data structure */
807  SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints to NLP */
808  SCIP_Bool addcontconss /**< whether to add continuous linear constraints to NLP */
809  )
810 {
811  SCIP_CONSHDLR* conshdlr;
812 
813  /* add linear constraints */
814  conshdlr = SCIPfindConshdlr(scip, "linear");
815  if( conshdlr != NULL )
816  {
817  SCIP_CALL( addLinearConstraints(scip, conshdlr, addcombconss, addcontconss) );
818  }
819 
820  /* add varbound constraints */
821  conshdlr = SCIPfindConshdlr(scip, "varbound");
822  if( conshdlr != NULL )
823  {
824  SCIP_CALL( addVarboundConstraints(scip, conshdlr, addcombconss, addcontconss) );
825  }
826 
827  if( addcombconss )
828  {
829  /* add logic-or constraints */
830  conshdlr = SCIPfindConshdlr(scip, "logicor");
831  if( conshdlr != NULL )
832  {
833  SCIP_CALL( addLogicOrConstraints(scip, conshdlr) );
834  }
835 
836  /* add setppc constraints */
837  conshdlr = SCIPfindConshdlr(scip, "setppc");
838  if( conshdlr != NULL )
839  {
840  SCIP_CALL( addSetppcConstraints(scip, conshdlr) );
841  }
842 
843  /* add knapsack constraints */
844  conshdlr = SCIPfindConshdlr(scip, "knapsack");
845  if( conshdlr != NULL )
846  {
847  SCIP_CALL( addKnapsackConstraints(scip, conshdlr) );
848  }
849  }
850 
851  return SCIP_OKAY;
852 }
853 
854 /* creates a SCIP_SOL in our SCIP space out of the solution from NLP solver in sub-SCIP */
855 static
857  SCIP* scip, /**< SCIP data structure */
858  SCIP_HEUR* heur, /**< heuristic data structure */
859  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 */
860  SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
861  )
862 {
863  SCIP_HEURDATA* heurdata;
864  SCIP_VAR* var;
865  SCIP_VAR* subvar;
866  int i;
867 
868  assert(scip != NULL);
869  assert(heur != NULL);
870  assert(sol != NULL);
871 
872  heurdata = SCIPheurGetData(heur);
873  assert(heurdata != NULL);
874 
875  if( *sol == NULL )
876  {
877  SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
878  }
879  else
880  {
881  SCIPsolSetHeur(*sol, authorheur);
882  }
883 
884  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
885  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
886  */
887  assert(heurdata->nsubvars <= SCIPgetNOrigVars(heurdata->subscip));
888 
889  for( i = 0; i < heurdata->nsubvars; ++i )
890  {
891  var = heurdata->var_subscip2scip[i];
892  if( var == NULL || !SCIPvarIsActive(var) )
893  continue;
894 
895  subvar = SCIPgetOrigVars(heurdata->subscip)[i];
896  assert(subvar != NULL);
897 
898  assert(SCIPvarGetNLPSol(subvar) != SCIP_INVALID); /*lint !e777*/
899  SCIP_CALL( SCIPsetSolVal(scip, *sol, var, SCIPvarGetNLPSol(subvar)) );
900  }
901 
902  return SCIP_OKAY;
903 }
904 
905 /* creates a SCIP_SOL in our SCIP space out of the SCIP_SOL from a sub-SCIP */
906 static
908  SCIP* scip, /**< SCIP data structure */
909  SCIP_HEUR* heur, /**< heuristic data structure */
910  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 */
911  SCIP_SOL* subsol, /**< solution of sub-SCIP */
912  SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
913  )
914 {
915  SCIP_HEURDATA* heurdata;
916  int i;
917 
918  assert(scip != NULL);
919  assert(heur != NULL);
920  assert(sol != NULL);
921  assert(subsol != NULL);
922 
923  heurdata = SCIPheurGetData(heur);
924  assert(heurdata != NULL);
925 
926  if( *sol == NULL )
927  {
928  SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
929  }
930  else
931  {
932  SCIPsolSetHeur(*sol, authorheur);
933  }
934 
935  assert(heurdata->nsubvars == SCIPgetNOrigVars(heurdata->subscip));
936  for( i = 0; i < heurdata->nsubvars; ++i )
937  {
938  if( heurdata->var_subscip2scip[i] == NULL || !SCIPvarIsActive(heurdata->var_subscip2scip[i]) )
939  continue;
940  SCIP_CALL( SCIPsetSolVal(scip, *sol, heurdata->var_subscip2scip[i],
941  SCIPgetSolVal(heurdata->subscip, subsol, SCIPgetOrigVars(heurdata->subscip)[i])) );
942  }
943 
944  return SCIP_OKAY;
945 }
946 
947 /* solves the subNLP specified in subscip */
948 static
950  SCIP* scip, /**< original SCIP data structure */
951  SCIP_HEUR* heur, /**< heuristic data structure */
952  SCIP_RESULT* result, /**< buffer to store result, DIDNOTFIND, FOUNDSOL, or CUTOFF */
953  SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
954  SCIP_Longint itercontingent, /**< iteration limit for NLP solver, or -1 for default of NLP heuristic */
955  SCIP_Real timelimit, /**< time limit for NLP solver */
956  SCIP_Longint* iterused, /**< buffer to store number of iterations used by NLP solver, or NULL if not of interest */
957  SCIP_Bool tighttolerances, /**< whether to use tight feasibility tolerances and reduce presolve */
958  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
959  )
960 {
961  SCIP_HEURDATA* heurdata;
962  SCIP_RETCODE retcode;
963  SCIP_Real* startpoint;
964  SCIP_VAR* var;
965  SCIP_VAR* subvar;
966  int i;
967  SCIP_HEUR* authorheur; /* the heuristic which will be the author of a solution, if found */
968 
969  assert(scip != NULL);
970  assert(heur != NULL);
971  assert(result != NULL);
972 
973  heurdata = SCIPheurGetData(heur);
974  assert(heurdata != NULL);
975 
976  /* if NLP timelimit is set to 0.0, then return immediately
977  * Previously, we were still running scip presolve, assuming the caller wanted to see if the instance is still feasible after presolve.
978  * But now we want to set a timelimit also for the scip presolve, and it is easiest to use timelimit for this.
979  */
980  if( timelimit == 0.0 )
981  goto CLEANUP;
982 
983  if( tighttolerances )
984  {
985  SCIP_Real sumepsilon;
986 
987  /* reduce feasibility tolerance of sub-SCIP and do less aggressive presolve */
988  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/feastol", heurdata->resolvetolfactor*SCIPfeastol(scip)) );
989  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/epsilon", heurdata->resolvetolfactor*SCIPepsilon(scip)) );
990  SCIP_CALL( SCIPgetRealParam(scip, "numerics/sumepsilon", &sumepsilon) );
991  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/sumepsilon", heurdata->resolvetolfactor*sumepsilon) );
992  SCIP_CALL( SCIPsetPresolving(heurdata->subscip, SCIP_PARAMSETTING_FAST, TRUE) );
993 
994  if( !SCIPisParamFixed(heurdata->subscip, "constraints/linear/aggregatevariables") )
995  {
996  SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "constraints/linear/aggregatevariables", FALSE) );
997  }
998  }
999 
1000  /* transform sub-SCIP */
1001  SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
1002 
1003  /* presolve sub-SCIP
1004  * set scip timelimit in case presolve is unexpectedly expensive
1005  * set node limit to 1 so that presolve can go
1006  * reset maxpresolverounds, in case user changed
1007  */
1008  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/time", timelimit) );
1009  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
1010  if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrounds") )
1011  {
1012  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", heurdata->maxpresolverounds) );
1013  }
1014  SCIP_CALL( SCIPpresolve(heurdata->subscip) );
1015  if( SCIPpressedCtrlC(heurdata->subscip) )
1016  {
1017  SCIPdebugMsg(scip, "SCIP presolve interrupted by user\n");
1018  goto CLEANUP;
1019  }
1020  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED )
1021  {
1022  /* presolve probably found the subproblem infeasible */
1023  SCIPdebugMsg(scip, "SCIP returned from presolve in stage solved with status %d\n", SCIPgetStatus(heurdata->subscip));
1024  /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
1025  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
1026  *result = SCIP_CUTOFF;
1027  goto CLEANUP;
1028  }
1029  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING )
1030  {
1031  /* presolve was stopped because some still existing limit was hit (e.g., memory) */
1032  SCIPdebugMsg(scip, "SCIP returned from presolve in stage presolving with status %d\n", SCIPgetStatus(heurdata->subscip));
1033  /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
1034  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
1035  *result = SCIP_CUTOFF;
1036  goto CLEANUP;
1037  }
1038  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVED);
1039 
1040  if( SCIPgetNVars(heurdata->subscip) > 0 )
1041  {
1042  /* 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) */
1043  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
1044  retcode = SCIPsolve(heurdata->subscip);
1045 
1046  /* If no NLP was constructed, then there were no nonlinearities after presolve.
1047  * So we increase the nodelimit to 1 and hope that SCIP will find some solution to this probably linear subproblem.
1048  */
1049  if( retcode == SCIP_OKAY && SCIPgetStage(heurdata->subscip) != SCIP_STAGE_SOLVED && !SCIPisNLPConstructed(heurdata->subscip) )
1050  {
1051  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
1052  retcode = SCIPsolve(heurdata->subscip);
1053  }
1054  }
1055  else
1056  {
1057  /* If all variables were removed by presolve, but presolve did not end with status SOLVED,
1058  * then we run solve, still with nodelimit=1, and hope to find some (maybe trivial) solution.
1059  */
1060  retcode = SCIPsolve(heurdata->subscip);
1061  }
1062 
1063  /* errors in solving the subproblem should not kill the overall solving process;
1064  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
1065  if ( retcode != SCIP_OKAY )
1066  {
1067 #ifndef NDEBUG
1068  SCIP_CALL( retcode );
1069 #endif
1070  SCIPwarningMessage(scip, "Error while solving subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
1071  goto CLEANUP;
1072  }
1073 
1074  /* if the refpoint comes from a heuristic, then make it the author of a found solution,
1075  * otherwise let the subNLP heuristic claim authorship
1076  */
1077  if( refpoint == NULL || SCIPsolGetHeur(refpoint) == NULL )
1078  authorheur = heur;
1079  else
1080  authorheur = SCIPsolGetHeur(refpoint);
1081 
1082  /* if sub-SCIP found solutions already, then pass them to main scip */
1083  for( i = 0; i < SCIPgetNSols(heurdata->subscip); ++i )
1084  {
1085  SCIP_Bool stored;
1086 
1087  if( resultsol == NULL )
1088  {
1089  SCIP_SOL* sol;
1090 
1091  sol = NULL;
1092  SCIP_CALL( createSolFromSubScipSol(scip, heur, &sol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
1093 
1094  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
1095  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1096  if( stored )
1097  {
1098  if( heurdata->nlpverblevel >= 1 )
1099  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP stored solution from sub-SCIP root node\n");
1100  else
1101  {
1102  SCIPdebugMsg(scip, "SCIP stored solution from sub-SCIP root node\n");
1103  }
1104  *result = SCIP_FOUNDSOL;
1105  ++heurdata->nsolfound;
1106  break;
1107  }
1108  else
1109  {
1110  if( heurdata->nlpverblevel >= 1 )
1111  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP did not store sub-SCIP optimal solution\n");
1112  else
1113  {
1114  SCIPdebugMsg(scip, "SCIP did not store sub-SCIP optimal solution\n");
1115  }
1116  }
1117  }
1118  else
1119  {
1120  SCIP_CALL( createSolFromSubScipSol(scip, heur, &resultsol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
1121 
1122  heurdata->lastsol = resultsol;
1123  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1124  if( stored )
1125  {
1126  if( heurdata->nlpverblevel >= 1 )
1127  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP solution from sub-SCIP root node is feasible\n");
1128  else
1129  {
1130  SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is feasible\n");
1131  }
1132  *result = SCIP_FOUNDSOL;
1133  ++heurdata->nsolfound;
1134  break;
1135  }
1136  else
1137  {
1138  if( heurdata->nlpverblevel >= 1 )
1139  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP solution form sub-SCIP root node is not feasible\n");
1140  else
1141  {
1142  SCIPdebugMsg(scip, "SCIP solution form sub-SCIP root node is not feasible\n");
1143  }
1144  }
1145  }
1146  }
1147 
1148  /* we should either have variables, or the problem was trivial, in which case it should have been solved */
1149  assert(SCIPgetNVars(heurdata->subscip) > 0 || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
1150 
1151  /* if subscip is infeasible here, we signal this to the caller */
1152  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
1153  {
1154  if( heurdata->nlpverblevel >= 1 )
1155  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "sub-SCIP detected infeasibility\n");
1156  else
1157  {
1158  SCIPdebugMsg(scip, "sub-SCIP detected infeasibility\n");
1159  }
1160 
1161  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
1162  *result = SCIP_CUTOFF;
1163  goto CLEANUP;
1164  }
1165 
1166  /* if we stopped for some other reason, or there is no NLP, we also stop */
1167  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
1168  goto CLEANUP;
1169 
1170  /* in most cases, the status should be nodelimit
1171  * in some cases, if the sub-SCIP is very easy, it may report optimal, so we do not need invoke an NLP solver
1172  * if the presolve found the problem infeasible, then there is no use in solving an NLP
1173  * if the user interrupted or a timelimit was reached, then we should also stop here
1174  * unbounded is very unlikely to happen, in most cases, it should have been concluded in the main scip already
1175  */
1176  switch( SCIPgetStatus(heurdata->subscip) )
1177  {
1178  case SCIP_STATUS_NODELIMIT:
1179  break; /* this is the status that is most likely happening */
1182  case SCIP_STATUS_GAPLIMIT:
1183  case SCIP_STATUS_SOLLIMIT:
1185  /* these should not happen, but if one does, it's save to go to CLEANUP */
1186  SCIPABORT();
1187  case SCIP_STATUS_OPTIMAL:
1188  case SCIP_STATUS_INFEASIBLE:
1190  case SCIP_STATUS_TIMELIMIT:
1191  case SCIP_STATUS_MEMLIMIT:
1192  case SCIP_STATUS_UNBOUNDED:
1193  case SCIP_STATUS_INFORUNBD:
1194  goto CLEANUP;
1195  default:
1196  SCIPerrorMessage("unexpected status of sub-SCIP: <%d>\n", SCIPgetStatus(heurdata->subscip));
1197  return SCIP_ERROR;
1198  } /*lint !e788*/
1199 
1200  /* add non-combinatorial linear constraints from subscip into subNLP (shall be replaced by catching row events in NLP) */
1201  SCIP_CALL( addLinearConstraintsToNlp(heurdata->subscip, FALSE, TRUE) );
1202 
1203  /* set starting values (=refpoint, if not NULL; otherwise LP solution (or pseudo solution)) */
1204  SCIP_CALL( SCIPallocBufferArray(scip, &startpoint, SCIPgetNNLPVars(heurdata->subscip)) );
1205 
1206  if( heurdata->nlpverblevel >= 2 )
1207  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "set NLP starting point\n");
1208 
1209  for( i = 0; i < SCIPgetNNLPVars(heurdata->subscip); ++i )
1210  {
1211  SCIP_Real scalar;
1212  SCIP_Real constant;
1213 
1214  subvar = SCIPgetNLPVars(heurdata->subscip)[i];
1215 
1216  /* gets corresponding original variable */
1217  scalar = 1.0;
1218  constant = 0.0;
1219  SCIP_CALL( SCIPvarGetOrigvarSum(&subvar, &scalar, &constant) );
1220  if( subvar == NULL )
1221  {
1222  startpoint[i] = constant;
1223 
1224  if( heurdata->nlpverblevel >= 2 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1225  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1226 
1227  continue;
1228  }
1229 
1230  assert(SCIPvarGetProbindex(subvar) >= 0);
1231  assert(SCIPvarGetProbindex(subvar) < heurdata->nsubvars);
1232  var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
1233  if( var == NULL || REALABS(SCIPgetSolVal(scip, refpoint, var)) > 1.0e+12 )
1234  startpoint[i] = MIN(MAX(0.0, SCIPvarGetLbGlobal(subvar)), SCIPvarGetUbGlobal(subvar)); /*lint !e666*/
1235  else
1236  /* scalar*subvar+constant corresponds to nlpvar[i], so nlpvar[i] gets value scalar*varval+constant */
1237  startpoint[i] = scalar * SCIPgetSolVal(scip, refpoint, var) + constant;
1238 
1239  if( heurdata->nlpverblevel >= 2 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1240  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1241  }
1242  SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, startpoint) );
1243 
1244  SCIPfreeBufferArray(scip, &startpoint);
1245 
1246  *result = SCIP_DIDNOTFIND;
1247 
1248  /* setup NLP parameters */
1249 
1250  if( tighttolerances )
1251  {
1252  /* set feasibility tolerance, if tighttolerances is set */
1253  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_FEASTOL, heurdata->resolvetolfactor*SCIPfeastol(scip)) );
1254  }
1255  /* TODO Would it make sense to already start with a tighter feastol than SCIP's?
1256  else
1257  {
1258  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_FEASTOL, 0.1*SCIPfeastol(scip)) );
1259  }
1260  */
1261 
1262  /* set option file to use by NLP solver */
1263  if( heurdata->nlpoptfile != NULL && *heurdata->nlpoptfile != '\0' )
1264  {
1265  SCIP_CALL( SCIPsetNLPStringPar(heurdata->subscip, SCIP_NLPPAR_OPTFILE, heurdata->nlpoptfile) );
1266  }
1267 
1268  /* set iteration limit for NLP solver */
1269  if( itercontingent == -1 && heurdata->nlpiterlimit > 0 )
1270  itercontingent = heurdata->nlpiterlimit;
1271  if( itercontingent > 0 )
1272  {
1273  SCIP_CALL( SCIPsetNLPIntPar(heurdata->subscip, SCIP_NLPPAR_ITLIM, (int)MIN(INT_MAX, itercontingent)) );
1274  }
1275 
1276  /* set time limit for NLP solver */
1277  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_TILIM, timelimit) );
1278 
1279  /* set verbosity of NLP solver */
1280  SCIP_CALL( SCIPsetNLPIntPar(heurdata->subscip, SCIP_NLPPAR_VERBLEVEL, heurdata->nlpverblevel) );
1281 
1282 
1283  /* let the NLP solver do its magic */
1284  SCIPdebugMsg(scip, "start NLP solve with iteration limit %" SCIP_LONGINT_FORMAT " and timelimit %g\n", itercontingent, timelimit);
1285  SCIP_CALL( SCIPsolveNLP(heurdata->subscip) );
1286 
1287  SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
1288  SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
1289 
1290  if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_MEMERR )
1291  {
1292  /* oops, something did not go well at all */
1293  if( heurdata->nlpverblevel >= 1 )
1294  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d.",
1295  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip));
1296 
1297  ++(heurdata->nseriousnlpierror);
1299  "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d. This was the %d%s successive time.\n",
1300  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip), heurdata->nseriousnlpierror,
1301  heurdata->nseriousnlpierror == 1 ? "st" : heurdata->nseriousnlpierror == 2 ? "nd" : heurdata->nseriousnlpierror == 3 ? "rd" : "th");
1302  if( heurdata->nseriousnlpierror >= 5 )
1303  {
1304  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Will not run NLP heuristic again for this run.\n");
1305  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1306  }
1307  goto CLEANUP;
1308  }
1309  heurdata->nseriousnlpierror = 0;
1310 
1311  SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, heurdata->nlpstatistics) );
1312 
1313  if( iterused != NULL )
1314  *iterused += SCIPnlpStatisticsGetNIterations(heurdata->nlpstatistics);
1315  SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds\n",
1316  SCIPnlpStatisticsGetNIterations(heurdata->nlpstatistics), SCIPnlpStatisticsGetTotalTime(heurdata->nlpstatistics));
1317 
1318  /* NLP solver claims it found a feasible (maybe even optimal) solution
1319  * if the objective value is better than our cutoff, then try to add it
1320  * if we do not plan to add the solution (resultsol != NULL), then also check it if objective value is not better than objlimit
1321  */
1322  if( SCIPgetNLPSolstat(heurdata->subscip) <= SCIP_NLPSOLSTAT_FEASIBLE && (resultsol != NULL || SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip))) )
1323  {
1324  if( resultsol == NULL )
1325  {
1326  SCIP_SOL* sol;
1327  SCIP_Bool stored;
1328 
1329  sol = NULL;
1330  SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
1331 
1332  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
1333  if( heurdata->resolvefromscratch )
1334  {
1335 #ifdef SCIP_DEBUG
1336  /* print the infeasibilities to stdout */
1337  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
1338 #else
1339  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1340 #endif
1341  }
1342  else
1343  {
1344 #ifdef SCIP_DEBUG
1345  /* print the infeasibilities to stdout */
1346  SCIP_CALL( SCIPtrySol(scip, sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
1347 #else
1348  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1349 #endif
1350  }
1351 
1352  if( stored )
1353  { /* SCIP stored solution (yippi!), so we are done */
1354  if( heurdata->nlpverblevel >= 1 )
1355  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP stored subnlp solution\n");
1356  else
1357  {
1358  SCIPdebugMsg(scip, "SCIP stored subnlp solution\n");
1359  }
1360 
1361  *result = SCIP_FOUNDSOL;
1362  ++heurdata->nsolfound;
1363  }
1364  else if( !tighttolerances && heurdata->resolvetolfactor < 1.0 )
1365  {
1366  /* if SCIP does not like solution, we try again with tighter tolerances recreate subproblem and resolve with tighter tolerances */
1367  if( heurdata->nlpverblevel >= 1 )
1368  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1369  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1370  else
1371  {
1372  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1373  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1374  }
1375 
1376  /* free transformed problem */
1377  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1378 
1379  SCIP_CALL( solveSubNLP(scip, heur, result, heurdata->resolvefromscratch ? refpoint : sol, itercontingent, timelimit, iterused, TRUE, resultsol) );
1380  }
1381  else
1382  {
1383  if( heurdata->nlpverblevel >= 1 )
1384  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not stored by SCIP\n");
1385  else
1386  {
1387  SCIPdebugMsg(scip, "solution reported by NLP solver not stored by SCIP\n");
1388  }
1389  }
1390 
1391  if( sol != NULL )
1392  {
1393  SCIP_CALL( SCIPfreeSol(scip, &sol) );
1394  }
1395  }
1396  else
1397  {
1398  SCIP_Bool feasible;
1399 
1400  SCIP_CALL( createSolFromNLP(scip, heur, &resultsol, authorheur) );
1401 
1402  heurdata->lastsol = resultsol;
1403 #ifdef SCIP_DEBUG
1404  /* print the infeasibilities to stdout */
1405  SCIP_CALL( SCIPcheckSol(scip, resultsol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
1406 #else
1407  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
1408 #endif
1409  if( feasible )
1410  {
1411  /* SCIP find solution feasible, so we are done */
1412  if( heurdata->nlpverblevel >= 1 )
1413  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver feasible for SCIP\n");
1414  else
1415  {
1416  SCIPdebugMsg(scip, "solution reported by NLP solver feasible for SCIP\n");
1417  }
1418  *result = SCIP_FOUNDSOL;
1419  ++heurdata->nsolfound;
1420  }
1421  else if( !tighttolerances && heurdata->resolvetolfactor < 1.0 )
1422  {
1423  /* free transformed problem */
1424  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1425 
1426  /* if SCIP does not like solution, we try again with tighter tolerances
1427  * recreate subproblem and resolve with tighter tolerances
1428  */
1429  if( heurdata->nlpverblevel >= 1 )
1431  "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1432  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1433  else
1434  {
1435  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1436  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1437  }
1438 
1439  SCIP_CALL( solveSubNLP(scip, heur, result, heurdata->resolvefromscratch ? refpoint : resultsol, itercontingent, timelimit, iterused, TRUE, resultsol) );
1440  }
1441  else
1442  {
1443  if( heurdata->nlpverblevel >= 1 )
1444  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not feasible for SCIP\n");
1445  else
1446  {
1447  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP\n");
1448  }
1449  }
1450  }
1451  }
1452  else if( heurdata->nlpverblevel >= 1 )
1453  {
1454  /* print the violation of the NLP solution candidate */
1455  if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
1456  {
1457  SCIP_SOL* sol;
1458  SCIP_Bool feasible;
1459 
1460  sol = NULL;
1461  SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
1462 
1463  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "subnlp solution is infeasbile\n");
1464 
1465  /* print the infeasibilities to stdout */
1466  SCIP_CALL( SCIPcheckSol(scip, sol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
1467 
1468  SCIP_CALL( SCIPfreeSol(scip, &sol) );
1469  }
1470  else if( heurdata->nlpverblevel >= 1
1471  && !SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip)) )
1472  {
1473  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "subnlp solution objval %e is above the objlimit %e\n",
1474  SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip));
1475  }
1476  }
1477 
1478  CLEANUP:
1479  if( heurdata->subscip != NULL )
1480  {
1481  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1482  if( tighttolerances )
1483  {
1484  SCIP_Real sumepsilon;
1485 
1486  /* reset feasibility tolerance of sub-SCIP and reset to normal presolve */
1487  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/feastol", SCIPfeastol(scip)) );
1488  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/epsilon", SCIPepsilon(scip)) );
1489  SCIP_CALL( SCIPgetRealParam(scip, "numerics/sumepsilon", &sumepsilon) );
1490  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/sumepsilon", sumepsilon) );
1492  SCIP_CALL( SCIPresetParam(heurdata->subscip, "constraints/linear/aggregatevariables") );
1493  }
1494  }
1495 
1496  if( iterused != NULL && *iterused == 0 )
1497  *iterused = 1;
1498 
1499  return SCIP_OKAY;
1500 }
1501 
1502 
1503 /** adds a set covering or bound disjunction constraint to the original problem */
1504 static
1506  SCIP* scip, /**< SCIP data structure */
1507  SCIP_HEURDATA* heurdata /**< heuristic data */
1508  )
1509 {
1510  SCIP_VAR** subvars;
1511  int nsubvars;
1512  int nsubbinvars;
1513  int nsubintvars;
1514  SCIP_VAR* var;
1515  SCIP_VAR* subvar;
1516  SCIP_CONS* cons;
1517  SCIP_VAR** consvars;
1518  int nconsvars;
1519  char name[SCIP_MAXSTRLEN];
1520  int i;
1521  SCIP_Real fixval;
1522 
1523  assert(scip != NULL);
1524 
1525  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1526  assert(nsubvars == heurdata->nsubvars);
1527 
1528  if( nsubbinvars == 0 && nsubintvars == 0 )
1529  {
1530  /* If we did not fix any discrete variables but found the "sub"CIP infeasible, then also the CIP is infeasible. */
1531  SCIPwarningMessage(scip, "heur_subnlp found subCIP infeasible after fixing no variables, something is strange here...\n");
1532  return SCIP_OKAY;
1533  }
1534 
1535  /* initialize */
1536  cons = NULL;
1537  consvars = NULL;
1538 
1539  /* create constraint name */
1540  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "subnlp_cutoff");
1541 
1542  /* if all discrete variables in the CIP are binary, then we create a set covering constraint
1543  * sum_{x_i fixed at 0} x_i + sum_{x_i fixed at 1} ~x_i >= 1
1544  */
1545  if( nsubintvars == 0 )
1546  {
1547  /* allocate memory for constraint variables */
1548  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars) );
1549 
1550  /* get fixations of discrete variables
1551  * to be sure, we take the values that were put into the subCIP before
1552  */
1553  nconsvars = 0;
1554  for( i = nsubbinvars - 1; i >= 0; --i )
1555  {
1556  subvar = subvars[i];
1557  assert(SCIPvarGetProbindex(subvar) == i);
1558 
1559  var = heurdata->var_subscip2scip[i];
1560  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1561  if( var == NULL )
1562  continue;
1563 
1564  fixval = SCIPvarGetLbGlobal(subvar);
1565  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1566  assert(fixval == 0.0 || fixval == 1.0); /* we have rounded values before fixing */
1567 
1568  if( fixval == 0.0 )
1569  {
1570  /* variable fixed at lower bound */
1571  consvars[nconsvars] = var;
1572  }
1573  else
1574  {
1575  SCIP_CALL( SCIPgetNegatedVar(scip, var, &consvars[nconsvars]) );
1576  }
1577 
1578  ++nconsvars;
1579  }
1580 
1581  /* create conflict constraint
1582  * In undercover, ConsLogicor is used, since then the inequality is not added to the LP.
1583  * However, I may want to use Setcover to avoid that the same fixing is computed by some LP based heuristic again.
1584  */
1585  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nconsvars, consvars,
1587  }
1588  else
1589  {
1590  /* if there are also integer variable, then create a bound disjunction constraint
1591  * x_1 >= fixval_1 + 1 || x_1 <= fixval_1 - 1 || x_2 >= fixval_2 + 1 || x_2 <= fixval_2 - 1 || ...
1592  */
1593  SCIP_BOUNDTYPE* boundtypes;
1594  SCIP_Real* bounds;
1595 
1596  /* allocate memory for constraint variables, boundtypes, and bounds
1597  * (there should be at most two literals for each integer variable)
1598  */
1599  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars + 2*nsubintvars) );
1600  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nsubbinvars + 2*nsubintvars) );
1601  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nsubbinvars + 2*nsubintvars) );
1602 
1603  /* get fixations of discrete variables
1604  * to be sure, we take the values that were put into the subCIP before
1605  */
1606  nconsvars = 0;
1607  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1608  {
1609  subvar = subvars[i];
1610  assert(SCIPvarGetProbindex(subvar) == i);
1611 
1612  var = heurdata->var_subscip2scip[i];
1613  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1614 
1615  if( var == NULL )
1616  continue;
1617 
1618  fixval = SCIPvarGetLbGlobal(subvar);
1619  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1620  assert((int)fixval == fixval); /* we have rounded values before fixing */
1621  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*/
1622 
1623  if( SCIPvarGetLbGlobal(var) < fixval )
1624  {
1625  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1626 
1627  /* literal x_i <= fixval-1 */
1628  boundtypes[nconsvars] = SCIP_BOUNDTYPE_UPPER;
1629  bounds[nconsvars] = fixval - 1.0;
1630  consvars[nconsvars] = var;
1631  ++nconsvars;
1632  }
1633 
1634  if( SCIPvarGetUbGlobal(var) > fixval )
1635  {
1636  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1637 
1638  /* literal x_i >= fixval+1 */
1639  boundtypes[nconsvars] = SCIP_BOUNDTYPE_LOWER;
1640  bounds[nconsvars] = fixval + 1.0;
1641  consvars[nconsvars] = var;
1642  ++nconsvars;
1643  }
1644  }
1645 
1646  /* create conflict constraint */
1647  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, nconsvars, consvars, boundtypes, bounds,
1649 
1650  SCIPfreeBufferArray(scip, &consvars);
1651  SCIPfreeBufferArray(scip, &boundtypes);
1652  SCIPfreeBufferArray(scip, &bounds);
1653  }
1654 
1655  /* add and release constraint if created successfully */
1656  if( cons != NULL )
1657  {
1658  SCIPdebugMsg(scip, "adding constraint to forbid fixation in main problem\n");
1659  /* SCIPdebugPrintCons(scip, cons, NULL); */
1660  SCIP_CALL( SCIPaddCons(scip, cons) );
1661  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1662  }
1663 
1664  /* free memory */
1665  SCIPfreeBufferArrayNull(scip, &consvars);
1666 
1667  return SCIP_OKAY;
1668 }
1669 
1670 
1671 /** main procedure of the subNLP heuristic */
1673  SCIP* scip, /**< original SCIP data structure */
1674  SCIP_HEUR* heur, /**< heuristic data structure */
1675  SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found, no solution found, or fixing is infeasible (cutoff) */
1676  SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
1677  SCIP_Longint itercontingent, /**< iteration limit for NLP solver, or -1 for default of NLP heuristic */
1678  SCIP_Real timelimit, /**< time limit for NLP solver */
1679  SCIP_Real minimprove, /**< desired minimal relative improvement in objective function value */
1680  SCIP_Longint* iterused, /**< buffer to store number of iterations used by NLP solver, or NULL if not of interest */
1681  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
1682  )
1683 {
1684  SCIP_HEURDATA* heurdata;
1685  SCIP_VAR* var;
1686  SCIP_VAR* subvar;
1687  int i;
1688  SCIP_Real cutoff;
1689 
1690  assert(scip != NULL);
1691  assert(heur != NULL);
1692 
1693  /* get heuristic's data */
1694  heurdata = SCIPheurGetData(heur);
1695  assert(heurdata != NULL);
1696 
1697  /* try to setup NLP if not tried before */
1698  if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
1699  {
1700  SCIP_CALL( createSubSCIP(scip, heurdata) );
1701  }
1702 
1703  *result = SCIP_DIDNOTRUN;
1704 
1705  /* not initialized */
1706  if( heurdata->subscip == NULL )
1707  return SCIP_OKAY;
1708 
1709  assert(heurdata->nsubvars > 0);
1710  assert(heurdata->var_subscip2scip != NULL);
1711  assert(!SCIPisTransformed(heurdata->subscip));
1712 
1713  if( iterused != NULL )
1714  *iterused = 0;
1715 
1716  /* fix discrete variables in sub-SCIP */
1717  if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1718  {
1719  SCIP_Real fixval;
1720  SCIP_VAR** subvars;
1721  int nsubvars;
1722  int nsubbinvars;
1723  int nsubintvars;
1724 
1725  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1726  assert(nsubvars == heurdata->nsubvars);
1727 
1728  /* fix discrete variables to values in startpoint */
1729  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1730  {
1731  subvar = subvars[i];
1732  assert(SCIPvarGetProbindex(subvar) == i);
1733 
1734  var = heurdata->var_subscip2scip[i];
1735  assert(var != NULL);
1736 
1737  /* at this point, variables in subscip and in our scip should have same bounds */
1738  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
1739  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
1740 
1741  fixval = SCIPgetSolVal(scip, refpoint, var);
1742 
1743  /* only run heuristic on integer feasible points */
1744  if( !SCIPisFeasIntegral(scip, fixval) )
1745  {
1746  if( refpoint || SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
1747  {
1748  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
1749  goto CLEANUP;
1750  }
1751  /* otherwise we desperately wanna run the NLP heur, so we continue and round what we have */
1752  }
1753  /* if we do not really have a startpoint, then we should take care that we do not fix variables to very large values
1754  * thus, we set to 0.0 here and project on bounds below
1755  */
1756  if( REALABS(fixval) > 1E+10 && !refpoint && SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1757  fixval = 0.0;
1758 
1759  /* fixing variables to infinity causes problems, we should not have been passed such a solution as refpoint */
1760  assert(!SCIPisInfinity(scip, REALABS(fixval)));
1761 
1762  /* round fractional variables to the nearest integer,
1763  * use exact integral value, if the variable is only integral within numerical tolerances
1764  */
1765  fixval = SCIPfloor(scip, fixval+0.5);
1766 
1767  /* adjust value to the global bounds of the corresponding SCIP variable */
1768  fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
1769  fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
1770 
1771  /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
1772  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, fixval) );
1773  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, fixval) );
1774  }
1775  }
1776 
1777  /* if there is already a solution, add an objective cutoff in sub-SCIP */
1778  if( SCIPgetNSols(scip) > 0 )
1779  {
1780  SCIP_Real upperbound;
1781 
1782  assert( !SCIPisInfinity(scip, SCIPgetUpperbound(scip)) );
1783 
1784  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1785 
1786  if( !SCIPisInfinity(scip, -SCIPgetLowerbound(scip)) )
1787  {
1788  cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
1789  }
1790  else
1791  {
1792  if( SCIPgetUpperbound(scip) >= 0 )
1793  cutoff = ( 1.0 - minimprove ) * SCIPgetUpperbound(scip);
1794  else
1795  cutoff = ( 1.0 + minimprove ) * SCIPgetUpperbound(scip);
1796  }
1797  cutoff = MIN(upperbound, cutoff);
1798  SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
1799  SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
1800  }
1801  else
1802  cutoff = SCIPinfinity(scip);
1803 
1804  /* solve the subNLP and try to add solution to SCIP */
1805  SCIP_CALL( solveSubNLP(scip, heur, result, refpoint, itercontingent, timelimit, iterused, FALSE, resultsol) );
1806 
1807  if( heurdata->subscip == NULL )
1808  {
1809  /* something horrible must have happened that we decided to give up completely on this heuristic */
1810  *result = SCIP_DIDNOTFIND;
1811  return SCIP_OKAY;
1812  }
1813  assert(!SCIPisTransformed(heurdata->subscip));
1814 
1815  if( *result == SCIP_CUTOFF )
1816  {
1817  if( heurdata->subscipisvalid && SCIPgetNActivePricers(scip) == 0 )
1818  {
1819  /* 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 */
1820  if( SCIPisInfinity(scip, cutoff) && heurdata->forbidfixings )
1821  {
1822  SCIP_CALL( forbidFixation(scip, heurdata) );
1823  }
1824  }
1825  else
1826  {
1827  /* if the subNLP turned out to be globally infeasible but we are not sure that we have a valid copy, we change to DIDNOTFIND */
1828  *result = SCIP_DIDNOTFIND;
1829  }
1830  }
1831 
1832  CLEANUP:
1833  /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
1834  * also if keepcopy is disabled, then destroy subSCIP
1835  */
1836  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
1837  {
1838  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1839  heurdata->triedsetupsubscip = FALSE;
1840  }
1841  else if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1842  {
1843  /* undo fixing of discrete variables in sub-SCIP */
1844  SCIP_VAR** subvars;
1845  int nsubvars;
1846  int nsubbinvars;
1847  int nsubintvars;
1848 
1849  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1850  assert(nsubvars == heurdata->nsubvars);
1851 
1852  /* set bounds of discrete variables to original values */
1853  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1854  {
1855  subvar = subvars[i];
1856  assert(SCIPvarGetProbindex(subvar) == i);
1857 
1858  var = heurdata->var_subscip2scip[i];
1859  assert(var != NULL);
1860 
1861  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
1862  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
1863  }
1864  }
1865 
1866  return SCIP_OKAY;
1867 }
1868 
1869 /** for a given solution, resolves the corresponding subNLP and updates solution values for continuous variables, if NLP solution is feasible in original problem */
1871  SCIP* scip, /**< original SCIP data structure */
1872  SCIP_HEUR* heur, /**< heuristic data structure */
1873  SCIP_SOL* sol, /**< solution for which to solve NLP, and where to store resolved solution values */
1874  SCIP_Bool* success, /**< buffer where to store whether a feasible solution was found */
1875  SCIP_Longint itercontingent, /**< iteration limit for NLP solver, or -1 for default of NLP heuristic */
1876  SCIP_Real timelimit /**< time limit for NLP solver */
1877  )
1878 {
1879  SCIP_HEURDATA* heurdata;
1880  SCIP_VAR* var;
1881  SCIP_VAR* subvar;
1882  int i;
1883  SCIP_Real cutoff;
1884  SCIP_RESULT result;
1885 
1886  assert(scip != NULL);
1887  assert(heur != NULL);
1888  assert(sol != NULL);
1889  assert(success != NULL);
1890 
1891  /* get heuristic's data */
1892  heurdata = SCIPheurGetData(heur);
1893  assert(heurdata != NULL);
1894 
1895  /* try to setup NLP if not tried before */
1896  if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
1897  {
1898  SCIP_CALL( createSubSCIP(scip, heurdata) );
1899  }
1900 
1901  *success = FALSE;
1902 
1903  /* not initialized */
1904  if( heurdata->subscip == NULL )
1905  return SCIP_OKAY;
1906 
1907  assert(heurdata->nsubvars > 0);
1908  assert(heurdata->var_subscip2scip != NULL);
1909  assert(!SCIPisTransformed(heurdata->subscip));
1910 
1911  result = SCIP_DIDNOTRUN;
1912 
1913  /* fix discrete variables in subSCIP */
1914  if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1915  {
1916  SCIP_Real fixval;
1917  SCIP_VAR** subvars;
1918  int nsubvars;
1919  int nsubbinvars;
1920  int nsubintvars;
1921 
1922  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1923  assert(nsubvars == heurdata->nsubvars);
1924 
1925  /* fix discrete variables to values in startpoint */
1926  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1927  {
1928  subvar = subvars[i];
1929  assert(SCIPvarGetProbindex(subvar) == i);
1930 
1931  var = heurdata->var_subscip2scip[i];
1932  assert(var != NULL);
1933 
1934  /* at this point, variables in subscip and in our scip should have same bounds */
1935  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
1936  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
1937 
1938  fixval = SCIPgetSolVal(scip, sol, var);
1939 
1940  /* only run heuristic on integer feasible points */
1941  if( !SCIPisFeasIntegral(scip, fixval) )
1942  {
1943  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
1944  goto CLEANUP;
1945  /* otherwise we desperately want to run the NLP heur, so we continue and round what we have */
1946  }
1947 
1948  /* round fractional variables to the nearest integer,
1949  * use exact integral value, if the variable is only integral within numerical tolerances
1950  */
1951  fixval = SCIPround(scip, fixval);
1952 
1953  /* adjust value to the global bounds of the corresponding SCIP variable */
1954  fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
1955  fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
1956 
1957  /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
1958  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, fixval) );
1959  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, fixval) );
1960  }
1961  }
1962 
1963  /* if there is already a solution, add an objective cutoff in subSCIP */
1964  cutoff = SCIPgetSolOrigObj(scip, sol);
1966  {
1967  cutoff += 0.01 * REALABS(cutoff);
1968  }
1969  else
1970  {
1971  cutoff -= 0.01 * REALABS(cutoff);
1972  }
1973  cutoff = SCIPtransformObj(scip, cutoff);
1974  SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
1975  SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
1976 
1977  /* solve the subNLP and try to add solution to SCIP */
1978  SCIP_CALL( solveSubNLP(scip, heur, &result, sol, itercontingent, timelimit, NULL, FALSE, sol) );
1979 
1980  if( heurdata->subscip == NULL )
1981  {
1982  /* something horrible must have happened that we decided to give up completely on this heuristic */
1983  return SCIP_OKAY;
1984  }
1985  assert(!SCIPisTransformed(heurdata->subscip));
1986 
1987  if( result == SCIP_FOUNDSOL )
1988  *success = TRUE;
1989 
1990  CLEANUP:
1991  /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
1992  * also if keepcopy is not set, then destroy subSCIP
1993  */
1994  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
1995  {
1996  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1997  heurdata->triedsetupsubscip = FALSE;
1998  }
1999  else if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
2000  {
2001  /* undo fixing of discrete variables in subSCIP */
2002  SCIP_VAR** subvars;
2003  int nsubvars;
2004  int nsubbinvars;
2005  int nsubintvars;
2006 
2007  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
2008  assert(nsubvars == heurdata->nsubvars);
2009 
2010  /* set bounds of discrete variables to original values */
2011  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
2012  {
2013  subvar = subvars[i];
2014  assert(SCIPvarGetProbindex(subvar) == i);
2015 
2016  var = heurdata->var_subscip2scip[i];
2017  assert(var != NULL);
2018 
2019  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
2020  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
2021  }
2022  }
2023 
2024  return SCIP_OKAY;
2025 }
2026 
2027 /*
2028  * Callback methods of primal heuristic
2029  */
2030 
2031 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
2032 static
2033 SCIP_DECL_HEURCOPY(heurCopySubNlp)
2034 { /*lint --e{715}*/
2035  assert(scip != NULL);
2036  assert(heur != NULL);
2037  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2038 
2039  /* call inclusion method of primal heuristic */
2041 
2042  return SCIP_OKAY;
2043 }
2044 
2045 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
2046 static
2047 SCIP_DECL_HEURFREE(heurFreeSubNlp)
2048 {
2049  SCIP_HEURDATA* heurdata;
2050  assert(scip != NULL);
2051  assert(heur != NULL);
2052 
2053  heurdata = SCIPheurGetData(heur);
2054  assert(heurdata != NULL);
2055  assert(heurdata->subscip == NULL);
2056  assert(heurdata->var_subscip2scip == NULL);
2057  assert(heurdata->var_scip2subscip == NULL);
2058  assert(heurdata->startcand == NULL);
2059 
2060  SCIPfreeBlockMemory(scip, &heurdata);
2061 
2062  return SCIP_OKAY;
2063 }
2064 
2065 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
2066 static
2067 SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
2068 {
2069  SCIP_HEURDATA* heurdata;
2070 
2071  assert(scip != NULL);
2072  assert(heur != NULL);
2073 
2074  /* skip setting up sub-SCIP if heuristic is disabled or we do not want to run the heuristic */
2075  if( SCIPheurGetFreq(heur) < 0 || !runHeuristic(scip) )
2076  return SCIP_OKAY;
2077 
2078  heurdata = SCIPheurGetData(heur);
2079  assert(heurdata != NULL);
2080  assert(heurdata->subscip == NULL);
2081 
2082  /* reset solution found counter */
2083  heurdata->nsolfound = 0;
2084 
2085  if( heurdata->keepcopy )
2086  {
2087  /* create sub-SCIP for later use */
2088  SCIP_CALL( createSubSCIP(scip, heurdata) );
2089 
2090  /* creating sub-SCIP may fail if the NLP solver interfaces did not copy into subscip */
2091  if( heurdata->subscip == NULL )
2092  return SCIP_OKAY;
2093  }
2094 
2095  /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
2096  if( SCIPheurGetFreqofs(heur) == 0 )
2098 
2099  return SCIP_OKAY;
2100 }
2101 
2102 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
2103 static
2104 SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
2105 {
2106  SCIP_HEURDATA* heurdata;
2107  assert(scip != NULL);
2108  assert(heur != NULL);
2109 
2110  /* get heuristic's data */
2111  heurdata = SCIPheurGetData(heur);
2112  assert(heurdata != NULL);
2113 
2114  if( heurdata->subscip != NULL )
2115  {
2116  SCIP_CALL( freeSubSCIP(scip, heurdata) );
2117  }
2118 
2119  /* free start candidate */
2120  if( heurdata->startcand != NULL )
2121  {
2122  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2123  }
2124 
2126 
2127  /* reset some flags and counters */
2128  heurdata->triedsetupsubscip = FALSE;
2129  heurdata->comblinearconsadded = FALSE;
2130  heurdata->contlinearconsadded = FALSE;
2131  heurdata->nseriousnlpierror = 0;
2132  heurdata->iterused = 0;
2133 
2134  return SCIP_OKAY;
2135 }
2136 
2137 
2138 /** execution method of primal heuristic */
2139 static
2140 SCIP_DECL_HEUREXEC(heurExecSubNlp)
2141 { /*lint --e{666,715}*/
2142  SCIP_HEURDATA* heurdata;
2143  SCIP_Longint itercontingent;
2144  SCIP_Real timelimit;
2145  SCIP_Longint iterused;
2146 
2147  assert(scip != NULL);
2148  assert(heur != NULL);
2149 
2150  /* obviously, we did not do anything yet */
2151  *result = SCIP_DIDNOTRUN;
2152 
2153  /* get heuristic's data */
2154  heurdata = SCIPheurGetData(heur);
2155  assert(heurdata != NULL);
2156 
2157  /* if keepcopy and subscip == NULL, then InitsolNlp decided that we do not need an NLP solver,
2158  * probably because we do not have nonlinear continuous or implicit integer variables
2159  * if triedsetupsubscip and subscip == NULL, then we run the heuristic already, but gave up due to some serious error
2160  * in both cases, we do not want to run
2161  *
2162  * otherwise, we continue and let SCIPapplyHeurSubNlp try to create subscip
2163  */
2164  if( heurdata->subscip == NULL && (heurdata->keepcopy || heurdata->triedsetupsubscip) )
2165  return SCIP_OKAY;
2166 
2167  /* if we recreate the subSCIP in every run, then also check whether we want to run the heuristic at all */
2168  if( !heurdata->keepcopy && !runHeuristic(scip) )
2169  return SCIP_OKAY;
2170 
2171  if( heurdata->startcand == NULL )
2172  {
2173  /* if no start candidate is given, we consider the LP solution of the current node */
2174 
2175  /* however, if the node was already detected to be infeasible, then there is no point to look at its LP solution */
2176  if( nodeinfeasible )
2177  return SCIP_OKAY;
2178 
2179  /* at least if we are not called the first time, we call the heuristic only if an optimal LP solution is available
2180  * if we are called the first time and the LP is unbounded, then we are quite desperate and still give the NLP a try
2181  */
2183  {
2185  {
2186  *result = SCIP_DELAYED;
2187  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and no LP solution available; LP status = %d\n", SCIPgetLPSolstat(scip));
2188  return SCIP_OKAY;
2189  }
2190  else
2191  {
2192  SCIPdebugMsg(scip, "LP is unbounded in root node, so we are quite desperate; run NLP heuristic and pray\n");
2193  }
2194  }
2195  else if( SCIPgetNLPBranchCands(scip) > 0 )
2196  {
2197  /* only call heuristic, if there are no fractional variables */
2198  *result = SCIP_DELAYED;
2199  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and current LP solution is fractional\n");
2200  return SCIP_OKAY;
2201  }
2203  {
2204  /* only call heuristic, if there is still room for improvement in the current node */
2205  SCIPdebugMsg(scip, "NLP heuristic delayed because lower and upper bound coincide in current node\n");
2206  return SCIP_OKAY;
2207  }
2208  SCIPdebugMsg(scip, "using current LP solution as startcand\n");
2209  }
2210  else
2211  {
2212  SCIPdebugMsg(scip, "have startcand from heur %s\n", SCIPsolGetHeur(heurdata->startcand) ? SCIPheurGetName(SCIPsolGetHeur(heurdata->startcand)) : "NULL");
2213  }
2214 
2215  if( !heurdata->runalways )
2216  {
2217  /* check if enough nodes have been processed so that we want to run the heuristic again */
2218 
2219  /* compute the contingent on number of iterations that the NLP solver is allowed to use
2220  * we make it depending on the current number of processed nodes
2221  */
2222  itercontingent = (SCIP_Longint)(heurdata->iterquot * SCIPgetNNodes(scip));
2223 
2224  /* weight by previous success of heuristic */
2225  itercontingent = (SCIP_Longint)(itercontingent * 3.0 * (heurdata->nsolfound+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
2226  /* add the fixed offset */
2227  itercontingent += heurdata->iteroffset;
2228  /* subtract the number of iterations used so far */
2229  itercontingent -= heurdata->iterused;
2230 
2231  if( itercontingent < heurdata->itermin )
2232  {
2233  /* not enough iterations left to start NLP solver */
2234  SCIPdebugMsg(scip, "skip NLP heuristic; contingent=%" SCIP_LONGINT_FORMAT "; minimal number of iterations=%d; success ratio=%g\n",
2235  itercontingent, heurdata->itermin, (heurdata->nsolfound+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
2236  return SCIP_OKAY;
2237  }
2238 
2239  /* enforce user given iteration limit, if given */
2240  if( heurdata->nlpiterlimit > 0 )
2241  itercontingent = MIN(itercontingent, heurdata->nlpiterlimit);
2242  }
2243  else
2244  {
2245  itercontingent = -1;
2246  }
2247 
2248  /* check whether there is enough time left */
2249  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
2250  if( !SCIPisInfinity(scip, timelimit) )
2251  {
2252  timelimit -= SCIPgetSolvingTime(scip);
2253  if( timelimit <= 0.0 )
2254  {
2255  SCIPdebugMsg(scip, "skip NLP heuristic; no time left\n");
2256  return SCIP_OKAY;
2257  }
2258  }
2259  /* enforce user given time limit, if given */
2260  if( heurdata->nlptimelimit > 0 )
2261  timelimit = MIN(heurdata->nlptimelimit, timelimit);
2262 
2263  /* so far we have not found any solution, but now we are willing to search for one */
2264  *result = SCIP_DIDNOTFIND;
2265 
2266  if( heurdata->nlpverblevel >= 1 )
2267  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "calling subnlp heuristic\n");
2268 
2269  SCIP_CALL( SCIPapplyHeurSubNlp(scip, heur, result, heurdata->startcand, itercontingent, timelimit,
2270  heurdata->minimprove, &iterused, NULL) );
2271  heurdata->iterused += iterused;
2272 
2273  /* SCIP does not like cutoff as return, so we say didnotfind, since we did not find a solution */
2274  if( *result == SCIP_CUTOFF )
2275  *result = SCIP_DIDNOTFIND;
2276 
2277  /* forget startcand */
2278  if( heurdata->startcand != NULL )
2279  {
2280  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2281  }
2282 
2283  /* reset timing, if it was changed temporary (at the root node) */
2284  if( heurtiming != HEUR_TIMING )
2286 
2287  return SCIP_OKAY;
2288 }
2289 
2290 
2291 /*
2292  * primal heuristic specific interface methods
2293  */
2294 
2295 /** creates the NLP local search primal heuristic and includes it in SCIP */
2297  SCIP* scip /**< SCIP data structure */
2298  )
2299 {
2300  SCIP_HEURDATA* heurdata;
2301  SCIP_HEUR* heur;
2302 
2303  /* create Nlp primal heuristic data */
2304  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
2305  BMSclearMemory(heurdata);
2306 
2307  /* include variable event handler */
2308  heurdata->eventhdlr = NULL;
2309  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, HEUR_NAME, "propagates a global bound change to the sub-SCIP",
2310  processVarEvent, NULL) );
2311  assert(heurdata->eventhdlr != NULL);
2312 
2313  /* include primal heuristic */
2314  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
2316  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecSubNlp, heurdata) );
2317 
2318  assert(heur != NULL);
2319 
2320  /* set non-NULL pointers to callback methods */
2321  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopySubNlp) );
2322  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeSubNlp) );
2323  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolSubNlp) );
2324  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolSubNlp) );
2325 
2326  /* add Nlp primal heuristic parameters */
2327  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpverblevel",
2328  "verbosity level of NLP solver",
2329  &heurdata->nlpverblevel, FALSE, 0, 0, INT_MAX, NULL, NULL) );
2330 
2331  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpiterlimit",
2332  "iteration limit of NLP solver; 0 to use solver default",
2333  &heurdata->nlpiterlimit, FALSE, 0, 0, INT_MAX, NULL, NULL) );
2334 
2335  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nlptimelimit",
2336  "time limit of NLP solver; 0 to use solver default",
2337  &heurdata->nlptimelimit, FALSE, 0.0, 0.0, SCIPinfinity(scip), NULL, NULL) );
2338 
2339  SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/nlpoptfile",
2340  "name of an NLP solver specific options file",
2341  &heurdata->nlpoptfile, TRUE, "", NULL, NULL) );
2342 
2343  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/resolvetolfactor",
2344  "if SCIP does not accept a NLP feasible solution, resolve NLP with feas. tolerance reduced by this factor (set to 1.0 to turn off resolve)",
2345  &heurdata->resolvetolfactor, TRUE, 0.001, 0.0, 1.0, NULL, NULL) );
2346 
2347  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resolvefromscratch",
2348  "should the NLP resolve be started from the original starting point or the infeasible solution?",
2349  &heurdata->resolvefromscratch, TRUE, TRUE, NULL, NULL) );
2350 
2351  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/iteroffset",
2352  "number of iterations added to the contingent of the total number of iterations",
2353  &heurdata->iteroffset, FALSE, 500, 0, INT_MAX, NULL, NULL) );
2354 
2355  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/iterquotient",
2356  "contingent of NLP iterations in relation to the number of nodes in SCIP",
2357  &heurdata->iterquot, FALSE, 0.1, 0.0, SCIPinfinity(scip), NULL, NULL) );
2358 
2359  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/itermin",
2360  "contingent of NLP iterations in relation to the number of nodes in SCIP",
2361  &heurdata->itermin, FALSE, 300, 0, INT_MAX, NULL, NULL) );
2362 
2363  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/runalways",
2364  "whether to run NLP heuristic always if starting point available (does not use iteroffset,iterquot,itermin)",
2365  &heurdata->runalways, FALSE, FALSE, NULL, NULL) );
2366 
2367  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
2368  "factor by which NLP heuristic should at least improve the incumbent",
2369  &heurdata->minimprove, TRUE, 0.01, 0.0, 1.0, NULL, NULL) );
2370 
2371  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxpresolverounds",
2372  "limit on number of presolve rounds in sub-SCIP (-1 for unlimited, 0 for no presolve)",
2373  &heurdata->maxpresolverounds, TRUE, -1, -1, INT_MAX, NULL, NULL) );
2374 
2375  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/forbidfixings",
2376  "whether to add constraints that forbid specific fixings that turned out to be infeasible",
2377  &heurdata->forbidfixings, FALSE, TRUE, NULL, NULL) );
2378 
2379  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/keepcopy",
2380  "whether to keep SCIP copy or to create new copy each time heuristic is applied",
2381  &heurdata->keepcopy, TRUE, TRUE, NULL, NULL) );
2382 
2383  return SCIP_OKAY;
2384 }
2385 
2386 /** adds all known linear constraint to the NLP, if initialized and not done already
2387  * This function is temporary and will hopefully become obsolete in the near future.
2388  */
2390  SCIP* scip, /**< original SCIP data structure */
2391  SCIP_HEUR* heur, /**< heuristic data structure */
2392  SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints, i.e., linear constraints that involve only discrete variables */
2393  SCIP_Bool addcontconss /**< whether to add continuous linear constraints, i.e., linear constraints that involve not only discrete variables */
2394  )
2395 {
2396  SCIP_HEURDATA* heurdata;
2397 
2398  assert(scip != NULL);
2399  assert(heur != NULL);
2400  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2401 
2402  heurdata = SCIPheurGetData(heur);
2403  assert(heurdata != NULL);
2404 
2405  /* return, if nothing to do */
2406  if( (!addcombconss || heurdata->comblinearconsadded) && (!addcontconss || heurdata->contlinearconsadded) )
2407  return SCIP_OKAY;
2408 
2410  addcombconss && !heurdata->comblinearconsadded,
2411  addcontconss && !heurdata->contlinearconsadded) );
2412 
2413  heurdata->comblinearconsadded |= addcombconss;
2414  heurdata->contlinearconsadded |= addcontconss;
2415 
2416  return SCIP_OKAY;
2417 }
2418 
2419 /** updates the starting point for the NLP heuristic
2420  *
2421  * Is called by a constraint handler that handles nonlinear constraints when a check on feasibility of a solution fails.
2422  */
2424  SCIP* scip, /**< SCIP data structure */
2425  SCIP_HEUR* heur, /**< NLP heuristic */
2426  SCIP_SOL* solcand, /**< solution candidate */
2427  SCIP_Real violation /**< constraint violation of solution candidate */
2428  )
2429 {
2430  SCIP_HEURDATA* heurdata;
2431 
2432  assert(scip != NULL);
2433  assert(heur != NULL);
2434  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2435  assert(solcand != NULL);
2436  assert(SCIPisPositive(scip, violation));
2437 
2438  /* too early or the game is over already: no more interest in starting points */
2439  if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
2440  return SCIP_OKAY;
2441 
2442  heurdata = SCIPheurGetData(heur);
2443  assert(heurdata != NULL);
2444 
2445  /* we do not have a sub-SCIP, so we also do not need a starting point */
2446  if( heurdata->subscip == NULL )
2447  return SCIP_OKAY;
2448 
2449  /* if the solution is the one we created (last), then it is useless to use it as starting point again
2450  * (we cannot check SCIPsolGetHeur()==heur, as subnlp may not be registered as author of the solution)
2451  */
2452  if( heurdata->lastsol == solcand )
2453  return SCIP_OKAY;
2454 
2455  SCIPdebugMsg(scip, "consider solution candidate with violation %g and objective %g from %s\n",
2456  violation, SCIPgetSolTransObj(scip, solcand), SCIPsolGetHeur(solcand) ? SCIPheurGetName(SCIPsolGetHeur(solcand)) : "tree");
2457 
2458  /* 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 */
2459  if( heurdata->startcand == NULL || violation < heurdata->startcandviol ||
2460  SCIPisRelGT(scip, SCIPgetSolTransObj(scip, heurdata->startcand), SCIPgetSolTransObj(scip, solcand)) )
2461  {
2462  if( heurdata->startcand != NULL )
2463  {
2464  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2465  }
2466  SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->startcand, solcand) );
2467  SCIP_CALL( SCIPunlinkSol(scip, heurdata->startcand) );
2468  heurdata->startcandviol = violation;
2469 
2470  /* remember which heuristic proposed the candidate */
2471  SCIPsolSetHeur(heurdata->startcand, SCIPgetSolHeur(scip, solcand));
2472  }
2473 
2474  return SCIP_OKAY;
2475 }
2476 
2477 /** gets sub-SCIP used by NLP heuristic, or NULL if none */
2479  SCIP* scip, /**< original SCIP data structure */
2480  SCIP_HEUR* heur /**< heuristic data structure */
2481  )
2482 {
2483  SCIP_HEURDATA* heurdata;
2484 
2485  assert(heur != NULL);
2486  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2487 
2488  heurdata = SCIPheurGetData(heur);
2489  assert(heurdata != NULL);
2490 
2491  return heurdata->subscip;
2492 }
2493 
2494 /** gets mapping of SCIP variables to sub-SCIP variables */
2496  SCIP* scip, /**< original SCIP data structure */
2497  SCIP_HEUR* heur /**< heuristic data structure */
2498  )
2499 {
2500  SCIP_HEURDATA* heurdata;
2501 
2502  assert(heur != NULL);
2503  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2504 
2505  heurdata = SCIPheurGetData(heur);
2506  assert(heurdata != NULL);
2507 
2508  return heurdata->var_scip2subscip;
2509 }
2510 
2511 /** gets mapping of sub-SCIP variables to SCIP variables */
2513  SCIP* scip, /**< original SCIP data structure */
2514  SCIP_HEUR* heur /**< heuristic data structure */
2515  )
2516 {
2517  SCIP_HEURDATA* heurdata;
2518 
2519  assert(heur != NULL);
2520  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2521 
2522  heurdata = SCIPheurGetData(heur);
2523  assert(heurdata != NULL);
2524 
2525  return heurdata->var_subscip2scip;
2526 }
2527 
2528 /** gets startpoint candidate to be used in next call to NLP heuristic, or NULL if none */
2530  SCIP* scip, /**< original SCIP data structure */
2531  SCIP_HEUR* heur /**< heuristic data structure */
2532  )
2533 {
2534  SCIP_HEURDATA* heurdata;
2535 
2536  assert(heur != NULL);
2537  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2538 
2539  heurdata = SCIPheurGetData(heur);
2540  assert(heurdata != NULL);
2541 
2542  return heurdata->startcand;
2543 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip.c:8159
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21975
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11770
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:71
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3143
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:21971
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:45371
static SCIP_RETCODE createSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:118
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:45508
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:7978
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21958
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:30965
SCIP_RETCODE SCIPnlpStatisticsCreate(SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:781
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46320
SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
Definition: scip.c:31032
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:814
Constraint handler for variable bound constraints .
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40502
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6576
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
Definition: scip.c:42675
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9172
SCIP_VAR ** SCIPgetVarMappingScip2SubScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2495
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17169
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4461
#define SCIP_MAXSTRLEN
Definition: def.h:225
SCIP_RETCODE SCIPincludeHeurSubNlp(SCIP *scip)
Definition: heur_subnlp.c:2296
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9813
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:46110
SCIP_Real SCIPnlpStatisticsGetTotalTime(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:820
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12120
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:9093
internal methods for NLPI solver interfaces
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8561
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:31348
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3133
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18461
static SCIP_RETCODE createSolFromNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_HEUR *authorheur)
Definition: heur_subnlp.c:856
static SCIP_RETCODE addLogicOrConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr)
Definition: heur_subnlp.c:574
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11554
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39108
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2764
SCIP_Bool SCIPhasNLPContinuousNonlinearity(SCIP *scip)
Definition: scip.c:30980
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip.c:5690
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:46050
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define TRUE
Definition: def.h:63
#define HEUR_FREQ
Definition: heur_subnlp.c:41
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPsolveNLP(SCIP *scip)
Definition: scip.c:31325
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5104
int SCIPheurGetFreqofs(SCIP_HEUR *heur)
Definition: heur.c:1287
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16862
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip.c:12093
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define HEUR_FREQOFS
Definition: heur_subnlp.c:42
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21973
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
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.c:8034
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4348
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:12045
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1228
SCIP_RETCODE SCIPsetNLPIntPar(SCIP *scip, SCIP_NLPPARAM type, int ival)
Definition: scip.c:31527
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2902
SCIP_RETCODE SCIPsetNLPStringPar(SCIP *scip, SCIP_NLPPARAM type, const char *sval)
Definition: scip.c:31639
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45985
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22003
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:696
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21956
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1010
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:36334
SCIP_Bool SCIPpressedCtrlC(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4776
static SCIP_RETCODE createSolFromSubScipSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_SOL *subsol, SCIP_HEUR *authorheur)
Definition: heur_subnlp.c:907
static SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
Definition: heur_subnlp.c:2104
static SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
Definition: heur_subnlp.c:2067
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1260
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22058
#define SCIPdebugMsg
Definition: scip.h:451
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.c:4237
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:3493
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPnlpStatisticsFree(SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:798
SCIP_SOL * SCIPgetStartCandidateHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2529
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:45480
SCIP_Bool SCIPisRelGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46735
static SCIP_DECL_HEUREXEC(heurExecSubNlp)
Definition: heur_subnlp.c:2140
static SCIP_RETCODE addKnapsackConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr)
Definition: heur_subnlp.c:734
static SCIP_RETCODE addSetppcConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr)
Definition: heur_subnlp.c:642
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10759
#define HEUR_DESC
Definition: heur_subnlp.c:38
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17179
Constraint handler for knapsack constraints of the form , x binary and .
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip.c:31054
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:37468
SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
Definition: scip.c:31370
static SCIP_RETCODE solveSubNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_Longint itercontingent, SCIP_Real timelimit, SCIP_Longint *iterused, SCIP_Bool tighttolerances, SCIP_SOL *resultsol)
Definition: heur_subnlp.c:949
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:8143
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:15846
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2389
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1181
static SCIP_RETCODE addVarboundConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:517
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4373
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12459
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3114
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3122
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8095
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip.c:31216
#define HEUR_DISPCHAR
Definition: heur_subnlp.c:39
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip.c:32031
static SCIP_RETCODE forbidFixation(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:1505
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.c:2333
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22004
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4602
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:921
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip.c:15685
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45753
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE freeSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:329
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2797
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2382
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38317
SCIP_RETCODE SCIPsetNLPInitialGuess(SCIP *scip, SCIP_Real *initialguess)
Definition: scip.c:31266
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9479
#define REALABS(x)
Definition: def.h:169
SCIP_Real SCIPgetLocalDualbound(SCIP *scip)
Definition: scip.c:13252
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1266
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42550
static SCIP_RETCODE addLinearConstraintsToNlp(SCIP *scip, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:805
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:584
#define HEUR_TIMING
Definition: heur_subnlp.c:44
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1353
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1307
#define HEUR_PRIORITY
Definition: heur_subnlp.c:40
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetNLPRealPar(SCIP *scip, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: scip.c:31583
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21991
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38042
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip.c:16947
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
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.c:40256
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
Definition: scip.c:31395
static SCIP_DECL_HEURFREE(heurFreeSubNlp)
Definition: heur_subnlp.c:2047
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:28948
SCIP_Real SCIPgetObjlimit(SCIP *scip)
Definition: scip.c:11184
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11114
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17556
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9214
#define HEUR_MAXDEPTH
Definition: heur_subnlp.c:43
SCIP_RETCODE SCIPresolveSolHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol, SCIP_Bool *success, SCIP_Longint itercontingent, SCIP_Real timelimit)
Definition: heur_subnlp.c:1870
SCIP_RETCODE SCIPcopyConss(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool *valid)
Definition: scip.c:2661
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2423
#define MAX(x, y)
Definition: tclique_def.h:75
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.c:40070
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4660
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:37806
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8080
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40548
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39059
#define HEUR_USESSUBSCIP
Definition: heur_subnlp.c:45
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38268
Constraint handler for linear constraints in their most general form, .
SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_Longint itercontingent, SCIP_Real timelimit, SCIP_Real minimprove, SCIP_Longint *iterused, SCIP_SOL *resultsol)
Definition: heur_subnlp.c:1672
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:46061
#define BMSclearMemory(ptr)
Definition: memory.h:88
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12080
SCIP_VAR ** SCIPgetVarMappingSubScip2ScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2512
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:39976
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11725
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4549
static SCIP_RETCODE addLinearConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:444
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9193
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11680
static SCIP_DECL_HEURCOPY(heurCopySubNlp)
Definition: heur_subnlp.c:2033
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPtransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:38377
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:12728
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27417
NLP local search primal heuristic using sub-SCIPs.
#define HEUR_NAME
Definition: heur_subnlp.c:37
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11635
SCIP_HEUR * SCIPgetSolHeur(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38510
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18427
#define SCIP_Real
Definition: def.h:145
#define MIN(x, y)
Definition: memory.c:75
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1221
#define SCIP_INVALID
Definition: def.h:165
int SCIPnlpStatisticsGetNIterations(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:810
#define SCIP_Longint
Definition: def.h:130
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38011
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip.c:10917
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)
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:13717
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46098
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition: scip.c:31419
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46011
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8079
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46421
SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
Definition: heur_subnlp.c:2423
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:45494
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42699
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:89
static SCIP_DECL_EVENTEXEC(processVarEvent)
Definition: heur_subnlp.c:387
static SCIP_Bool runHeuristic(SCIP *scip)
Definition: heur_subnlp.c:99
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadvars, SCIP_VAR **quadvars, int nquadelems, SCIP_QUADELEM *quadelems, SCIP_EXPRTREE *expression, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip.c:31923
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1092
constraint handler for bound disjunction constraints
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPresetParam(SCIP *scip, const char *name)
Definition: scip.c:4987
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41409
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:288
SCIP * SCIPgetSubScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2478
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:46195
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38182
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
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.c:4293
SCIP_Bool SCIPisRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46722
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:46171
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4718
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 copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:1561
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:18740
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.c:4211
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16842
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:774
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37178
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:21995