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