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