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