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-2018 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, /* tables */
173  FALSE, /* dialogs */
174  TRUE, /* nlpis */
175  TRUE, /* message handler */
176  &success) );
177  if( !success )
178  {
179  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "In heur_subnlp: failed to copy some plugins to sub-SCIP, continue anyway\n");
180  }
181 
182  /* check if we still have NLPI's in subscip */
183  if( SCIPgetNNlpis(heurdata->subscip) <= 0 )
184  {
185  SCIPdebugMsg(scip, "some NLPIs from main SCIP did not copy into sub-SCIP, give up heuristic.\n");
186  SCIP_CALL( SCIPfree(&heurdata->subscip) );
187  SCIPhashmapFree(&varsmap);
188 
189  return SCIP_OKAY;
190  }
191 
192  /* copy parameter settings */
193  SCIP_CALL( SCIPcopyParamSettings(scip, heurdata->subscip) );
194 
195  /* create problem in sub-SCIP */
196  /* get name of the original problem and add "subnlp" */
197  (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_subnlp", SCIPgetProbName(scip));
198  SCIP_CALL( SCIPcreateProb(heurdata->subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
199  SCIPsetSubscipDepth(heurdata->subscip, SCIPgetSubscipDepth(scip) + 1);
200 
201  /* copy all variables */
202  SCIP_CALL( SCIPcopyVars(scip, heurdata->subscip, varsmap, NULL, NULL, NULL, 0, TRUE) );
203 
204  /* copy as many constraints as possible */
205  SCIP_CALL( SCIPhashmapCreate(&conssmap, SCIPblkmem(scip), SCIPgetNConss(scip)) );
206  SCIP_CALL( SCIPcopyConss(scip, heurdata->subscip, varsmap, conssmap, TRUE, FALSE, &heurdata->subscipisvalid) );
207  SCIPhashmapFree(&conssmap);
208  if( !heurdata->subscipisvalid )
209  {
210  SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "In heur_subnlp: failed to copy some constraints to sub-SCIP, continue anyway\n");
211  SCIPdebugMsg(scip, "In heur_subnlp: failed to copy some constraints to sub-SCIP, continue anyway\n");
212  }
213 
214  /* create arrays translating scip transformed vars to subscip original vars, and vice versa
215  * capture variables in SCIP and sub-SCIP
216  * catch global bound change events
217  */
218 
219  SCIP_CALL( SCIPgetVarsData(heurdata->subscip, &subvars, &heurdata->nsubvars, NULL, NULL, NULL, NULL) );
220 
221  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars) );
222 #ifndef NDEBUG
223  BMSclearMemoryArray(heurdata->var_subscip2scip, heurdata->nsubvars);
224 #endif
225 
226  heurdata->nvars = nvars;
227  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars) );
228 #ifndef NDEBUG
229  BMSclearMemoryArray(heurdata->var_scip2subscip, heurdata->nvars);
230 #endif
231 
232  /* we need to get all subscip variables, also those which are copies of fixed variables from the main scip
233  * therefore we iterate over the hashmap
234  */
235  for( i = 0; i < SCIPhashmapGetNEntries(varsmap); ++i )
236  {
237  SCIP_HASHMAPENTRY* entry;
238  entry = SCIPhashmapGetEntry(varsmap, i);
239  if( entry != NULL )
240  {
241  var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
242  subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
243 
244  assert(SCIPvarGetProbindex(subvar) >= 0);
245  assert(SCIPvarGetProbindex(subvar) <= heurdata->nsubvars);
246 
247  if( SCIPvarIsActive(var) )
248  {
249  assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
250  assert(heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == NULL); /* assert that we have no mapping for this var yet */
251  heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] = subvar;
252  }
253 
254  assert(heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] == NULL); /* assert that we have no mapping for this subvar yet */
255  heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] = var;
256 
257  SCIP_CALL( SCIPcaptureVar(scip, var) );
258  SCIP_CALL( SCIPcaptureVar(heurdata->subscip, subvar) );
259 
260  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetLbGlobal(subvar)));
261  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), SCIPvarGetUbGlobal(subvar)));
262 
263  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, NULL) );
264  }
265  }
266 
267 #ifndef NDEBUG
268  for( i = 0; i < heurdata->nvars; ++i )
269  {
270  assert(heurdata->var_scip2subscip[i] != NULL);
271  assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)vars[i]) == heurdata->var_scip2subscip[i]);
272  }
273  for( i = 0; i < heurdata->nsubvars; ++i )
274  {
275  assert(heurdata->var_subscip2scip[i] != NULL);
276  assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)heurdata->var_subscip2scip[i]) == subvars[i]);
277  }
278 #endif
279 
280  /* do not need hashmap anymore */
281  SCIPhashmapFree(&varsmap);
282 
283  /* initialize data structure for NLP solve statistics */
284  SCIP_CALL( SCIPnlpStatisticsCreate(SCIPblkmem(scip), &heurdata->nlpstatistics) );
285 
286  /* do not abort subproblem on CTRL-C */
287  SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "misc/catchctrlc", FALSE) );
288 
289  /* disable keeping solutions from one subscip solve for next solve (with usually different fixings) */
290  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "limits/maxorigsol", 0) );
291 
292  /* disable output to console */
293  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 0) );
294 
295  /* reset some limits to default values, in case users changed them in main scip (SCIPcopy copies parameter values :-() */
296  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/absgap") );
297  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/bestsol") );
298  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/gap") );
299  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/restarts") );
300  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/solutions") );
301  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/time") );
302  SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/totalnodes") );
303 
304  /* disable restarts (not sure they could be triggered on continuous problems anyway)
305  * keep normal presolving, but disable components presolver
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, "constraints/components/maxprerounds") )
313  {
314  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "constraints/components/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(SCIPblkmem(scip), &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 NLP timelimit is set to 0.0, then return immediately
979  * Previously, we were still running scip presolve, assuming the caller wanted to see if the instance is still feasible after presolve.
980  * But now we want to set a timelimit also for the scip presolve, and it is easiest to use timelimit for this.
981  */
982  if( timelimit == 0.0 )
983  goto CLEANUP;
984 
985  if( tighttolerances )
986  {
987  SCIP_Real sumepsilon;
988 
989  /* reduce feasibility tolerance of sub-SCIP and do less aggressive presolve */
990  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/feastol", heurdata->resolvetolfactor*SCIPfeastol(scip)) );
991  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/epsilon", heurdata->resolvetolfactor*SCIPepsilon(scip)) );
992  SCIP_CALL( SCIPgetRealParam(scip, "numerics/sumepsilon", &sumepsilon) );
993  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/sumepsilon", heurdata->resolvetolfactor*sumepsilon) );
994  SCIP_CALL( SCIPsetPresolving(heurdata->subscip, SCIP_PARAMSETTING_FAST, TRUE) );
995 
996  if( !SCIPisParamFixed(heurdata->subscip, "constraints/linear/aggregatevariables") )
997  {
998  SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "constraints/linear/aggregatevariables", FALSE) );
999  }
1000  }
1001 
1002  /* transform sub-SCIP */
1003  SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
1004 
1005  /* presolve sub-SCIP
1006  * set scip timelimit in case presolve is unexpectedly expensive
1007  * set node limit to 1 so that presolve can go
1008  * reset maxpresolverounds, in case user changed
1009  */
1010  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/time", timelimit) );
1011  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
1012  if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrounds") )
1013  {
1014  SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", heurdata->maxpresolverounds) );
1015  }
1016  SCIP_CALL( SCIPpresolve(heurdata->subscip) );
1017  if( SCIPpressedCtrlC(heurdata->subscip) )
1018  {
1019  SCIPdebugMsg(scip, "SCIP presolve interrupted by user\n");
1020  goto CLEANUP;
1021  }
1022  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED )
1023  {
1024  /* presolve probably found the subproblem infeasible */
1025  SCIPdebugMsg(scip, "SCIP returned from presolve in stage solved 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  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING )
1032  {
1033  /* presolve was stopped because some still existing limit was hit (e.g., memory) */
1034  SCIPdebugMsg(scip, "SCIP returned from presolve in stage presolving with status %d\n", SCIPgetStatus(heurdata->subscip));
1035  /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
1036  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
1037  *result = SCIP_CUTOFF;
1038  goto CLEANUP;
1039  }
1040  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVED);
1041 
1042  if( SCIPgetNVars(heurdata->subscip) > 0 )
1043  {
1044  /* 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) */
1045  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
1046  retcode = SCIPsolve(heurdata->subscip);
1047 
1048  /* If no NLP was constructed, then there were no nonlinearities after presolve.
1049  * So we increase the nodelimit to 1 and hope that SCIP will find some solution to this probably linear subproblem.
1050  */
1051  if( retcode == SCIP_OKAY && SCIPgetStage(heurdata->subscip) != SCIP_STAGE_SOLVED && !SCIPisNLPConstructed(heurdata->subscip) )
1052  {
1053  SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
1054  retcode = SCIPsolve(heurdata->subscip);
1055  }
1056  }
1057  else
1058  {
1059  /* If all variables were removed by presolve, but presolve did not end with status SOLVED,
1060  * then we run solve, still with nodelimit=1, and hope to find some (maybe trivial) solution.
1061  */
1062  retcode = SCIPsolve(heurdata->subscip);
1063  }
1064 
1065  /* errors in solving the subproblem should not kill the overall solving process;
1066  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
1067  if ( retcode != SCIP_OKAY )
1068  {
1069 #ifndef NDEBUG
1070  SCIP_CALL( retcode );
1071 #endif
1072  SCIPwarningMessage(scip, "Error while solving subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
1073  goto CLEANUP;
1074  }
1075 
1076  /* if the refpoint comes from a heuristic, then make it the author of a found solution,
1077  * otherwise let the subNLP heuristic claim authorship
1078  */
1079  if( refpoint == NULL || SCIPsolGetHeur(refpoint) == NULL )
1080  authorheur = heur;
1081  else
1082  authorheur = SCIPsolGetHeur(refpoint);
1083 
1084  /* if sub-SCIP found solutions already, then pass them to main scip */
1085  for( i = 0; i < SCIPgetNSols(heurdata->subscip); ++i )
1086  {
1087  SCIP_Bool stored;
1088 
1089  if( resultsol == NULL )
1090  {
1091  SCIP_SOL* sol;
1092 
1093  sol = NULL;
1094  SCIP_CALL( createSolFromSubScipSol(scip, heur, &sol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
1095 
1096  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
1097  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1098  if( stored )
1099  {
1100  if( heurdata->nlpverblevel >= 1 )
1101  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP stored solution from sub-SCIP root node\n");
1102  else
1103  {
1104  SCIPdebugMsg(scip, "SCIP stored solution from sub-SCIP root node\n");
1105  }
1106  *result = SCIP_FOUNDSOL;
1107  ++heurdata->nsolfound;
1108  break;
1109  }
1110  else
1111  {
1112  if( heurdata->nlpverblevel >= 1 )
1113  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP did not store sub-SCIP optimal solution\n");
1114  else
1115  {
1116  SCIPdebugMsg(scip, "SCIP did not store sub-SCIP optimal solution\n");
1117  }
1118  }
1119  }
1120  else
1121  {
1122  SCIP_CALL( createSolFromSubScipSol(scip, heur, &resultsol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
1123 
1124  heurdata->lastsol = resultsol;
1125  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1126  if( stored )
1127  {
1128  if( heurdata->nlpverblevel >= 1 )
1129  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP solution from sub-SCIP root node is feasible\n");
1130  else
1131  {
1132  SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is feasible\n");
1133  }
1134  *result = SCIP_FOUNDSOL;
1135  ++heurdata->nsolfound;
1136  break;
1137  }
1138  else
1139  {
1140  if( heurdata->nlpverblevel >= 1 )
1141  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP solution form sub-SCIP root node is not feasible\n");
1142  else
1143  {
1144  SCIPdebugMsg(scip, "SCIP solution form sub-SCIP root node is not feasible\n");
1145  }
1146  }
1147  }
1148  }
1149 
1150  /* we should either have variables, or the problem was trivial, in which case it should have been solved */
1151  assert(SCIPgetNVars(heurdata->subscip) > 0 || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
1152 
1153  /* if subscip is infeasible here, we signal this to the caller */
1154  if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
1155  {
1156  if( heurdata->nlpverblevel >= 1 )
1157  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "sub-SCIP detected infeasibility\n");
1158  else
1159  {
1160  SCIPdebugMsg(scip, "sub-SCIP detected infeasibility\n");
1161  }
1162 
1163  assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
1164  *result = SCIP_CUTOFF;
1165  goto CLEANUP;
1166  }
1167 
1168  /* if we stopped for some other reason, or there is no NLP, we also stop */
1169  if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
1170  goto CLEANUP;
1171 
1172  /* in most cases, the status should be nodelimit
1173  * in some cases, if the sub-SCIP is very easy, it may report optimal, so we do not need invoke an NLP solver
1174  * if the presolve found the problem infeasible, then there is no use in solving an NLP
1175  * if the user interrupted or a timelimit was reached, then we should also stop here
1176  * unbounded is very unlikely to happen, in most cases, it should have been concluded in the main scip already
1177  */
1178  switch( SCIPgetStatus(heurdata->subscip) )
1179  {
1180  case SCIP_STATUS_NODELIMIT:
1181  break; /* this is the status that is most likely happening */
1184  case SCIP_STATUS_GAPLIMIT:
1185  case SCIP_STATUS_SOLLIMIT:
1187  /* these should not happen, but if one does, it's save to go to CLEANUP */
1188  SCIPABORT();
1189  case SCIP_STATUS_OPTIMAL:
1190  case SCIP_STATUS_INFEASIBLE:
1192  case SCIP_STATUS_TIMELIMIT:
1193  case SCIP_STATUS_MEMLIMIT:
1194  case SCIP_STATUS_UNBOUNDED:
1195  case SCIP_STATUS_INFORUNBD:
1196  goto CLEANUP;
1197  default:
1198  SCIPerrorMessage("unexpected status of sub-SCIP: <%d>\n", SCIPgetStatus(heurdata->subscip));
1199  return SCIP_ERROR;
1200  } /*lint !e788*/
1201 
1202  /* add non-combinatorial linear constraints from subscip into subNLP (shall be replaced by catching row events in NLP) */
1203  SCIP_CALL( addLinearConstraintsToNlp(heurdata->subscip, FALSE, TRUE) );
1204 
1205  /* set starting values (=refpoint, if not NULL; otherwise LP solution (or pseudo solution)) */
1206  SCIP_CALL( SCIPallocBufferArray(scip, &startpoint, SCIPgetNNLPVars(heurdata->subscip)) );
1207 
1208  if( heurdata->nlpverblevel >= 2 )
1209  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "set NLP starting point\n");
1210 
1211  for( i = 0; i < SCIPgetNNLPVars(heurdata->subscip); ++i )
1212  {
1213  SCIP_Real scalar;
1214  SCIP_Real constant;
1215 
1216  subvar = SCIPgetNLPVars(heurdata->subscip)[i];
1217 
1218  /* gets corresponding original variable */
1219  scalar = 1.0;
1220  constant = 0.0;
1221  SCIP_CALL( SCIPvarGetOrigvarSum(&subvar, &scalar, &constant) );
1222  if( subvar == NULL )
1223  {
1224  startpoint[i] = constant;
1225 
1226  if( heurdata->nlpverblevel >= 2 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1227  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1228 
1229  continue;
1230  }
1231 
1232  assert(SCIPvarGetProbindex(subvar) >= 0);
1233  assert(SCIPvarGetProbindex(subvar) < heurdata->nsubvars);
1234  var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
1235  if( var == NULL || REALABS(SCIPgetSolVal(scip, refpoint, var)) > 1.0e+12 )
1236  startpoint[i] = MIN(MAX(0.0, SCIPvarGetLbGlobal(subvar)), SCIPvarGetUbGlobal(subvar)); /*lint !e666*/
1237  else
1238  /* scalar*subvar+constant corresponds to nlpvar[i], so nlpvar[i] gets value scalar*varval+constant */
1239  startpoint[i] = scalar * SCIPgetSolVal(scip, refpoint, var) + constant;
1240 
1241  if( heurdata->nlpverblevel >= 2 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
1242  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
1243  }
1244  SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, startpoint) );
1245 
1246  SCIPfreeBufferArray(scip, &startpoint);
1247 
1248  *result = SCIP_DIDNOTFIND;
1249 
1250  /* setup NLP parameters */
1251 
1252  if( tighttolerances )
1253  {
1254  /* set feasibility tolerance, if tighttolerances is set */
1255  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_FEASTOL, heurdata->resolvetolfactor*SCIPfeastol(scip)) );
1256  }
1257  /* TODO Would it make sense to already start with a tighter feastol than SCIP's?
1258  else
1259  {
1260  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_FEASTOL, 0.1*SCIPfeastol(scip)) );
1261  }
1262  */
1263 
1264  /* set option file to use by NLP solver */
1265  if( heurdata->nlpoptfile != NULL && *heurdata->nlpoptfile != '\0' )
1266  {
1267  SCIP_CALL( SCIPsetNLPStringPar(heurdata->subscip, SCIP_NLPPAR_OPTFILE, heurdata->nlpoptfile) );
1268  }
1269 
1270  /* set iteration limit for NLP solver */
1271  if( itercontingent == -1 && heurdata->nlpiterlimit > 0 )
1272  itercontingent = heurdata->nlpiterlimit;
1273  if( itercontingent > 0 )
1274  {
1275  SCIP_CALL( SCIPsetNLPIntPar(heurdata->subscip, SCIP_NLPPAR_ITLIM, (int)MIN(INT_MAX, itercontingent)) );
1276  }
1277 
1278  /* set time limit for NLP solver */
1279  SCIP_CALL( SCIPsetNLPRealPar(heurdata->subscip, SCIP_NLPPAR_TILIM, timelimit) );
1280 
1281  /* set verbosity of NLP solver */
1282  SCIP_CALL( SCIPsetNLPIntPar(heurdata->subscip, SCIP_NLPPAR_VERBLEVEL, heurdata->nlpverblevel) );
1283 
1284 
1285  /* let the NLP solver do its magic */
1286  SCIPdebugMsg(scip, "start NLP solve with iteration limit %" SCIP_LONGINT_FORMAT " and timelimit %g\n", itercontingent, timelimit);
1287  SCIP_CALL( SCIPsolveNLP(heurdata->subscip) );
1288 
1289  SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
1290  SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
1291 
1292  if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_MEMERR )
1293  {
1294  /* oops, something did not go well at all */
1295  if( heurdata->nlpverblevel >= 1 )
1296  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d.",
1297  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip));
1298 
1299  ++(heurdata->nseriousnlpierror);
1301  "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d. This was the %d%s successive time.\n",
1302  SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip), heurdata->nseriousnlpierror,
1303  heurdata->nseriousnlpierror == 1 ? "st" : heurdata->nseriousnlpierror == 2 ? "nd" : heurdata->nseriousnlpierror == 3 ? "rd" : "th");
1304  if( heurdata->nseriousnlpierror >= 5 )
1305  {
1306  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Will not run NLP heuristic again for this run.\n");
1307  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1308  }
1309  goto CLEANUP;
1310  }
1311  heurdata->nseriousnlpierror = 0;
1312 
1313  SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, heurdata->nlpstatistics) );
1314 
1315  if( iterused != NULL )
1316  *iterused += SCIPnlpStatisticsGetNIterations(heurdata->nlpstatistics);
1317  SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds\n",
1318  SCIPnlpStatisticsGetNIterations(heurdata->nlpstatistics), SCIPnlpStatisticsGetTotalTime(heurdata->nlpstatistics));
1319 
1320  /* NLP solver claims it found a feasible (maybe even optimal) solution
1321  * if the objective value is better than our cutoff, then try to add it
1322  * if we do not plan to add the solution (resultsol != NULL), then also check it if objective value is not better than objlimit
1323  */
1324  if( SCIPgetNLPSolstat(heurdata->subscip) <= SCIP_NLPSOLSTAT_FEASIBLE && (resultsol != NULL || SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip))) )
1325  {
1326  if( resultsol == NULL )
1327  {
1328  SCIP_SOL* sol;
1329  SCIP_Bool stored;
1330 
1331  sol = NULL;
1332  SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
1333 
1334  heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
1335  if( heurdata->resolvefromscratch )
1336  {
1337 #ifdef SCIP_DEBUG
1338  /* print the infeasibilities to stdout */
1339  SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
1340 #else
1341  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1342 #endif
1343  }
1344  else
1345  {
1346 #ifdef SCIP_DEBUG
1347  /* print the infeasibilities to stdout */
1348  SCIP_CALL( SCIPtrySol(scip, sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
1349 #else
1350  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
1351 #endif
1352  }
1353 
1354  if( stored )
1355  { /* SCIP stored solution (yippi!), so we are done */
1356  if( heurdata->nlpverblevel >= 1 )
1357  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "SCIP stored subnlp solution\n");
1358  else
1359  {
1360  SCIPdebugMsg(scip, "SCIP stored subnlp solution\n");
1361  }
1362 
1363  *result = SCIP_FOUNDSOL;
1364  ++heurdata->nsolfound;
1365  }
1366  else if( !tighttolerances && heurdata->resolvetolfactor < 1.0 )
1367  {
1368  /* if SCIP does not like solution, we try again with tighter tolerances recreate subproblem and resolve with tighter tolerances */
1369  if( heurdata->nlpverblevel >= 1 )
1370  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1371  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1372  else
1373  {
1374  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1375  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1376  }
1377 
1378  /* free transformed problem */
1379  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1380 
1381  SCIP_CALL( solveSubNLP(scip, heur, result, heurdata->resolvefromscratch ? refpoint : sol, itercontingent, timelimit, iterused, TRUE, resultsol) );
1382  }
1383  else
1384  {
1385  if( heurdata->nlpverblevel >= 1 )
1386  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not stored by SCIP\n");
1387  else
1388  {
1389  SCIPdebugMsg(scip, "solution reported by NLP solver not stored by SCIP\n");
1390  }
1391  }
1392 
1393  if( sol != NULL )
1394  {
1395  SCIP_CALL( SCIPfreeSol(scip, &sol) );
1396  }
1397  }
1398  else
1399  {
1400  SCIP_Bool feasible;
1401 
1402  SCIP_CALL( createSolFromNLP(scip, heur, &resultsol, authorheur) );
1403 
1404  heurdata->lastsol = resultsol;
1405 #ifdef SCIP_DEBUG
1406  /* print the infeasibilities to stdout */
1407  SCIP_CALL( SCIPcheckSol(scip, resultsol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
1408 #else
1409  SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
1410 #endif
1411  if( feasible )
1412  {
1413  /* SCIP find solution feasible, so we are done */
1414  if( heurdata->nlpverblevel >= 1 )
1415  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver feasible for SCIP\n");
1416  else
1417  {
1418  SCIPdebugMsg(scip, "solution reported by NLP solver feasible for SCIP\n");
1419  }
1420  *result = SCIP_FOUNDSOL;
1421  ++heurdata->nsolfound;
1422  }
1423  else if( !tighttolerances && heurdata->resolvetolfactor < 1.0 )
1424  {
1425  /* free transformed problem */
1426  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1427 
1428  /* if SCIP does not like solution, we try again with tighter tolerances
1429  * recreate subproblem and resolve with tighter tolerances
1430  */
1431  if( heurdata->nlpverblevel >= 1 )
1433  "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1434  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1435  else
1436  {
1437  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP, resolve with feasibility tolerance %g and epsilon %g\n",
1438  heurdata->resolvetolfactor*SCIPfeastol(scip), heurdata->resolvetolfactor*SCIPepsilon(scip));
1439  }
1440 
1441  SCIP_CALL( solveSubNLP(scip, heur, result, heurdata->resolvefromscratch ? refpoint : resultsol, itercontingent, timelimit, iterused, TRUE, resultsol) );
1442  }
1443  else
1444  {
1445  if( heurdata->nlpverblevel >= 1 )
1446  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "solution reported by NLP solver not feasible for SCIP\n");
1447  else
1448  {
1449  SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP\n");
1450  }
1451  }
1452  }
1453  }
1454  else if( heurdata->nlpverblevel >= 1 )
1455  {
1456  /* print the violation of the NLP solution candidate */
1457  if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
1458  {
1459  SCIP_SOL* sol;
1460  SCIP_Bool feasible;
1461 
1462  sol = NULL;
1463  SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
1464 
1465  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "subnlp solution is infeasbile\n");
1466 
1467  /* print the infeasibilities to stdout */
1468  SCIP_CALL( SCIPcheckSol(scip, sol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
1469 
1470  SCIP_CALL( SCIPfreeSol(scip, &sol) );
1471  }
1472  else if( heurdata->nlpverblevel >= 1
1473  && !SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip)) )
1474  {
1475  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "subnlp solution objval %e is above the objlimit %e\n",
1476  SCIPgetNLPObjval(heurdata->subscip), SCIPgetObjlimit(heurdata->subscip));
1477  }
1478  }
1479 
1480  CLEANUP:
1481  if( heurdata->subscip != NULL )
1482  {
1483  SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
1484  if( tighttolerances )
1485  {
1486  SCIP_Real sumepsilon;
1487 
1488  /* reset feasibility tolerance of sub-SCIP and reset to normal presolve */
1489  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/feastol", SCIPfeastol(scip)) );
1490  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/epsilon", SCIPepsilon(scip)) );
1491  SCIP_CALL( SCIPgetRealParam(scip, "numerics/sumepsilon", &sumepsilon) );
1492  SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "numerics/sumepsilon", sumepsilon) );
1494  SCIP_CALL( SCIPresetParam(heurdata->subscip, "constraints/linear/aggregatevariables") );
1495  }
1496  }
1497 
1498  if( iterused != NULL && *iterused == 0 )
1499  *iterused = 1;
1500 
1501  return SCIP_OKAY;
1502 }
1503 
1504 
1505 /** adds a set covering or bound disjunction constraint to the original problem */
1506 static
1508  SCIP* scip, /**< SCIP data structure */
1509  SCIP_HEURDATA* heurdata /**< heuristic data */
1510  )
1511 {
1512  SCIP_VAR** subvars;
1513  int nsubvars;
1514  int nsubbinvars;
1515  int nsubintvars;
1516  SCIP_VAR* var;
1517  SCIP_VAR* subvar;
1518  SCIP_CONS* cons;
1519  SCIP_VAR** consvars;
1520  int nconsvars;
1521  char name[SCIP_MAXSTRLEN];
1522  int i;
1523  SCIP_Real fixval;
1524 
1525  assert(scip != NULL);
1526 
1527  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1528  assert(nsubvars == heurdata->nsubvars);
1529 
1530  if( nsubbinvars == 0 && nsubintvars == 0 )
1531  {
1532  /* If we did not fix any discrete variables but found the "sub"CIP infeasible, then also the CIP is infeasible. */
1533  SCIPwarningMessage(scip, "heur_subnlp found subCIP infeasible after fixing no variables, something is strange here...\n");
1534  return SCIP_OKAY;
1535  }
1536 
1537  /* initialize */
1538  cons = NULL;
1539  consvars = NULL;
1540 
1541  /* create constraint name */
1542  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "subnlp_cutoff");
1543 
1544  /* if all discrete variables in the CIP are binary, then we create a set covering constraint
1545  * sum_{x_i fixed at 0} x_i + sum_{x_i fixed at 1} ~x_i >= 1
1546  */
1547  if( nsubintvars == 0 )
1548  {
1549  /* allocate memory for constraint variables */
1550  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars) );
1551 
1552  /* get fixations of discrete variables
1553  * to be sure, we take the values that were put into the subCIP before
1554  */
1555  nconsvars = 0;
1556  for( i = nsubbinvars - 1; i >= 0; --i )
1557  {
1558  subvar = subvars[i];
1559  assert(SCIPvarGetProbindex(subvar) == i);
1560 
1561  var = heurdata->var_subscip2scip[i];
1562  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1563  if( var == NULL )
1564  continue;
1565 
1566  fixval = SCIPvarGetLbGlobal(subvar);
1567  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1568  assert(fixval == 0.0 || fixval == 1.0); /* we have rounded values before fixing */
1569 
1570  if( fixval == 0.0 )
1571  {
1572  /* variable fixed at lower bound */
1573  consvars[nconsvars] = var;
1574  }
1575  else
1576  {
1577  SCIP_CALL( SCIPgetNegatedVar(scip, var, &consvars[nconsvars]) );
1578  }
1579 
1580  ++nconsvars;
1581  }
1582 
1583  /* create conflict constraint
1584  * In undercover, ConsLogicor is used, since then the inequality is not added to the LP.
1585  * However, I may want to use Setcover to avoid that the same fixing is computed by some LP based heuristic again.
1586  */
1587  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nconsvars, consvars,
1589  }
1590  else
1591  {
1592  /* if there are also integer variable, then create a bound disjunction constraint
1593  * x_1 >= fixval_1 + 1 || x_1 <= fixval_1 - 1 || x_2 >= fixval_2 + 1 || x_2 <= fixval_2 - 1 || ...
1594  */
1595  SCIP_BOUNDTYPE* boundtypes;
1596  SCIP_Real* bounds;
1597 
1598  /* allocate memory for constraint variables, boundtypes, and bounds
1599  * (there should be at most two literals for each integer variable)
1600  */
1601  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars + 2*nsubintvars) );
1602  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nsubbinvars + 2*nsubintvars) );
1603  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nsubbinvars + 2*nsubintvars) );
1604 
1605  /* get fixations of discrete variables
1606  * to be sure, we take the values that were put into the subCIP before
1607  */
1608  nconsvars = 0;
1609  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1610  {
1611  subvar = subvars[i];
1612  assert(SCIPvarGetProbindex(subvar) == i);
1613 
1614  var = heurdata->var_subscip2scip[i];
1615  assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
1616 
1617  if( var == NULL )
1618  continue;
1619 
1620  fixval = SCIPvarGetLbGlobal(subvar);
1621  assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
1622  assert((int)fixval == fixval); /* we have rounded values before fixing */
1623  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*/
1624 
1625  if( SCIPvarGetLbGlobal(var) < fixval )
1626  {
1627  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1628 
1629  /* literal x_i <= fixval-1 */
1630  boundtypes[nconsvars] = SCIP_BOUNDTYPE_UPPER;
1631  bounds[nconsvars] = fixval - 1.0;
1632  consvars[nconsvars] = var;
1633  ++nconsvars;
1634  }
1635 
1636  if( SCIPvarGetUbGlobal(var) > fixval )
1637  {
1638  assert(nconsvars < nsubbinvars + 2*nsubintvars);
1639 
1640  /* literal x_i >= fixval+1 */
1641  boundtypes[nconsvars] = SCIP_BOUNDTYPE_LOWER;
1642  bounds[nconsvars] = fixval + 1.0;
1643  consvars[nconsvars] = var;
1644  ++nconsvars;
1645  }
1646  }
1647 
1648  /* create conflict constraint */
1649  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, nconsvars, consvars, boundtypes, bounds,
1651 
1652  SCIPfreeBufferArray(scip, &consvars);
1653  SCIPfreeBufferArray(scip, &boundtypes);
1654  SCIPfreeBufferArray(scip, &bounds);
1655  }
1656 
1657  /* add and release constraint if created successfully */
1658  if( cons != NULL )
1659  {
1660  SCIPdebugMsg(scip, "adding constraint to forbid fixation in main problem\n");
1661  /* SCIPdebugPrintCons(scip, cons, NULL); */
1662  SCIP_CALL( SCIPaddCons(scip, cons) );
1663  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1664  }
1665 
1666  /* free memory */
1667  SCIPfreeBufferArrayNull(scip, &consvars);
1668 
1669  return SCIP_OKAY;
1670 }
1671 
1672 
1673 /** main procedure of the subNLP heuristic */
1675  SCIP* scip, /**< original SCIP data structure */
1676  SCIP_HEUR* heur, /**< heuristic data structure */
1677  SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found, no solution found, or fixing is infeasible (cutoff) */
1678  SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
1679  SCIP_Longint itercontingent, /**< iteration limit for NLP solver, or -1 for default of NLP heuristic */
1680  SCIP_Real timelimit, /**< time limit for NLP solver */
1681  SCIP_Real minimprove, /**< desired minimal relative improvement in objective function value */
1682  SCIP_Longint* iterused, /**< buffer to store number of iterations used by NLP solver, or NULL if not of interest */
1683  SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
1684  )
1685 {
1686  SCIP_HEURDATA* heurdata;
1687  SCIP_VAR* var;
1688  SCIP_VAR* subvar;
1689  int i;
1690  SCIP_Real cutoff;
1691 
1692  assert(scip != NULL);
1693  assert(heur != NULL);
1694 
1695  /* get heuristic's data */
1696  heurdata = SCIPheurGetData(heur);
1697  assert(heurdata != NULL);
1698 
1699  /* try to setup NLP if not tried before */
1700  if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
1701  {
1702  SCIP_CALL( createSubSCIP(scip, heurdata) );
1703  }
1704 
1705  *result = SCIP_DIDNOTRUN;
1706 
1707  /* not initialized */
1708  if( heurdata->subscip == NULL )
1709  return SCIP_OKAY;
1710 
1711  assert(heurdata->nsubvars > 0);
1712  assert(heurdata->var_subscip2scip != NULL);
1713  assert(!SCIPisTransformed(heurdata->subscip));
1714 
1715  if( iterused != NULL )
1716  *iterused = 0;
1717 
1718  /* fix discrete variables in sub-SCIP */
1719  if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1720  {
1721  SCIP_Real fixval;
1722  SCIP_VAR** subvars;
1723  int nsubvars;
1724  int nsubbinvars;
1725  int nsubintvars;
1726 
1727  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1728  assert(nsubvars == heurdata->nsubvars);
1729 
1730  /* fix discrete variables to values in startpoint */
1731  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1732  {
1733  subvar = subvars[i];
1734  assert(SCIPvarGetProbindex(subvar) == i);
1735 
1736  var = heurdata->var_subscip2scip[i];
1737  assert(var != NULL);
1738 
1739  /* at this point, variables in subscip and in our scip should have same bounds */
1740  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
1741  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
1742 
1743  fixval = SCIPgetSolVal(scip, refpoint, var);
1744 
1745  /* only run heuristic on integer feasible points */
1746  if( !SCIPisFeasIntegral(scip, fixval) )
1747  {
1748  if( refpoint || SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
1749  {
1750  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
1751  goto CLEANUP;
1752  }
1753  /* otherwise we desperately wanna run the NLP heur, so we continue and round what we have */
1754  }
1755  /* if we do not really have a startpoint, then we should take care that we do not fix variables to very large values
1756  * thus, we set to 0.0 here and project on bounds below
1757  */
1758  if( REALABS(fixval) > 1E+10 && !refpoint && SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1759  fixval = 0.0;
1760 
1761  /* fixing variables to infinity causes problems, we should not have been passed such a solution as refpoint */
1762  assert(!SCIPisInfinity(scip, REALABS(fixval)));
1763 
1764  /* round fractional variables to the nearest integer,
1765  * use exact integral value, if the variable is only integral within numerical tolerances
1766  */
1767  fixval = SCIPfloor(scip, fixval+0.5);
1768 
1769  /* adjust value to the global bounds of the corresponding SCIP variable */
1770  fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
1771  fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
1772 
1773  /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
1774  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, fixval) );
1775  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, fixval) );
1776  }
1777  }
1778 
1779  /* if there is already a solution, add an objective cutoff in sub-SCIP */
1780  if( SCIPgetNSols(scip) > 0 )
1781  {
1782  SCIP_Real upperbound;
1783 
1784  assert( !SCIPisInfinity(scip, SCIPgetUpperbound(scip)) );
1785 
1786  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1787 
1788  if( !SCIPisInfinity(scip, -SCIPgetLowerbound(scip)) )
1789  {
1790  cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
1791  }
1792  else
1793  {
1794  if( SCIPgetUpperbound(scip) >= 0 )
1795  cutoff = ( 1.0 - minimprove ) * SCIPgetUpperbound(scip);
1796  else
1797  cutoff = ( 1.0 + minimprove ) * SCIPgetUpperbound(scip);
1798  }
1799  cutoff = MIN(upperbound, cutoff);
1800  SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
1801  SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
1802  }
1803  else
1804  cutoff = SCIPinfinity(scip);
1805 
1806  /* solve the subNLP and try to add solution to SCIP */
1807  SCIP_CALL( solveSubNLP(scip, heur, result, refpoint, itercontingent, timelimit, iterused, FALSE, resultsol) );
1808 
1809  if( heurdata->subscip == NULL )
1810  {
1811  /* something horrible must have happened that we decided to give up completely on this heuristic */
1812  *result = SCIP_DIDNOTFIND;
1813  return SCIP_OKAY;
1814  }
1815  assert(!SCIPisTransformed(heurdata->subscip));
1816 
1817  if( *result == SCIP_CUTOFF )
1818  {
1819  if( heurdata->subscipisvalid && SCIPgetNActivePricers(scip) == 0 )
1820  {
1821  /* 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 */
1822  if( SCIPisInfinity(scip, cutoff) && heurdata->forbidfixings )
1823  {
1824  SCIP_CALL( forbidFixation(scip, heurdata) );
1825  }
1826  }
1827  else
1828  {
1829  /* if the subNLP turned out to be globally infeasible but we are not sure that we have a valid copy, we change to DIDNOTFIND */
1830  *result = SCIP_DIDNOTFIND;
1831  }
1832  }
1833 
1834  CLEANUP:
1835  /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
1836  * also if keepcopy is disabled, then destroy subSCIP
1837  */
1838  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
1839  {
1840  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1841  heurdata->triedsetupsubscip = FALSE;
1842  }
1843  else if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1844  {
1845  /* undo fixing of discrete variables in sub-SCIP */
1846  SCIP_VAR** subvars;
1847  int nsubvars;
1848  int nsubbinvars;
1849  int nsubintvars;
1850 
1851  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1852  assert(nsubvars == heurdata->nsubvars);
1853 
1854  /* set bounds of discrete variables to original values */
1855  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1856  {
1857  subvar = subvars[i];
1858  assert(SCIPvarGetProbindex(subvar) == i);
1859 
1860  var = heurdata->var_subscip2scip[i];
1861  assert(var != NULL);
1862 
1863  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
1864  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
1865  }
1866  }
1867 
1868  return SCIP_OKAY;
1869 }
1870 
1871 /** for a given solution, resolves the corresponding subNLP and updates solution values for continuous variables, if NLP solution is feasible in original problem */
1873  SCIP* scip, /**< original SCIP data structure */
1874  SCIP_HEUR* heur, /**< heuristic data structure */
1875  SCIP_SOL* sol, /**< solution for which to solve NLP, and where to store resolved solution values */
1876  SCIP_Bool* success, /**< buffer where to store whether a feasible solution was found */
1877  SCIP_Longint itercontingent, /**< iteration limit for NLP solver, or -1 for default of NLP heuristic */
1878  SCIP_Real timelimit /**< time limit for NLP solver */
1879  )
1880 {
1881  SCIP_HEURDATA* heurdata;
1882  SCIP_VAR* var;
1883  SCIP_VAR* subvar;
1884  int i;
1885  SCIP_Real cutoff;
1886  SCIP_RESULT result;
1887 
1888  assert(scip != NULL);
1889  assert(heur != NULL);
1890  assert(sol != NULL);
1891  assert(success != NULL);
1892 
1893  /* get heuristic's data */
1894  heurdata = SCIPheurGetData(heur);
1895  assert(heurdata != NULL);
1896 
1897  /* try to setup NLP if not tried before */
1898  if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
1899  {
1900  SCIP_CALL( createSubSCIP(scip, heurdata) );
1901  }
1902 
1903  *success = FALSE;
1904 
1905  /* not initialized */
1906  if( heurdata->subscip == NULL )
1907  return SCIP_OKAY;
1908 
1909  assert(heurdata->nsubvars > 0);
1910  assert(heurdata->var_subscip2scip != NULL);
1911  assert(!SCIPisTransformed(heurdata->subscip));
1912 
1913  result = SCIP_DIDNOTRUN;
1914 
1915  /* fix discrete variables in subSCIP */
1916  if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
1917  {
1918  SCIP_Real fixval;
1919  SCIP_VAR** subvars;
1920  int nsubvars;
1921  int nsubbinvars;
1922  int nsubintvars;
1923 
1924  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
1925  assert(nsubvars == heurdata->nsubvars);
1926 
1927  /* fix discrete variables to values in startpoint */
1928  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
1929  {
1930  subvar = subvars[i];
1931  assert(SCIPvarGetProbindex(subvar) == i);
1932 
1933  var = heurdata->var_subscip2scip[i];
1934  assert(var != NULL);
1935 
1936  /* at this point, variables in subscip and in our scip should have same bounds */
1937  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
1938  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
1939 
1940  fixval = SCIPgetSolVal(scip, sol, var);
1941 
1942  /* only run heuristic on integer feasible points */
1943  if( !SCIPisFeasIntegral(scip, fixval) )
1944  {
1945  SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
1946  goto CLEANUP;
1947  /* otherwise we desperately want to run the NLP heur, so we continue and round what we have */
1948  }
1949 
1950  /* round fractional variables to the nearest integer,
1951  * use exact integral value, if the variable is only integral within numerical tolerances
1952  */
1953  fixval = SCIPround(scip, fixval);
1954 
1955  /* adjust value to the global bounds of the corresponding SCIP variable */
1956  fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
1957  fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
1958 
1959  /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
1960  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, fixval) );
1961  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, fixval) );
1962  }
1963  }
1964 
1965  /* if there is already a solution, add an objective cutoff in subSCIP */
1966  cutoff = SCIPgetSolOrigObj(scip, sol);
1968  {
1969  cutoff += 0.01 * REALABS(cutoff);
1970  }
1971  else
1972  {
1973  cutoff -= 0.01 * REALABS(cutoff);
1974  }
1975  cutoff = SCIPtransformObj(scip, cutoff);
1976  SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
1977  SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
1978 
1979  /* solve the subNLP and try to add solution to SCIP */
1980  SCIP_CALL( solveSubNLP(scip, heur, &result, sol, itercontingent, timelimit, NULL, FALSE, sol) );
1981 
1982  if( heurdata->subscip == NULL )
1983  {
1984  /* something horrible must have happened that we decided to give up completely on this heuristic */
1985  return SCIP_OKAY;
1986  }
1987  assert(!SCIPisTransformed(heurdata->subscip));
1988 
1989  if( result == SCIP_FOUNDSOL )
1990  *success = TRUE;
1991 
1992  CLEANUP:
1993  /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
1994  * also if keepcopy is not set, then destroy subSCIP
1995  */
1996  if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
1997  {
1998  SCIP_CALL( freeSubSCIP(scip, heurdata) );
1999  heurdata->triedsetupsubscip = FALSE;
2000  }
2001  else if( SCIPgetNBinVars(heurdata->subscip) || SCIPgetNIntVars(heurdata->subscip) )
2002  {
2003  /* undo fixing of discrete variables in subSCIP */
2004  SCIP_VAR** subvars;
2005  int nsubvars;
2006  int nsubbinvars;
2007  int nsubintvars;
2008 
2009  SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
2010  assert(nsubvars == heurdata->nsubvars);
2011 
2012  /* set bounds of discrete variables to original values */
2013  for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
2014  {
2015  subvar = subvars[i];
2016  assert(SCIPvarGetProbindex(subvar) == i);
2017 
2018  var = heurdata->var_subscip2scip[i];
2019  assert(var != NULL);
2020 
2021  SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPvarGetLbGlobal(var)) );
2022  SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPvarGetUbGlobal(var)) );
2023  }
2024  }
2025 
2026  return SCIP_OKAY;
2027 }
2028 
2029 /*
2030  * Callback methods of primal heuristic
2031  */
2032 
2033 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
2034 static
2035 SCIP_DECL_HEURCOPY(heurCopySubNlp)
2036 { /*lint --e{715}*/
2037  assert(scip != NULL);
2038  assert(heur != NULL);
2039  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2040 
2041  /* call inclusion method of primal heuristic */
2043 
2044  return SCIP_OKAY;
2045 }
2046 
2047 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
2048 static
2049 SCIP_DECL_HEURFREE(heurFreeSubNlp)
2050 {
2051  SCIP_HEURDATA* heurdata;
2052  assert(scip != NULL);
2053  assert(heur != NULL);
2054 
2055  heurdata = SCIPheurGetData(heur);
2056  assert(heurdata != NULL);
2057  assert(heurdata->subscip == NULL);
2058  assert(heurdata->var_subscip2scip == NULL);
2059  assert(heurdata->var_scip2subscip == NULL);
2060  assert(heurdata->startcand == NULL);
2061 
2062  SCIPfreeBlockMemory(scip, &heurdata);
2063 
2064  return SCIP_OKAY;
2065 }
2066 
2067 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
2068 static
2069 SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
2070 {
2071  SCIP_HEURDATA* heurdata;
2072 
2073  assert(scip != NULL);
2074  assert(heur != NULL);
2075 
2076  /* skip setting up sub-SCIP if heuristic is disabled or we do not want to run the heuristic */
2077  if( SCIPheurGetFreq(heur) < 0 || !runHeuristic(scip) )
2078  return SCIP_OKAY;
2079 
2080  heurdata = SCIPheurGetData(heur);
2081  assert(heurdata != NULL);
2082  assert(heurdata->subscip == NULL);
2083 
2084  /* reset solution found counter */
2085  heurdata->nsolfound = 0;
2086 
2087  if( heurdata->keepcopy )
2088  {
2089  /* create sub-SCIP for later use */
2090  SCIP_CALL( createSubSCIP(scip, heurdata) );
2091 
2092  /* creating sub-SCIP may fail if the NLP solver interfaces did not copy into subscip */
2093  if( heurdata->subscip == NULL )
2094  return SCIP_OKAY;
2095  }
2096 
2097  /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
2098  if( SCIPheurGetFreqofs(heur) == 0 )
2100 
2101  return SCIP_OKAY;
2102 }
2103 
2104 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
2105 static
2106 SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
2107 {
2108  SCIP_HEURDATA* heurdata;
2109  assert(scip != NULL);
2110  assert(heur != NULL);
2111 
2112  /* get heuristic's data */
2113  heurdata = SCIPheurGetData(heur);
2114  assert(heurdata != NULL);
2115 
2116  if( heurdata->subscip != NULL )
2117  {
2118  SCIP_CALL( freeSubSCIP(scip, heurdata) );
2119  }
2120 
2121  /* free start candidate */
2122  if( heurdata->startcand != NULL )
2123  {
2124  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2125  }
2126 
2128 
2129  /* reset some flags and counters */
2130  heurdata->triedsetupsubscip = FALSE;
2131  heurdata->comblinearconsadded = FALSE;
2132  heurdata->contlinearconsadded = FALSE;
2133  heurdata->nseriousnlpierror = 0;
2134  heurdata->iterused = 0;
2135 
2136  return SCIP_OKAY;
2137 }
2138 
2139 
2140 /** execution method of primal heuristic */
2141 static
2142 SCIP_DECL_HEUREXEC(heurExecSubNlp)
2143 { /*lint --e{666,715}*/
2144  SCIP_HEURDATA* heurdata;
2145  SCIP_Longint itercontingent;
2146  SCIP_Real timelimit;
2147  SCIP_Longint iterused;
2148 
2149  assert(scip != NULL);
2150  assert(heur != NULL);
2151 
2152  /* obviously, we did not do anything yet */
2153  *result = SCIP_DIDNOTRUN;
2154 
2155  /* get heuristic's data */
2156  heurdata = SCIPheurGetData(heur);
2157  assert(heurdata != NULL);
2158 
2159  /* if keepcopy and subscip == NULL, then InitsolNlp decided that we do not need an NLP solver,
2160  * probably because we do not have nonlinear continuous or implicit integer variables
2161  * if triedsetupsubscip and subscip == NULL, then we run the heuristic already, but gave up due to some serious error
2162  * in both cases, we do not want to run
2163  *
2164  * otherwise, we continue and let SCIPapplyHeurSubNlp try to create subscip
2165  */
2166  if( heurdata->subscip == NULL && (heurdata->keepcopy || heurdata->triedsetupsubscip) )
2167  return SCIP_OKAY;
2168 
2169  /* if we recreate the subSCIP in every run, then also check whether we want to run the heuristic at all */
2170  if( !heurdata->keepcopy && !runHeuristic(scip) )
2171  return SCIP_OKAY;
2172 
2173  if( heurdata->startcand == NULL )
2174  {
2175  /* if no start candidate is given, we consider the LP solution of the current node */
2176 
2177  /* however, if the node was already detected to be infeasible, then there is no point to look at its LP solution */
2178  if( nodeinfeasible )
2179  return SCIP_OKAY;
2180 
2181  /* at least if we are not called the first time, we call the heuristic only if an optimal LP solution is available
2182  * if we are called the first time and the LP is unbounded, then we are quite desperate and still give the NLP a try
2183  */
2185  {
2187  {
2188  *result = SCIP_DELAYED;
2189  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and no LP solution available; LP status = %d\n", SCIPgetLPSolstat(scip));
2190  return SCIP_OKAY;
2191  }
2192  else
2193  {
2194  SCIPdebugMsg(scip, "LP is unbounded in root node, so we are quite desperate; run NLP heuristic and pray\n");
2195  }
2196  }
2197  else if( SCIPgetNLPBranchCands(scip) > 0 )
2198  {
2199  /* only call heuristic, if there are no fractional variables */
2200  *result = SCIP_DELAYED;
2201  SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and current LP solution is fractional\n");
2202  return SCIP_OKAY;
2203  }
2205  {
2206  /* only call heuristic, if there is still room for improvement in the current node */
2207  SCIPdebugMsg(scip, "NLP heuristic delayed because lower and upper bound coincide in current node\n");
2208  return SCIP_OKAY;
2209  }
2210  SCIPdebugMsg(scip, "using current LP solution as startcand\n");
2211  }
2212  else
2213  {
2214  SCIPdebugMsg(scip, "have startcand from heur %s\n", SCIPsolGetHeur(heurdata->startcand) ? SCIPheurGetName(SCIPsolGetHeur(heurdata->startcand)) : "NULL");
2215  }
2216 
2217  if( !heurdata->runalways )
2218  {
2219  /* check if enough nodes have been processed so that we want to run the heuristic again */
2220 
2221  /* compute the contingent on number of iterations that the NLP solver is allowed to use
2222  * we make it depending on the current number of processed nodes
2223  */
2224  itercontingent = (SCIP_Longint)(heurdata->iterquot * SCIPgetNNodes(scip));
2225 
2226  /* weight by previous success of heuristic */
2227  itercontingent = (SCIP_Longint)(itercontingent * 3.0 * (heurdata->nsolfound+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
2228  /* add the fixed offset */
2229  itercontingent += heurdata->iteroffset;
2230  /* subtract the number of iterations used so far */
2231  itercontingent -= heurdata->iterused;
2232 
2233  if( itercontingent < heurdata->itermin )
2234  {
2235  /* not enough iterations left to start NLP solver */
2236  SCIPdebugMsg(scip, "skip NLP heuristic; contingent=%" SCIP_LONGINT_FORMAT "; minimal number of iterations=%d; success ratio=%g\n",
2237  itercontingent, heurdata->itermin, (heurdata->nsolfound+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
2238  return SCIP_OKAY;
2239  }
2240 
2241  /* enforce user given iteration limit, if given */
2242  if( heurdata->nlpiterlimit > 0 )
2243  itercontingent = MIN(itercontingent, heurdata->nlpiterlimit);
2244  }
2245  else
2246  {
2247  itercontingent = -1;
2248  }
2249 
2250  /* check whether there is enough time left */
2251  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
2252  if( !SCIPisInfinity(scip, timelimit) )
2253  {
2254  timelimit -= SCIPgetSolvingTime(scip);
2255  if( timelimit <= 0.0 )
2256  {
2257  SCIPdebugMsg(scip, "skip NLP heuristic; no time left\n");
2258  return SCIP_OKAY;
2259  }
2260  }
2261  /* enforce user given time limit, if given */
2262  if( heurdata->nlptimelimit > 0 )
2263  timelimit = MIN(heurdata->nlptimelimit, timelimit);
2264 
2265  /* so far we have not found any solution, but now we are willing to search for one */
2266  *result = SCIP_DIDNOTFIND;
2267 
2268  if( heurdata->nlpverblevel >= 1 )
2269  SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "calling subnlp heuristic\n");
2270 
2271  SCIP_CALL( SCIPapplyHeurSubNlp(scip, heur, result, heurdata->startcand, itercontingent, timelimit,
2272  heurdata->minimprove, &iterused, NULL) );
2273  heurdata->iterused += iterused;
2274 
2275  /* SCIP does not like cutoff as return, so we say didnotfind, since we did not find a solution */
2276  if( *result == SCIP_CUTOFF )
2277  *result = SCIP_DIDNOTFIND;
2278 
2279  /* forget startcand */
2280  if( heurdata->startcand != NULL )
2281  {
2282  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2283  }
2284 
2285  /* reset timing, if it was changed temporary (at the root node) */
2286  if( heurtiming != HEUR_TIMING )
2288 
2289  return SCIP_OKAY;
2290 }
2291 
2292 
2293 /*
2294  * primal heuristic specific interface methods
2295  */
2296 
2297 /** creates the NLP local search primal heuristic and includes it in SCIP */
2299  SCIP* scip /**< SCIP data structure */
2300  )
2301 {
2302  SCIP_HEURDATA* heurdata;
2303  SCIP_HEUR* heur;
2304 
2305  /* create Nlp primal heuristic data */
2306  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
2307  BMSclearMemory(heurdata);
2308 
2309  /* include variable event handler */
2310  heurdata->eventhdlr = NULL;
2311  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, HEUR_NAME, "propagates a global bound change to the sub-SCIP",
2312  processVarEvent, NULL) );
2313  assert(heurdata->eventhdlr != NULL);
2314 
2315  /* include primal heuristic */
2316  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
2318  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecSubNlp, heurdata) );
2319 
2320  assert(heur != NULL);
2321 
2322  /* set non-NULL pointers to callback methods */
2323  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopySubNlp) );
2324  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeSubNlp) );
2325  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolSubNlp) );
2326  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolSubNlp) );
2327 
2328  /* add Nlp primal heuristic parameters */
2329  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpverblevel",
2330  "verbosity level of NLP solver",
2331  &heurdata->nlpverblevel, FALSE, 0, 0, INT_MAX, NULL, NULL) );
2332 
2333  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpiterlimit",
2334  "iteration limit of NLP solver; 0 to use solver default",
2335  &heurdata->nlpiterlimit, FALSE, 0, 0, INT_MAX, NULL, NULL) );
2336 
2337  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nlptimelimit",
2338  "time limit of NLP solver; 0 to use solver default",
2339  &heurdata->nlptimelimit, FALSE, 0.0, 0.0, SCIPinfinity(scip), NULL, NULL) );
2340 
2341  SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/nlpoptfile",
2342  "name of an NLP solver specific options file",
2343  &heurdata->nlpoptfile, TRUE, "", NULL, NULL) );
2344 
2345  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/resolvetolfactor",
2346  "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)",
2347  &heurdata->resolvetolfactor, TRUE, 0.001, 0.0, 1.0, NULL, NULL) );
2348 
2349  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resolvefromscratch",
2350  "should the NLP resolve be started from the original starting point or the infeasible solution?",
2351  &heurdata->resolvefromscratch, TRUE, TRUE, NULL, NULL) );
2352 
2353  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/iteroffset",
2354  "number of iterations added to the contingent of the total number of iterations",
2355  &heurdata->iteroffset, FALSE, 500, 0, INT_MAX, NULL, NULL) );
2356 
2357  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/iterquotient",
2358  "contingent of NLP iterations in relation to the number of nodes in SCIP",
2359  &heurdata->iterquot, FALSE, 0.1, 0.0, SCIPinfinity(scip), NULL, NULL) );
2360 
2361  SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/itermin",
2362  "contingent of NLP iterations in relation to the number of nodes in SCIP",
2363  &heurdata->itermin, FALSE, 300, 0, INT_MAX, NULL, NULL) );
2364 
2365  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/runalways",
2366  "whether to run NLP heuristic always if starting point available (does not use iteroffset,iterquot,itermin)",
2367  &heurdata->runalways, FALSE, FALSE, NULL, NULL) );
2368 
2369  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
2370  "factor by which NLP heuristic should at least improve the incumbent",
2371  &heurdata->minimprove, TRUE, 0.01, 0.0, 1.0, NULL, NULL) );
2372 
2373  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxpresolverounds",
2374  "limit on number of presolve rounds in sub-SCIP (-1 for unlimited, 0 for no presolve)",
2375  &heurdata->maxpresolverounds, TRUE, -1, -1, INT_MAX, NULL, NULL) );
2376 
2377  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/forbidfixings",
2378  "whether to add constraints that forbid specific fixings that turned out to be infeasible",
2379  &heurdata->forbidfixings, FALSE, TRUE, NULL, NULL) );
2380 
2381  SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/keepcopy",
2382  "whether to keep SCIP copy or to create new copy each time heuristic is applied",
2383  &heurdata->keepcopy, TRUE, TRUE, NULL, NULL) );
2384 
2385  return SCIP_OKAY;
2386 }
2387 
2388 /** adds all known linear constraint to the NLP, if initialized and not done already
2389  * This function is temporary and will hopefully become obsolete in the near future.
2390  */
2392  SCIP* scip, /**< original SCIP data structure */
2393  SCIP_HEUR* heur, /**< heuristic data structure */
2394  SCIP_Bool addcombconss, /**< whether to add combinatorial linear constraints, i.e., linear constraints that involve only discrete variables */
2395  SCIP_Bool addcontconss /**< whether to add continuous linear constraints, i.e., linear constraints that involve not only discrete variables */
2396  )
2397 {
2398  SCIP_HEURDATA* heurdata;
2399 
2400  assert(scip != NULL);
2401  assert(heur != NULL);
2402  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2403 
2404  heurdata = SCIPheurGetData(heur);
2405  assert(heurdata != NULL);
2406 
2407  /* return, if nothing to do */
2408  if( (!addcombconss || heurdata->comblinearconsadded) && (!addcontconss || heurdata->contlinearconsadded) )
2409  return SCIP_OKAY;
2410 
2412  addcombconss && !heurdata->comblinearconsadded,
2413  addcontconss && !heurdata->contlinearconsadded) );
2414 
2415  heurdata->comblinearconsadded |= addcombconss;
2416  heurdata->contlinearconsadded |= addcontconss;
2417 
2418  return SCIP_OKAY;
2419 }
2420 
2421 /** updates the starting point for the NLP heuristic
2422  *
2423  * Is called by a constraint handler that handles nonlinear constraints when a check on feasibility of a solution fails.
2424  */
2426  SCIP* scip, /**< SCIP data structure */
2427  SCIP_HEUR* heur, /**< NLP heuristic */
2428  SCIP_SOL* solcand, /**< solution candidate */
2429  SCIP_Real violation /**< constraint violation of solution candidate */
2430  )
2431 {
2432  SCIP_HEURDATA* heurdata;
2433 
2434  assert(scip != NULL);
2435  assert(heur != NULL);
2436  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2437  assert(solcand != NULL);
2438  assert(SCIPisPositive(scip, violation));
2439 
2440  /* too early or the game is over already: no more interest in starting points */
2441  if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
2442  return SCIP_OKAY;
2443 
2444  heurdata = SCIPheurGetData(heur);
2445  assert(heurdata != NULL);
2446 
2447  /* we do not have a sub-SCIP, so we also do not need a starting point */
2448  if( heurdata->subscip == NULL )
2449  return SCIP_OKAY;
2450 
2451  /* if the solution is the one we created (last), then it is useless to use it as starting point again
2452  * (we cannot check SCIPsolGetHeur()==heur, as subnlp may not be registered as author of the solution)
2453  */
2454  if( heurdata->lastsol == solcand )
2455  return SCIP_OKAY;
2456 
2457  SCIPdebugMsg(scip, "consider solution candidate with violation %g and objective %g from %s\n",
2458  violation, SCIPgetSolTransObj(scip, solcand), SCIPsolGetHeur(solcand) ? SCIPheurGetName(SCIPsolGetHeur(solcand)) : "tree");
2459 
2460  /* 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 */
2461  if( heurdata->startcand == NULL || violation < heurdata->startcandviol ||
2462  SCIPisRelGT(scip, SCIPgetSolTransObj(scip, heurdata->startcand), SCIPgetSolTransObj(scip, solcand)) )
2463  {
2464  if( heurdata->startcand != NULL )
2465  {
2466  SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
2467  }
2468  SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->startcand, solcand) );
2469  SCIP_CALL( SCIPunlinkSol(scip, heurdata->startcand) );
2470  heurdata->startcandviol = violation;
2471 
2472  /* remember which heuristic proposed the candidate */
2473  SCIPsolSetHeur(heurdata->startcand, SCIPgetSolHeur(scip, solcand));
2474  }
2475 
2476  return SCIP_OKAY;
2477 }
2478 
2479 /** gets sub-SCIP used by NLP heuristic, or NULL if none */
2481  SCIP* scip, /**< original SCIP data structure */
2482  SCIP_HEUR* heur /**< heuristic data structure */
2483  )
2484 {
2485  SCIP_HEURDATA* heurdata;
2486 
2487  assert(heur != NULL);
2488  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2489 
2490  heurdata = SCIPheurGetData(heur);
2491  assert(heurdata != NULL);
2492 
2493  return heurdata->subscip;
2494 }
2495 
2496 /** gets mapping of SCIP variables to sub-SCIP variables */
2498  SCIP* scip, /**< original SCIP data structure */
2499  SCIP_HEUR* heur /**< heuristic data structure */
2500  )
2501 {
2502  SCIP_HEURDATA* heurdata;
2503 
2504  assert(heur != NULL);
2505  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2506 
2507  heurdata = SCIPheurGetData(heur);
2508  assert(heurdata != NULL);
2509 
2510  return heurdata->var_scip2subscip;
2511 }
2512 
2513 /** gets mapping of sub-SCIP variables to SCIP variables */
2515  SCIP* scip, /**< original SCIP data structure */
2516  SCIP_HEUR* heur /**< heuristic data structure */
2517  )
2518 {
2519  SCIP_HEURDATA* heurdata;
2520 
2521  assert(heur != NULL);
2522  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2523 
2524  heurdata = SCIPheurGetData(heur);
2525  assert(heurdata != NULL);
2526 
2527  return heurdata->var_subscip2scip;
2528 }
2529 
2530 /** gets startpoint candidate to be used in next call to NLP heuristic, or NULL if none */
2532  SCIP* scip, /**< original SCIP data structure */
2533  SCIP_HEUR* heur /**< heuristic data structure */
2534  )
2535 {
2536  SCIP_HEURDATA* heurdata;
2537 
2538  assert(heur != NULL);
2539  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
2540 
2541  heurdata = SCIPheurGetData(heur);
2542  assert(heurdata != NULL);
2543 
2544  return heurdata->startcand;
2545 }
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:8209
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:71
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3172
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22282
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
static SCIP_RETCODE createSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:118
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8083
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:31233
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
Definition: scip.c:31300
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
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:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
Definition: scip.c:43402
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9230
SCIP_VAR ** SCIPgetVarMappingScip2SubScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2497
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4489
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPincludeHeurSubNlp(SCIP *scip)
Definition: heur_subnlp.c:2298
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:9936
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47088
SCIP_Real SCIPnlpStatisticsGetTotalTime(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:826
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
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:9151
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:8611
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:31616
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 copytables, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:1568
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3162
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
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:11686
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39832
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
void SCIPsetSubscipDepth(SCIP *scip, int newdepth)
Definition: scip.c:3563
SCIP_Bool SCIPhasNLPContinuousNonlinearity(SCIP *scip)
Definition: scip.c:31248
int SCIPgetSubscipDepth(SCIP *scip)
Definition: scip.c:3542
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip.c:5718
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#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:31593
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5132
int SCIPheurGetFreqofs(SCIP_HEUR *heur)
Definition: heur.c:1304
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip.c:12225
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:22602
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:8084
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:4376
SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:12177
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1235
SCIP_RETCODE SCIPsetNLPIntPar(SCIP *scip, SCIP_NLPPARAM type, int ival)
Definition: scip.c:31795
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_RETCODE SCIPsetNLPStringPar(SCIP *scip, SCIP_NLPPARAM type, const char *sval)
Definition: scip.c:31907
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
void SCIPnlpStatisticsFree(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:801
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:748
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:37034
SCIP_Bool SCIPpressedCtrlC(SCIP *scip)
Definition: scip.c:1132
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4804
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:2106
static SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
Definition: heur_subnlp.c:2069
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22369
#define SCIPdebugMsg
Definition: scip.h:455
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:4265
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:3501
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_SOL * SCIPgetStartCandidateHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2531
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:46415
SCIP_Bool SCIPisRelGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47713
static SCIP_DECL_HEUREXEC(heurExecSubNlp)
Definition: heur_subnlp.c:2142
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:10891
#define HEUR_DESC
Definition: heur_subnlp.c:38
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
Constraint handler for knapsack constraints of the form , x binary and .
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip.c:31322
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:38168
SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
Definition: scip.c:31638
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:8193
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2391
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
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:4401
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3143
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3151
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8145
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip.c:31484
#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:32299
static SCIP_RETCODE forbidFixation(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_subnlp.c:1507
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:2341
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22633
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4630
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:928
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip.c:15954
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
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:16662
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2548
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:39041
SCIP_RETCODE SCIPsetNLPInitialGuess(SCIP *scip, SCIP_Real *initialguess)
Definition: scip.c:31534
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9602
#define REALABS(x)
Definition: def.h:173
SCIP_Real SCIPgetLocalDualbound(SCIP *scip)
Definition: scip.c:13389
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1283
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
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:1360
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1324
#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:31851
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38771
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip.c:17252
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:40980
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
Definition: scip.c:31663
static SCIP_DECL_HEURFREE(heurFreeSubNlp)
Definition: heur_subnlp.c:2049
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:29293
SCIP_Real SCIPgetObjlimit(SCIP *scip)
Definition: scip.c:11316
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17663
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9272
#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:1872
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:2669
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2589
#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:40794
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4688
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
#define HEUR_USESSUBSCIP
Definition: heur_subnlp.c:45
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38994
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:1674
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
#define BMSclearMemory(ptr)
Definition: memory.h:111
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12184
SCIP_VAR ** SCIPgetVarMappingSubScip2ScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2514
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:40700
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
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:9251
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
static SCIP_DECL_HEURCOPY(heurCopySubNlp)
Definition: heur_subnlp.c:2035
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPtransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:39101
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:12862
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
NLP local search primal heuristic using sub-SCIPs.
SCIP_RETCODE SCIPnlpStatisticsCreate(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:784
#define HEUR_NAME
Definition: heur_subnlp.c:37
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
SCIP_HEUR * SCIPgetSolHeur(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:39234
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1238
#define SCIP_INVALID
Definition: def.h:169
int SCIPnlpStatisticsGetNIterations(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:816
#define SCIP_Longint
Definition: def.h:134
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38740
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip.c:11049
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:13935
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition: scip.c:31687
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
Definition: heur_subnlp.c:2425
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
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:32191
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
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:5015
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:322
SCIP * SCIPgetSubScipHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
Definition: heur_subnlp.c:2480
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:47173
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
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:4321
SCIP_Bool SCIPisRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47700
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47149
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4746
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:19045
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:4239
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:780
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624