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