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