Scippy

SCIP

Solving Constraint Integer Programs

heur_undercover.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_undercover.c
17  * @brief Undercover primal heuristic for MINLPs
18  * @author Timo Berthold
19  * @author Ambros Gleixner
20  *
21  * The undercover heuristic is designed for mixed-integer nonlinear programs and tries to fix a subset of variables such
22  * as to make each constraint linear or convex. For this purpose it solves a binary program to automatically determine
23  * the minimum number of variable fixings necessary. As fixing values, we use values from the LP relaxation, the NLP
24  * relaxation, or the incumbent solution.
25  *
26  * @todo use the conflict analysis to analyze the infeasibility which arise after the probing of the cover worked and
27  * solve returned infeasible, instead of adding the Nogood/Conflict by hand; that has the advantage that the SCIP
28  * takes care of creating the conflict and might shrink the initial reason
29  *
30  * @todo do not use LP and NLP fixing values in the same run, e.g., fixingalts = "lni", but start a second dive if LP
31  * values fail
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include <assert.h>
37 #include <string.h>
38 
39 #include "scip/scip.h"
40 #include "scip/scipdefplugins.h"
41 #include "scip/heur_undercover.h"
42 #include "nlpi/exprinterpret.h"
43 
44 #define HEUR_NAME "undercover"
45 #define HEUR_DESC "solves a sub-CIP determined by a set covering approach"
46 #define HEUR_DISPCHAR 'U'
47 #define HEUR_PRIORITY -1110000
48 #define HEUR_FREQ 0
49 #define HEUR_FREQOFS 0
50 #define HEUR_MAXDEPTH -1
51 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
52 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
53 
54 /* default values for user parameters, grouped by parameter type */
55 #define DEFAULT_FIXINGALTS "li" /**< sequence of fixing values used: 'l'p relaxation, 'n'lp relaxation, 'i'ncumbent solution */
56 
57 #define DEFAULT_MAXNODES (SCIP_Longint)500/**< maximum number of nodes to regard in the subproblem */
58 #define DEFAULT_MINNODES (SCIP_Longint)500/**< minimum number of nodes to regard in the subproblem */
59 #define DEFAULT_NODESOFS (SCIP_Longint)500/**< number of nodes added to the contingent of the total nodes */
60 
61 #define DEFAULT_CONFLICTWEIGHT 1000.0 /**< weight for conflict score in fixing order */
62 #define DEFAULT_CUTOFFWEIGHT 1.0 /**< weight for cutoff score in fixing order */
63 #define DEFAULT_INFERENCEWEIGHT 1.0 /**< weight for inference score in fixing order */
64 #define DEFAULT_MAXCOVERSIZEVARS 1.0 /**< maximum coversize (as fraction of total number of variables) */
65 #define DEFAULT_MAXCOVERSIZECONSS SCIP_REAL_MAX /**< maximum coversize (as ratio to the percentage of non-affected constraints) */
66 #define DEFAULT_MINCOVEREDREL 0.15 /**< minimum percentage of nonlinear constraints in the original problem */
67 #define DEFAULT_MINCOVEREDABS 5 /**< minimum number of nonlinear constraints in the original problem */
68 #define DEFAULT_MINIMPROVE 0.0 /**< factor by which heuristic should at least improve the incumbent */
69 #define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
70 #define DEFAULT_RECOVERDIV 0.9 /**< fraction of covering variables in the last cover which need to change their value when recovering */
71 
72 #define DEFAULT_MAXBACKTRACKS 6 /**< maximum number of backtracks */
73 #define DEFAULT_MAXRECOVERS 0 /**< maximum number of recoverings */
74 #define DEFAULT_MAXREORDERS 1 /**< maximum number of reorderings of the fixing order */
75 
76 #define DEFAULT_COVERINGOBJ 'u' /**< objective function of the covering problem */
77 #define DEFAULT_FIXINGORDER 'v' /**< order in which variables should be fixed */
78 
79 #define DEFAULT_BEFORECUTS TRUE /**< should undercover called at root node before cut separation? */
80 #define DEFAULT_FIXINTFIRST FALSE /**< should integer variables in the cover be fixed first? */
81 #define DEFAULT_LOCKSROUNDING TRUE /**< shall LP values for integer vars be rounded according to locks? */
82 #define DEFAULT_ONLYCONVEXIFY FALSE /**< should we only fix/dom.red. variables creating nonconvexity? */
83 #define DEFAULT_POSTNLP TRUE /**< should the NLP heuristic be called to polish a feasible solution? */
84 #define DEFAULT_COVERBD FALSE /**< should bounddisjunction constraints be covered (or just copied)? */
85 #define DEFAULT_REUSECOVER FALSE /**< shall the cover be re-used if a conflict was added after an infeasible subproblem? */
86 #define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the original scip be copied
87  * to constraints of the subscip
88  */
89 
90 /* local defines */
91 #define COVERINGOBJS "cdlmtu" /**< list of objective functions of the covering problem */
92 #define FIXINGORDERS "CcVv" /**< list of orders in which variables can be fixed */
93 #define MAXNLPFAILS 1 /**< maximum number of fails after which we give up solving the NLP relaxation */
94 #define MAXPOSTNLPFAILS 1 /**< maximum number of fails after which we give up calling NLP local search */
95 #define MINTIMELEFT 1.0 /**< don't start expensive parts of the heuristics if less than this amount of time left */
96 #define SUBMIPSETUPCOSTS 200 /**< number of nodes equivalent for the costs for setting up the sub-CIP */
97 
98 
99 /*
100  * Data structures
101  */
102 
103 /** primal heuristic data */
104 struct SCIP_HeurData
105 {
106  SCIP_CONSHDLR** nlconshdlrs; /**< array of nonlinear constraint handlers */
107  SCIP_HEUR* nlpheur; /**< pointer to NLP local search heuristics */
108  char* fixingalts; /**< sequence of fixing values used: 'l'p relaxation, 'n'lp relaxation, 'i'ncumbent solution */
109  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
110  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
111  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
112  SCIP_Longint nusednodes; /**< nodes already used by heuristic in earlier calls */
113  SCIP_Real conflictweight; /**< weight for conflict score in fixing order */
114  SCIP_Real cutoffweight; /**< weight for cutoff score in fixing order */
115  SCIP_Real inferenceweight; /**< weight for inference score in foxing order */
116  SCIP_Real maxcoversizevars; /**< maximum coversize (as fraction of total number of variables) */
117  SCIP_Real maxcoversizeconss; /**< maximum coversize maximum coversize (as ratio to the percentage of non-affected constraints) */
118  SCIP_Real mincoveredrel; /**< minimum percentage of nonlinear constraints in the original problem */
119  SCIP_Real minimprove; /**< factor by which heuristic should at least improve the incumbent */
120  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
121  SCIP_Real recoverdiv; /**< fraction of covering variables in the last cover which need to change their value when recovering */
122  int mincoveredabs; /**< minimum number of nonlinear constraints in the original problem */
123  int maxbacktracks; /**< maximum number of backtracks */
124  int maxrecovers; /**< maximum number of recoverings */
125  int maxreorders; /**< maximum number of reorderings of the fixing order */
126  int nfixingalts; /**< number of fixing alternatives */
127  int nnlpfails; /**< number of fails when solving the NLP relaxation after last success */
128  int npostnlpfails; /**< number of fails of the NLP local search after last success */
129  int nnlconshdlrs; /**< number of nonlinear constraint handlers */
130  char coveringobj; /**< objective function of the covering problem */
131  char fixingorder; /**< order in which variables should be fixed */
132  SCIP_Bool beforecuts; /**< should undercover be called at root node before cut separation? */
133  SCIP_Bool fixintfirst; /**< should integer variables in the cover be fixed first? */
134  SCIP_Bool globalbounds; /**< should global bounds on variables be used instead of local bounds at focus node? */
135  SCIP_Bool locksrounding; /**< shall LP values for integer vars be rounded according to locks? */
136  SCIP_Bool nlpsolved; /**< has current NLP relaxation already been solved successfully? */
137  SCIP_Bool nlpfailed; /**< has solving the NLP relaxation failed? */
138  SCIP_Bool onlyconvexify; /**< should we only fix/dom.red. variables creating nonconvexity? */
139  SCIP_Bool postnlp; /**< should the NLP heuristic be called to polish a feasible solution? */
140  SCIP_Bool coverbd; /**< should bounddisjunction constraints be covered (or just copied)? */
141  SCIP_Bool reusecover; /**< shall the cover be re-used if a conflict was added after an infeasible subproblem? */
142  SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
143  * subproblem? */
144 };
145 
146 /** working memory for retrieving dense sparsity of Hessian matrices */
147 struct HessianData
148 {
149  SCIP_SOL* evalsol;
150  SCIP_Real* varvals;
151  SCIP_Bool* sparsity;
152  int nvars;
153 };
154 
155 /*
156  * Local methods
157  */
158 
159 
160 /** determines, whether a variable is fixed to the given value */
161 static
163  SCIP* scip, /**< SCIP data structure */
164  SCIP_VAR* var, /**< variable to check */
165  SCIP_Real val, /**< value to check */
166  SCIP_Bool global /**< should global bounds be used? */
167  )
168 {
169  SCIP_Bool isfixed;
170 
171  if( global )
172  isfixed = SCIPisFeasEQ(scip, val, SCIPvarGetLbGlobal(var)) && SCIPisFeasEQ(scip, val, SCIPvarGetUbGlobal(var));
173  else
174  isfixed = SCIPisFeasEQ(scip, val, SCIPvarGetLbLocal(var)) && SCIPisFeasEQ(scip, val, SCIPvarGetUbLocal(var));
175 
176  return isfixed;
177 }
178 
179 
180 /** determines, whether a term is already constant, because the variable is fixed or the coefficient is zero */
181 static
183  SCIP* scip, /**< SCIP data structure */
184  SCIP_VAR* var, /**< variable to check */
185  SCIP_Real coeff, /**< coefficient to check */
186  SCIP_Bool global /**< should global bounds be used? */
187  )
188 {
189  /* if the variable has zero coefficient in the original problem, the term is linear */
190  if( SCIPisZero(scip, coeff) )
191  return TRUE;
192 
193  /* if the variable is fixed in the original problem, the term is linear */
194  if( global )
195  return SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
196  else
197  return SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
198 
199 }
200 
201 
202 /** determines, whether a term is convex */
203 static
205  SCIP* scip, /**< SCIP data structure */
206  SCIP_Real lhs, /**< left hand side of the constraint */
207  SCIP_Real rhs, /**< right hand side of the constraint */
208  SCIP_Bool sign /**< signature of the term */
209  )
210 {
211  return sign ? SCIPisInfinity(scip, -lhs) : SCIPisInfinity(scip, rhs);
212 }
213 
214 
215 /** increases counters */
216 static
217 void incCounters(
218  int* termcounter, /**< array to count in how many nonlinear terms a variable appears */
219  int* conscounter, /**< array to count in how many constraints a variable appears */
220  SCIP_Bool* consmarker, /**< was this variable already counted for this constraint? */
221  int idx /**< problem index of the variable */
222  )
223 {
224  termcounter[idx]++;
225  if( !consmarker[idx] )
226  {
227  conscounter[idx]++;
228  consmarker[idx] = TRUE;
229  }
230  return;
231 }
232 
233 
234 /** update time limit */
235 static
237  SCIP* scip, /**< SCIP data structure */
238  SCIP_CLOCK* clck, /**< clock timer */
239  SCIP_Real* timelimit /**< time limit */
240  )
241 {
242  *timelimit -= SCIPgetClockTime(scip, clck);
243  SCIP_CALL( SCIPresetClock(scip, clck) );
244  SCIP_CALL( SCIPstartClock(scip, clck) );
245 
246  return SCIP_OKAY;
247 }
248 
249 
250 /** analyzes a nonlinear row and adds constraints and fixings to the covering problem */
251 static
253  SCIP* scip, /**< original SCIP data structure */
254  SCIP_NLROW* nlrow, /**< nonlinear row representation of a nonlinear constraint */
255  SCIP_EXPRINT* exprint, /**< expression interpreter for computing sparsity pattern of the Hessian;
256  * if NULL, we will simply fix all variables in the expression tree */
257  struct HessianData* hessiandata, /**< working memory for retrieving dense sparsity of Hessian matrices */
258  SCIP* coveringscip, /**< SCIP data structure for the covering problem */
259  int nvars, /**< number of variables */
260  SCIP_VAR** coveringvars, /**< array to store the covering problem's variables */
261  int* termcounter, /**< counter array for number of nonlinear nonzeros per variable */
262  int* conscounter, /**< counter array for number of nonlinear constraints per variable */
263  SCIP_Bool* consmarker, /**< marker array if constraint has been counted in conscounter */
264  SCIP_Bool globalbounds, /**< should global bounds on variables be used instead of local bounds at focus node? */
265  SCIP_Bool onlyconvexify, /**< should we only fix/dom.red. variables creating nonconvexity? */
266  SCIP_Bool* success /**< pointer to store whether row was processed successfully */
267  )
268 {
269  SCIP_EXPRTREE* exprtree;
270  SCIP_Bool infeas;
271  SCIP_Bool fixed;
272  int t;
273  char name[SCIP_MAXSTRLEN];
274 
275  assert(scip != NULL);
276  assert(nlrow != NULL);
277  assert(exprint == NULL || hessiandata != NULL);
278  assert(coveringscip != NULL);
279  assert(nvars >= 1);
280  assert(coveringvars != NULL);
281  assert(termcounter != NULL);
282  assert(conscounter != NULL);
283  assert(consmarker != NULL);
284  assert(success != NULL);
285 
286  *success = FALSE;
287  BMSclearMemoryArray(consmarker, nvars);
288 
289  /* go through expression tree */
290  exprtree = SCIPnlrowGetExprtree(nlrow);
291  if( exprtree != NULL )
292  {
293  SCIP_VAR** exprtreevars;
294  int nexprtreevars;
295  int probidx1;
296  int probidx2;
297 
298  /* get variables in expression tree */
299  nexprtreevars = SCIPexprtreeGetNVars(exprtree);
300  exprtreevars = SCIPexprtreeGetVars(exprtree);
301 
302  if( exprtreevars != NULL && nexprtreevars > 0 )
303  {
304  SCIP_Bool usehessian;
305  int i;
306 
307  /* is an expression interpreter available which can return the sparsity pattern of the Hessian? */
308  usehessian = exprint != NULL && (SCIPexprintGetCapability() & SCIP_EXPRINTCAPABILITY_HESSIAN);
309  if( usehessian )
310  {
311  int idx1;
312  int idx2;
313 
314  assert(hessiandata != NULL);
315  assert(hessiandata->nvars == 0 || hessiandata->varvals != NULL);
316  assert(hessiandata->nvars == 0 || hessiandata->sparsity != NULL);
317 
318  /* compile expression tree */
319  SCIP_CALL( SCIPexprintCompile(exprint, exprtree) );
320 
321  /* ensure memory */
322  if( hessiandata->nvars < nexprtreevars )
323  {
324  SCIP_CALL( SCIPreallocBufferArray(scip, &hessiandata->varvals, nexprtreevars) );
325  SCIP_CALL( SCIPreallocBufferArray(scip, &hessiandata->sparsity, nexprtreevars*nexprtreevars) );
326  hessiandata->nvars = nexprtreevars;
327  }
328 
329  /* get point at which to evaluate the Hessian sparsity */
330  if( hessiandata->evalsol == NULL )
331  {
332  SCIP_CALL( SCIPcreateSol(scip, &hessiandata->evalsol, NULL) );
333  SCIP_CALL( SCIPlinkCurrentSol(scip, hessiandata->evalsol) );
334  }
335  SCIP_CALL( SCIPgetSolVals(scip, hessiandata->evalsol, nexprtreevars, exprtreevars, hessiandata->varvals) );
336 
337  /* get sparsity of the Hessian at current LP solution */
338  SCIP_CALL( SCIPexprintHessianSparsityDense(exprint, exprtree, hessiandata->varvals, hessiandata->sparsity) );
339 
340  for( idx1 = nexprtreevars-1; idx1 >= 0; idx1-- )
341  {
342  /* if constraints with inactive variables are present, we will have difficulties creating the sub-CIP later */
343  probidx1 = SCIPvarGetProbindex(exprtreevars[idx1]);
344  if( probidx1 == -1 )
345  {
346  SCIPdebugMessage("strange: inactive variables detected in nonlinear row <%s>\n", SCIPnlrowGetName(nlrow));
347  return SCIP_OKAY;
348  }
349 
350  /* nonzero diagonal element of the Hessian: fix */
351  if( hessiandata->sparsity[idx1*nexprtreevars + idx1]
352  && !termIsConstant(scip, exprtreevars[idx1], 1.0, globalbounds) )
353  {
354  SCIP_CALL( SCIPfixVar(coveringscip, coveringvars[probidx1], 1.0, &infeas, &fixed) );
355  assert(!infeas);
356  assert(fixed);
357 
358  /* update counters */
359  incCounters(termcounter, conscounter, consmarker, probidx1);
360 
361  SCIPdebugMessage("fixing var <%s> in covering problem to 1\n", SCIPvarGetName(coveringvars[probidx1]));
362 
363  /* if covering variable is fixed, then no need to still check non-diagonal elements */
364  continue;
365  }
366 
367  /* two different variables relate nonlinearly */
368  for( idx2 = nexprtreevars-1; idx2 > idx1; idx2-- )
369  {
370  SCIP_CONS* coveringcons;
371  SCIP_VAR* coveringconsvars[2];
372 
373  /* do not assume symmetry */
374  if( !hessiandata->sparsity[idx1*nexprtreevars + idx2] && !hessiandata->sparsity[idx2*nexprtreevars + idx1] )
375  continue;
376 
377  /* if diagonal has entry already, then covering constraint would always be satisfied, thus no need to add */
378  if( hessiandata->sparsity[idx2*nexprtreevars + idx2] && !termIsConstant(scip, exprtreevars[idx2], 1.0, globalbounds) )
379  continue;
380 
381  /* if constraints with inactive variables are present, we will have difficulties creating the sub-CIP later */
382  probidx2 = SCIPvarGetProbindex(exprtreevars[idx2]);
383  if( probidx2 == -1 )
384  {
385  SCIPdebugMessage("strange: inactive variables detected in nonlinear row <%s>\n", SCIPnlrowGetName(nlrow));
386  return SCIP_OKAY;
387  }
388 
389  /* if the term is linear because one of the variables is fixed, nothing to do */
390  if( termIsConstant(scip, exprtreevars[idx1], 1.0, globalbounds)
391  || termIsConstant(scip, exprtreevars[idx2], 1.0, globalbounds) )
392  continue;
393 
394  /* create covering constraint */
395  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering_%d_%d", SCIPnlrowGetName(nlrow), idx1, idx2);
396  coveringconsvars[0] = coveringvars[probidx1];
397  coveringconsvars[1] = coveringvars[probidx2];
398  SCIP_CALL( SCIPcreateConsSetcover(coveringscip, &coveringcons, name, 2, coveringconsvars,
399  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
400 
401  if( coveringcons == NULL )
402  {
403  SCIPdebugMessage("failed to create set covering constraint <%s>\n", name);
404  return SCIP_OKAY;
405  }
406 
407  /* add and release covering constraint */
408  SCIP_CALL( SCIPaddCons(coveringscip, coveringcons) );
409  SCIP_CALL( SCIPreleaseCons(coveringscip, &coveringcons) );
410 
411  SCIPdebugMessage("added covering constraint for vars <%s> and <%s> in covering problem\n", SCIPvarGetName(coveringvars[probidx1]), SCIPvarGetName(coveringvars[probidx2]));
412 
413  /* update counters for both variables */
414  incCounters(termcounter, conscounter, consmarker, probidx1);
415  incCounters(termcounter, conscounter, consmarker, probidx2);
416  }
417  }
418  }
419  /* fix all variables contained in the expression tree */
420  else
421  {
422  for( i = nexprtreevars-1; i >= 0; i-- )
423  {
424  assert(exprtreevars[i] != NULL);
425 
426  /* if constraints with inactive variables are present, we will have difficulties creating the sub-CIP later */
427  probidx1 = SCIPvarGetProbindex(exprtreevars[i]);
428  if( probidx1 == -1 )
429  {
430  SCIPdebugMessage("strange: inactive variable <%s> detected in nonlinear row <%s>\n",
431  SCIPvarGetName(exprtreevars[i]), SCIPnlrowGetName(nlrow));
432  return SCIP_OKAY;
433  }
434 
435  /* term is constant, nothing to do */
436  if( termIsConstant(scip, exprtreevars[i], 1.0, globalbounds) )
437  continue;
438 
439  /* otherwise fix variable */
440  SCIP_CALL( SCIPfixVar(coveringscip, coveringvars[probidx1], 1.0, &infeas, &fixed) );
441  assert(!infeas);
442  assert(fixed);
443 
444  /* update counters */
445  incCounters(termcounter, conscounter, consmarker, probidx1);
446 
447  SCIPdebugMessage("fixing var <%s> in covering problem to 1\n", SCIPvarGetName(coveringvars[probidx1]));
448  }
449  }
450  }
451  }
452 
453  /* go through all quadratic terms */
454  for( t = SCIPnlrowGetNQuadElems(nlrow)-1; t >= 0; t-- )
455  {
456  SCIP_QUADELEM* quadelem;
457  SCIP_VAR* bilinvar1;
458  SCIP_VAR* bilinvar2;
459  int probidx1;
460  int probidx2;
461 
462  /* get quadratic term */
463  quadelem = &SCIPnlrowGetQuadElems(nlrow)[t];
464 
465  /* get involved variables */
466  bilinvar1 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx1];
467  bilinvar2 = SCIPnlrowGetQuadVars(nlrow)[quadelem->idx2];
468  assert(bilinvar1 != NULL);
469  assert(bilinvar2 != NULL);
470 
471  /* if constraints with inactive variables are present, we will have difficulties creating the sub-CIP later */
472  probidx1 = SCIPvarGetProbindex(bilinvar1);
473  probidx2 = SCIPvarGetProbindex(bilinvar2);
474  if( probidx1 == -1 || probidx2 == -1 )
475  {
476  SCIPdebugMessage("inactive variables detected in nonlinear row <%s>\n", SCIPnlrowGetName(nlrow));
477  return SCIP_OKAY;
478  }
479 
480  /* we have a square term */
481  if( bilinvar1 == bilinvar2 )
482  {
483  /* term is constant, nothing to do */
484  if( termIsConstant(scip, bilinvar1, quadelem->coef, globalbounds) )
485  continue;
486 
487  /* if we only convexify and term is convex considering the bounds of the nlrow, nothing to do */
488  if( onlyconvexify && termIsConvex(scip, SCIPnlrowGetLhs(nlrow), SCIPnlrowGetRhs(nlrow), quadelem->coef >= 0) )
489  continue;
490 
491  /* otherwise variable has to be in the cover */
492  SCIP_CALL( SCIPfixVar(coveringscip, coveringvars[probidx1], 1.0, &infeas, &fixed) );
493  assert(!infeas);
494  assert(fixed);
495 
496  /* update counters */
497  incCounters(termcounter, conscounter, consmarker, probidx1);
498 
499  SCIPdebugMessage("fixing var <%s> in covering problem to 1\n", SCIPvarGetName(coveringvars[probidx1]));
500  }
501  /* we have a bilinear term */
502  else
503  {
504  SCIP_CONS* coveringcons;
505  SCIP_VAR* coveringconsvars[2];
506 
507  /* if the term is linear because one of the variables is fixed or the coefficient is zero, nothing to do */
508  if( termIsConstant(scip, bilinvar1, quadelem->coef, globalbounds)
509  || termIsConstant(scip, bilinvar2, quadelem->coef, globalbounds) )
510  continue;
511 
512  /* create covering constraint */
513  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering%d", SCIPnlrowGetName(nlrow), t);
514  coveringconsvars[0] = coveringvars[probidx1];
515  coveringconsvars[1] = coveringvars[probidx2];
516  SCIP_CALL( SCIPcreateConsSetcover(coveringscip, &coveringcons, name, 2, coveringconsvars,
517  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
518 
519  if( coveringcons == NULL )
520  {
521  SCIPdebugMessage("failed to create set covering constraint <%s>\n", name);
522  return SCIP_OKAY;
523  }
524 
525  /* add and release covering constraint */
526  SCIP_CALL( SCIPaddCons(coveringscip, coveringcons) );
527  SCIP_CALL( SCIPreleaseCons(coveringscip, &coveringcons) );
528 
529  /* update counters for both variables */
530  incCounters(termcounter, conscounter, consmarker, probidx1);
531  incCounters(termcounter, conscounter, consmarker, probidx2);
532  }
533  }
534 
535  *success = TRUE;
536 
537  return SCIP_OKAY;
538 }
539 
540 
541 /** creates the covering problem to determine a number of variables to be fixed */
542 static
544  SCIP* scip, /**< original SCIP data structure */
545  SCIP* coveringscip, /**< SCIP data structure for the covering problem */
546  SCIP_VAR** coveringvars, /**< array to store the covering problem's variables */
547  SCIP_Bool globalbounds, /**< should global bounds on variables be used instead of local bounds at focus node? */
548  SCIP_Bool onlyconvexify, /**< should we only fix/dom.red. variables creating nonconvexity? */
549  SCIP_Bool coverbd, /**< should bounddisjunction constraints be covered (or just copied)? */
550  char coveringobj, /**< objective function of the covering problem */
551  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
552  )
553 {
554  SCIP_VAR** vars;
555  SCIP_CONSHDLR* conshdlr;
556  SCIP_HASHMAP* nlrowmap;
557  SCIP_EXPRINT* exprint;
558  SCIP_Bool* consmarker;
559  int* conscounter;
560  int* termcounter;
561 
562  struct HessianData hessiandata;
563  int nlocksup;
564  int nlocksdown;
565  int nvars;
566  int i;
567  int probindex;
568  char name[SCIP_MAXSTRLEN];
569 
570  assert(scip != NULL);
571  assert(coveringscip != NULL);
572  assert(coveringvars != NULL);
573  assert(success != NULL);
574 
575  *success = FALSE;
576 
577  /* get required data of the original problem */
578  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
579 
580  /* create problem data structure */
581  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering", SCIPgetProbName(scip));
582  SCIP_CALL( SCIPcreateProb(coveringscip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
583 
584  /* allocate and initialize to zero counter arrays for weighted objectives */
585  SCIP_CALL( SCIPallocBufferArray(scip, &consmarker, nvars) );
586  SCIP_CALL( SCIPallocBufferArray(scip, &conscounter, nvars) );
587  SCIP_CALL( SCIPallocBufferArray(scip, &termcounter, nvars) );
588  BMSclearMemoryArray(conscounter, nvars);
589  BMSclearMemoryArray(termcounter, nvars);
590 
591  /* create expression interpreter */
592  SCIP_CALL( SCIPexprintCreate(SCIPblkmem(scip), &exprint) );
593  assert(exprint != NULL);
594 
595  /* initialize empty hessiandata; memory will be allocated in method processNlRow() as required */
596  hessiandata.evalsol = NULL;
597  hessiandata.varvals = NULL;
598  hessiandata.sparsity = NULL;
599  hessiandata.nvars = 0;
600 
601  /* create covering variable for each variable in the original problem (fix it or not?) in the same order as in the
602  * original problem
603  */
604  for( i = 0; i < nvars; i++ )
605  {
606  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering", SCIPvarGetName(vars[i]));
607  SCIP_CALL( SCIPcreateVar(coveringscip, &coveringvars[i], name, 0.0, 1.0, 1.0, SCIP_VARTYPE_BINARY,
608  TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
609  assert(coveringvars[i] != NULL);
610  SCIP_CALL( SCIPaddVar(coveringscip, coveringvars[i]) );
611  }
612 
613  /* first, go through some special constraint handlers which we do not want to treat by looking at their nlrow
614  * representation; we store these in a hash map and afterwards process all nlrows which are not found in the hash map
615  */
616  nlrowmap = NULL;
617  if( SCIPisNLPConstructed(scip) )
618  {
619  int nnlprows;
620 
621  nnlprows = SCIPgetNNLPNlRows(scip);
622  if( nnlprows > 0 )
623  {
624  int mapsize;
625 
626  /* calculate size of hash map */
627  conshdlr = SCIPfindConshdlr(scip, "quadratic");
628  mapsize = (conshdlr == NULL) ? 0 : SCIPconshdlrGetNActiveConss(conshdlr);
629  conshdlr = SCIPfindConshdlr(scip, "soc");
630  if( conshdlr != NULL )
631  mapsize += SCIPconshdlrGetNActiveConss(conshdlr);
632  mapsize = MAX(mapsize, nnlprows);
633  mapsize = SCIPcalcHashtableSize(2*mapsize);
634  assert(mapsize > 0);
635 
636  /* create hash map */
637  SCIP_CALL( SCIPhashmapCreate(&nlrowmap, SCIPblkmem(scip), mapsize) );
638  assert(nlrowmap != NULL);
639  }
640  }
641 
642  /* go through all AND constraints in the original problem */
643  conshdlr = SCIPfindConshdlr(scip, "and");
644  if( conshdlr != NULL )
645  {
646  int c;
647 
648  for( c = SCIPconshdlrGetNActiveConss(conshdlr)-1; c >= 0; c-- )
649  {
650  SCIP_CONS* andcons;
651  SCIP_CONS* coveringcons;
652  SCIP_VAR** andvars;
653  SCIP_VAR* andres;
654  SCIP_VAR** coveringconsvars;
655  SCIP_Real* coveringconsvals;
656  SCIP_Bool negated;
657 
658  int ntofix;
659  int v;
660 
661  /* get constraint and variables */
662  andcons = SCIPconshdlrGetConss(conshdlr)[c];
663  assert(andcons != NULL);
664  andvars = SCIPgetVarsAnd(scip, andcons);
665  assert(andvars != NULL);
666 
667  /* "and" constraints are not passed to the NLP, hence nothing to store in the hash map */
668 
669  /* allocate memory for covering constraint */
670  SCIP_CALL( SCIPallocBufferArray(coveringscip, &coveringconsvars, SCIPgetNVarsAnd(scip, andcons)+1) );
671  SCIP_CALL( SCIPallocBufferArray(coveringscip, &coveringconsvals, SCIPgetNVarsAnd(scip, andcons)+1) );
672 
673  /* collect unfixed variables */
674  BMSclearMemoryArray(consmarker, nvars);
675  ntofix = 0;
676  for( v = SCIPgetNVarsAnd(scip, andcons)-1; v >= 0; v-- )
677  {
678  assert(andvars[v] != NULL);
679  negated = FALSE;
680 
681  /* if variable is fixed to 0, entire constraint can be linearized */
682  if( varIsFixed(scip, andvars[v], 0.0, globalbounds) )
683  {
684  ntofix = 0;
685  break;
686  }
687 
688  /* if variable is fixed, nothing to do */
689  if( termIsConstant(scip, andvars[v], 1.0, globalbounds) )
690  {
691  continue;
692  }
693 
694  /* if constraints with inactive variables are present, we have to find the corresponding active variable */
695  probindex = SCIPvarGetProbindex(andvars[v]);
696  if( probindex == -1 )
697  {
698  SCIP_VAR* repvar;
699 
700  /* get binary representative of variable */
701  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[v], &repvar, &negated) );
702  assert(repvar != NULL);
703  assert(SCIPvarGetStatus(repvar) != SCIP_VARSTATUS_FIXED);
704 
706  {
707  SCIPdebugMessage("strange: multiaggregated variable found <%s>\n", SCIPvarGetName(andvars[v]));
708  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(andcons));
709  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
710  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
711  goto TERMINATE;
712  }
713 
714  /* check for negation */
715  if( SCIPvarIsNegated(repvar) )
716  {
717  probindex = SCIPvarGetProbindex(SCIPvarGetNegationVar(repvar));
718  negated = TRUE;
719  }
720  else
721  {
722  assert(SCIPvarIsActive(repvar));
723  probindex = SCIPvarGetProbindex(repvar);
724  negated = FALSE;
725  }
726  }
727  assert(probindex >= 0);
728 
729  /* add covering variable for unfixed original variable */
730  if( negated )
731  {
732  SCIP_CALL( SCIPgetNegatedVar(coveringscip, coveringvars[probindex], &coveringconsvars[ntofix]) );
733  }
734  else
735  coveringconsvars[ntofix] = coveringvars[probindex];
736  coveringconsvals[ntofix] = 1.0;
737  ntofix++;
738  }
739  negated = FALSE;
740 
741  /* if constraints with inactive variables are present, we have to find the corresponding active variable */
742  andres = SCIPgetResultantAnd(scip, andcons);
743  assert(andres != NULL);
744  probindex = SCIPvarGetProbindex(andres);
745 
746  /* if resultant is fixed this constraint can be either linearized or is redundant because all operands can be fixed */
747  if( termIsConstant(scip, andres, 1.0, globalbounds) )
748  {
749  /* free memory for covering constraint */
750  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
751  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
752 
753  continue;
754  }
755 
756  if( probindex == -1 )
757  {
758  SCIP_VAR* repvar;
759 
760  /* get binary representative of variable */
761  SCIP_CALL( SCIPgetBinvarRepresentative(scip, SCIPgetResultantAnd(scip, andcons), &repvar, &negated) );
762  assert(repvar != NULL);
763  assert(SCIPvarGetStatus(repvar) != SCIP_VARSTATUS_FIXED);
764 
766  {
767  SCIPdebugMessage("strange: multiaggregated variable found <%s>\n", SCIPvarGetName(SCIPgetResultantAnd(scip, andcons)));
768  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(andcons));
769  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
770  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
771  goto TERMINATE;
772  }
773 
774  /* check for negation */
775  if( SCIPvarIsNegated(repvar) )
776  {
777  probindex = SCIPvarGetProbindex(SCIPvarGetNegationVar(repvar));
778  negated = TRUE;
779  }
780  else
781  {
782  assert(SCIPvarIsActive(repvar));
783  probindex = SCIPvarGetProbindex(repvar);
784  negated = FALSE;
785  }
786  }
787  else if( SCIPvarGetLbGlobal(andres) > 0.5 || SCIPvarGetUbGlobal(andres) < 0.5 )
788  {
789  /* free memory for covering constraint */
790  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
791  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
792 
793  continue;
794  }
795  assert(probindex >= 0);
796  assert(!termIsConstant(scip, (negated ? SCIPvarGetNegatedVar(vars[probindex]) : vars[probindex]), 1.0, globalbounds));
797 
798  /* if less than two variables are unfixed or the resultant variable is fixed, the entire constraint can be
799  * linearized anyway
800  */
801  if( ntofix >= 2 )
802  {
803  assert(ntofix <= SCIPgetNVarsAnd(scip, andcons));
804 
805  /* add covering variable for unfixed resultant */
806  if( negated )
807  {
808  SCIP_CALL( SCIPgetNegatedVar(coveringscip, coveringvars[probindex], &coveringconsvars[ntofix]) );
809  }
810  else
811  coveringconsvars[ntofix] = coveringvars[probindex];
812  coveringconsvals[ntofix] = (SCIP_Real)(ntofix - 1);
813  ntofix++;
814 
815  /* create covering constraint */
816  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering", SCIPconsGetName(andcons));
817  SCIP_CALL( SCIPcreateConsLinear(coveringscip, &coveringcons, name, ntofix, coveringconsvars, coveringconsvals,
818  (SCIP_Real)(ntofix - 2), SCIPinfinity(coveringscip),
819  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
820 
821  if( coveringcons == NULL )
822  {
823  SCIPdebugMessage("failed to create linear constraint <%s>\n", name);
824  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
825  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
826  goto TERMINATE;
827  }
828 
829  /* add and release covering constraint */
830  SCIP_CALL( SCIPaddCons(coveringscip, coveringcons) );
831  SCIP_CALL( SCIPreleaseCons(coveringscip, &coveringcons) );
832 
833  /* update counters */
834  for( v = ntofix-1; v >= 0; v-- )
835  if( SCIPvarIsNegated(coveringconsvars[v]) )
836  incCounters(termcounter, conscounter, consmarker, SCIPvarGetProbindex(SCIPvarGetNegationVar(coveringconsvars[v])));
837  else
838  incCounters(termcounter, conscounter, consmarker, SCIPvarGetProbindex(coveringconsvars[v]));
839  }
840 
841  /* free memory for covering constraint */
842  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
843  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
844  }
845  }
846 
847  /* go through all bounddisjunction constraints in the original problem */
848  conshdlr = SCIPfindConshdlr(scip, "bounddisjunction");
849  if( conshdlr != NULL && coverbd )
850  {
851  int c;
852 
853  for( c = SCIPconshdlrGetNActiveConss(conshdlr)-1; c >= 0; c-- )
854  {
855  SCIP_CONS* bdcons;
856  SCIP_CONS* coveringcons;
857  SCIP_VAR** bdvars;
858  SCIP_VAR** coveringconsvars;
859  SCIP_Real* coveringconsvals;
860 
861  int nbdvars;
862  int ntofix;
863  int v;
864 
865  /* get constraint and variables */
866  bdcons = SCIPconshdlrGetConss(conshdlr)[c];
867  assert(bdcons != NULL);
868  bdvars = SCIPgetVarsBounddisjunction(scip, bdcons);
869  assert(bdvars != NULL);
870  nbdvars = SCIPgetNVarsBounddisjunction(scip, bdcons);
871 
872  /* bounddisjunction constraints are not passed to the NLP, hence nothing to store in the hash map */
873 
874  /* allocate memory for covering constraint */
875  SCIP_CALL( SCIPallocBufferArray(coveringscip, &coveringconsvars, nbdvars) );
876  SCIP_CALL( SCIPallocBufferArray(coveringscip, &coveringconsvals, nbdvars) );
877 
878  /* collect unfixed variables */
879  BMSclearMemoryArray(consmarker, nvars);
880  ntofix = 0;
881  for( v = nbdvars-1; v >= 0; v-- )
882  {
883  SCIP_Bool negated;
884 
885  assert(bdvars[v] != NULL);
886  negated = FALSE;
887 
888  /* if variable is fixed, nothing to do */
889  if( varIsFixed(scip, bdvars[v], globalbounds ? SCIPvarGetLbGlobal(bdvars[v]) : SCIPvarGetLbLocal(bdvars[v]),
890  globalbounds) )
891  {
892  continue;
893  }
894 
895  /* if constraints with inactive variables are present, we have to find the corresponding active variable */
896  probindex = SCIPvarGetProbindex(bdvars[v]);
897  if( probindex == -1 )
898  {
899  SCIP_VAR* repvar;
900 
901  /* get binary representative of variable */
902  SCIP_CALL( SCIPgetBinvarRepresentative(scip, bdvars[v], &repvar, &negated) );
903  assert(repvar != NULL);
904  assert(SCIPvarGetStatus(repvar) != SCIP_VARSTATUS_FIXED);
905 
907  {
908  SCIPdebugMessage("strange: multiaggregated variable found <%s>\n", SCIPvarGetName(bdvars[v]));
909  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(bdcons));
910  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
911  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
912  goto TERMINATE;
913  }
914 
915  /* check for negation */
916  if( SCIPvarIsNegated(repvar) )
917  {
918  probindex = SCIPvarGetProbindex(SCIPvarGetNegationVar(repvar));
919  negated = TRUE;
920  }
921  else
922  {
923  assert(SCIPvarIsActive(repvar));
924  probindex = SCIPvarGetProbindex(repvar);
925  negated = FALSE;
926  }
927  }
928  assert(probindex >= 0);
929 
930  /* add covering variable for unfixed original variable */
931  if( negated )
932  {
933  SCIP_CALL( SCIPgetNegatedVar(coveringscip, coveringvars[probindex], &coveringconsvars[ntofix]) );
934  }
935  else
936  coveringconsvars[ntofix] = coveringvars[probindex];
937  coveringconsvals[ntofix] = 1.0;
938  ntofix++;
939  }
940 
941  /* if less than two variables are unfixed, the entire constraint can be linearized anyway */
942  if( ntofix >= 2 )
943  {
944  assert(ntofix <= nbdvars);
945 
946  /* create covering constraint */
947  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering", SCIPconsGetName(bdcons));
948  SCIP_CALL( SCIPcreateConsLinear(coveringscip, &coveringcons, name, ntofix, coveringconsvars, coveringconsvals,
949  (SCIP_Real)(ntofix - 1), SCIPinfinity(coveringscip),
950  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
951 
952  if( coveringcons == NULL )
953  {
954  SCIPdebugMessage("failed to create linear constraint <%s>\n", name);
955  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
956  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
957  goto TERMINATE;
958  }
959 
960  /* add and release covering constraint */
961  SCIP_CALL( SCIPaddCons(coveringscip, coveringcons) );
962  SCIP_CALL( SCIPreleaseCons(coveringscip, &coveringcons) );
963 
964  /* update counters */
965  for( v = ntofix-1; v >= 0; v-- )
966  if( SCIPvarIsNegated(coveringconsvars[v]) )
967  incCounters(termcounter, conscounter, consmarker, SCIPvarGetProbindex(SCIPvarGetNegationVar(coveringconsvars[v])));
968  else
969  incCounters(termcounter, conscounter, consmarker, SCIPvarGetProbindex(coveringconsvars[v]));
970  }
971 
972  /* free memory for covering constraint */
973  SCIPfreeBufferArray(coveringscip, &coveringconsvals);
974  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
975  }
976  }
977 
978  /* go through all indicator constraints in the original problem; fix the binary variable */
979  conshdlr = SCIPfindConshdlr(scip, "indicator");
980  if( conshdlr != NULL )
981  {
982  int c;
983 
984  for( c = SCIPconshdlrGetNActiveConss(conshdlr)-1; c >= 0; c-- )
985  {
986  SCIP_CONS* indcons;
987  SCIP_VAR* binvar;
988  SCIP_VAR* coveringvar;
989 
990  /* get constraint and variables */
991  indcons = SCIPconshdlrGetConss(conshdlr)[c];
992  assert(indcons != NULL);
993  binvar = SCIPgetBinaryVarIndicator(indcons);
994  assert(binvar != NULL);
995 
996  /* indicator constraints are not passed to the NLP, hence nothing to store in the hash map */
997 
998  /* if variable is fixed, nothing to do */
999  if( varIsFixed(scip, binvar, globalbounds ? SCIPvarGetLbGlobal(binvar) : SCIPvarGetLbLocal(binvar), globalbounds) )
1000  {
1001  continue;
1002  }
1003 
1004  /* if constraints with inactive variables are present, we have to find the corresponding active variable */
1005  probindex = SCIPvarGetProbindex(binvar);
1006  if( probindex == -1 )
1007  {
1008  SCIP_VAR* repvar;
1009  SCIP_Bool negated;
1010 
1011  /* get binary representative of variable */
1012  negated = FALSE;
1013  SCIP_CALL( SCIPgetBinvarRepresentative(scip, binvar, &repvar, &negated) );
1014  assert(repvar != NULL);
1015  assert(SCIPvarGetStatus(repvar) != SCIP_VARSTATUS_FIXED);
1016 
1017  if( SCIPvarGetStatus(repvar) == SCIP_VARSTATUS_MULTAGGR )
1018  {
1019  SCIPdebugMessage("strange: multiaggregated variable found <%s>\n", SCIPvarGetName(binvar));
1020  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(indcons));
1021  goto TERMINATE;
1022  }
1023 
1024  /* check for negation */
1025  if( SCIPvarIsNegated(repvar) )
1026  probindex = SCIPvarGetProbindex(SCIPvarGetNegationVar(repvar));
1027  else
1028  {
1029  assert(SCIPvarIsActive(repvar));
1030  probindex = SCIPvarGetProbindex(repvar);
1031  }
1032  }
1033  assert(probindex >= 0);
1034 
1035  /* get covering variable for unfixed binary variable in indicator constraint */
1036  coveringvar = coveringvars[probindex];
1037 
1038  /* require covering variable to be fixed such that indicator is linearized */
1039  SCIP_CALL( SCIPchgVarLb(coveringscip, coveringvar, 1.0) );
1040 
1041  /* update counters */
1042  BMSclearMemoryArray(consmarker, nvars);
1043  incCounters(termcounter, conscounter, consmarker, probindex);
1044  }
1045  }
1046 
1047  /* go through all quadratic constraints in the original problem */
1048  conshdlr = SCIPfindConshdlr(scip, "quadratic");
1049  if( conshdlr != NULL )
1050  {
1051  int c;
1052 
1053  for( c = SCIPconshdlrGetNActiveConss(conshdlr)-1; c >= 0; c-- )
1054  {
1055  SCIP_CONS* quadcons;
1056  SCIP_NLROW* nlrow;
1057 
1058  /* get constraint */
1059  quadcons = SCIPconshdlrGetConss(conshdlr)[c];
1060  assert(quadcons != NULL);
1061 
1062  /* get nlrow representation and store it in hash map */
1063  SCIP_CALL( SCIPgetNlRowQuadratic(scip, quadcons, &nlrow) );
1064  assert(nlrow != NULL);
1065  if( nlrowmap != NULL )
1066  {
1067  assert(!SCIPhashmapExists(nlrowmap, nlrow));
1068  SCIP_CALL( SCIPhashmapInsert(nlrowmap, nlrow, quadcons) );
1069  }
1070 
1071  /* if we only want to convexify and curvature and bounds prove already convexity, nothing to do */
1072  if( onlyconvexify
1073  && ((SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, quadcons)) && SCIPisConvexQuadratic(scip, quadcons))
1074  || (SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, quadcons)) && SCIPisConcaveQuadratic(scip, quadcons))) )
1075  continue;
1076 
1077  /* process nlrow */
1078  *success = FALSE;
1079  SCIP_CALL( processNlRow(scip, nlrow, exprint, &hessiandata, coveringscip, nvars, coveringvars,
1080  termcounter, conscounter, consmarker, globalbounds, onlyconvexify, success) );
1081 
1082  if( *success == FALSE )
1083  goto TERMINATE;
1084  }
1085 
1086  *success = FALSE;
1087  }
1088 
1089  /* go through all "soc" constraints in the original problem */
1090  conshdlr = SCIPfindConshdlr(scip, "soc");
1091  if( conshdlr != NULL && !onlyconvexify )
1092  {
1093  int c;
1094 
1095  for( c = SCIPconshdlrGetNActiveConss(conshdlr)-1; c >= 0; c-- )
1096  {
1097  SCIP_CONS* soccons;
1098  SCIP_CONS* coveringcons;
1099  SCIP_VAR** soclhsvars;
1100  SCIP_VAR* socrhsvar;
1101  SCIP_VAR** coveringconsvars;
1102  SCIP_NLROW* nlrow;
1103 
1104  int ntofix;
1105  int v;
1106 
1107  /* get constraints and variables */
1108  soccons = SCIPconshdlrGetConss(conshdlr)[c];
1109  assert(soccons != NULL);
1110  socrhsvar = SCIPgetRhsVarSOC(scip, soccons);
1111  assert(socrhsvar != NULL);
1112  soclhsvars = SCIPgetLhsVarsSOC(scip, soccons);
1113  assert(soclhsvars != NULL);
1114 
1115  /* get nlrow representation and store it in hash map */
1116  SCIP_CALL( SCIPgetNlRowSOC(scip, soccons, &nlrow) );
1117  assert(nlrow != NULL);
1118  if( nlrowmap != NULL )
1119  {
1120  assert(!SCIPhashmapExists(nlrowmap, nlrow));
1121  SCIP_CALL( SCIPhashmapInsert(nlrowmap, nlrow, soccons) );
1122  }
1123 
1124  /* allocate memory for covering constraint */
1125  SCIP_CALL( SCIPallocBufferArray(coveringscip, &coveringconsvars, SCIPgetNLhsVarsSOC(scip, soccons)+1) );
1126 
1127  /* collect unfixed variables */
1128  BMSclearMemoryArray(consmarker, nvars);
1129  ntofix = 0;
1130 
1131  /* soc constraints should contain only active and multi-aggregated variables; the latter we do not handle */
1132  probindex = SCIPvarGetProbindex(socrhsvar);
1133  if( probindex == -1 )
1134  {
1135  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(soccons));
1136  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
1137  goto TERMINATE;
1138  }
1139 
1140  /* add covering variable for unfixed rhs variable */
1141  if( !termIsConstant(scip, socrhsvar, SCIPgetRhsCoefSOC(scip, soccons), globalbounds) )
1142  {
1143  SCIP_CALL( SCIPgetNegatedVar(coveringscip, coveringvars[probindex], &coveringconsvars[ntofix]) );
1144  ntofix++;
1145  }
1146 
1147  /* go through lhs variables */
1148  for( v = SCIPgetNLhsVarsSOC(scip, soccons)-1; v >= 0; v-- )
1149  {
1150  assert(soclhsvars[v] != NULL);
1151 
1152  /* soc constraints should contain only active and multi-aggregated variables; the latter we do not handle */
1153  probindex = SCIPvarGetProbindex(soclhsvars[v]);
1154  if( probindex == -1 )
1155  {
1156  SCIPdebugMessage("inactive variables detected in constraint <%s>\n", SCIPconsGetName(soccons));
1157  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
1158  goto TERMINATE;
1159  }
1160 
1161  /* add covering variable for unfixed lhs variable */
1162  if( !termIsConstant(scip, soclhsvars[v], SCIPgetLhsCoefsSOC(scip, soccons)[v], globalbounds) )
1163  {
1164  SCIP_CALL( SCIPgetNegatedVar(coveringscip, coveringvars[probindex], &coveringconsvars[ntofix]) );
1165  ntofix++;
1166  }
1167  }
1168 
1169  if( ntofix >= 2 )
1170  {
1171  /* create covering constraint */
1172  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_covering", SCIPconsGetName(soccons));
1173  SCIP_CALL( SCIPcreateConsSetpack(coveringscip, &coveringcons, name, ntofix, coveringconsvars,
1174  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
1175 
1176  if( coveringcons == NULL )
1177  {
1178  SCIPdebugMessage("failed to create set packing constraint <%s>\n", name);
1179  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
1180  goto TERMINATE;
1181  }
1182 
1183  /* add and release covering constraint */
1184  SCIP_CALL( SCIPaddCons(coveringscip, coveringcons) );
1185  SCIP_CALL( SCIPreleaseCons(coveringscip, &coveringcons) );
1186 
1187  /* update counters */
1188  for( v = ntofix-1; v >= 0; v-- )
1189  incCounters(termcounter, conscounter, consmarker, SCIPvarGetProbindex(SCIPvarGetNegatedVar(coveringconsvars[v])));
1190  }
1191 
1192  /* free memory for covering constraint */
1193  SCIPfreeBufferArray(coveringscip, &coveringconsvars);
1194  }
1195  }
1196 
1197  /* go through all yet unprocessed nlrows */
1198  if( nlrowmap != NULL )
1199  {
1200  SCIP_NLROW** nlrows;
1201  int nnlrows;
1202 
1203  assert(SCIPisNLPConstructed(scip));
1204 
1205  /* get nlrows */
1206  nnlrows = SCIPgetNNLPNlRows(scip);
1207  nlrows = SCIPgetNLPNlRows(scip);
1208 
1209  for( i = nnlrows-1; i >= 0; i-- )
1210  {
1211  assert(nlrows[i] != NULL);
1212 
1213  /* nlrow or corresponding constraint already processed */
1214  if( SCIPhashmapExists(nlrowmap, nlrows[i]) )
1215  continue;
1216 
1217  /* process nlrow */
1218  *success = FALSE;
1219  SCIP_CALL( processNlRow(scip, nlrows[i], exprint, &hessiandata, coveringscip, nvars, coveringvars,
1220  termcounter, conscounter, consmarker, globalbounds, onlyconvexify, success) );
1221 
1222  if( *success == FALSE )
1223  goto TERMINATE;
1224  }
1225  }
1226 
1227  /* set objective function of covering problem */
1228  switch( coveringobj )
1229  {
1230  case 'c': /* number of influenced nonlinear constraints */
1231  for( i = nvars-1; i >= 0; i-- )
1232  {
1233  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i], (SCIP_Real) conscounter[i]) );
1234  }
1235  break;
1236  case 'd': /* domain size */
1237  for( i = nvars-1; i >= 0; i-- )
1238  {
1239  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i],
1240  (globalbounds ? SCIPvarGetUbGlobal(vars[i]) - SCIPvarGetLbGlobal(vars[i]) : SCIPvarGetUbLocal(vars[i]) - SCIPvarGetLbLocal(vars[i]))) );
1241  }
1242  break;
1243  case 'l': /* number of locks */
1244  for( i = nvars-1; i >= 0; i-- )
1245  {
1246  nlocksup = SCIPvarGetNLocksUp(vars[i]);
1247  nlocksdown = SCIPvarGetNLocksDown(vars[i]);
1248  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i], (SCIP_Real) (nlocksup+nlocksdown+1)) );
1249  }
1250  break;
1251  case 'm': /* min(up locks, down locks)+1 */
1252  for( i = nvars-1; i >= 0; i-- )
1253  {
1254  nlocksup = SCIPvarGetNLocksUp(vars[i]);
1255  nlocksdown = SCIPvarGetNLocksDown(vars[i]);
1256  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i], (SCIP_Real) (MIN(nlocksup, nlocksdown)+1)) );
1257  }
1258  break;
1259  case 't': /* number of influenced nonlinear terms */
1260  for( i = nvars-1; i >= 0; i-- )
1261  {
1262  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i], (SCIP_Real) termcounter[i]) );
1263  }
1264  break;
1265  case 'u': /* unit penalties */
1266  for( i = nvars-1; i >= 0; i-- )
1267  {
1268  SCIP_CALL( SCIPchgVarObj(coveringscip, coveringvars[i], 1.0) );
1269  }
1270  break;
1271  default:
1272  SCIPerrorMessage("invalid choice <%c> for covering objective\n", coveringobj);
1273  goto TERMINATE;
1274  }
1275 
1276  /* covering problem successfully set up */
1277  *success = TRUE;
1278 
1279  TERMINATE:
1280  /* free nlrow hash map */
1281  if( nlrowmap != NULL )
1282  {
1283  SCIPhashmapFree(&nlrowmap);
1284  }
1285 
1286  /* free hessian data */
1287  if( hessiandata.nvars > 0 )
1288  {
1289  assert(hessiandata.evalsol != NULL);
1290  assert(hessiandata.varvals != NULL);
1291  assert(hessiandata.sparsity != NULL);
1292 
1293  SCIPfreeBufferArray(scip, &hessiandata.sparsity);
1294  SCIPfreeBufferArray(scip, &hessiandata.varvals);
1295 
1296  SCIP_CALL( SCIPfreeSol(scip, &hessiandata.evalsol) );
1297  }
1298  else
1299  {
1300  assert(hessiandata.evalsol == NULL);
1301  assert(hessiandata.varvals == NULL);
1302  assert(hessiandata.sparsity == NULL);
1303  }
1304 
1305  /* free expression interpreter */
1306  SCIP_CALL( SCIPexprintFree(&exprint) );
1307 
1308  SCIPstatistic(
1309  {
1310  int nnonzs;
1311  nnonzs = 0;
1312  for( i = 0; i < nvars; ++i)
1313  nnonzs += termcounter[i];
1314  SCIPstatisticPrintf("UCstats nnz/var: %9.6f\n", nnonzs/(SCIP_Real)nvars);
1315  nnonzs = 0;
1316  for( i = 0; i < nvars; ++i)
1317  if( conscounter[i] > 0 )
1318  nnonzs++;
1319  SCIPstatisticPrintf("UCstats nlvars: %6d\n", nnonzs);
1320  }
1321  );
1322 
1323  /* free counter arrays for weighted objectives */
1324  SCIPfreeBufferArray(scip, &termcounter);
1325  SCIPfreeBufferArray(scip, &conscounter);
1326  SCIPfreeBufferArray(scip, &consmarker);
1327 
1328  return SCIP_OKAY;
1329 }
1330 
1331 
1332 /** adds a constraint to the covering problem to forbid the given cover */
1333 static
1335  SCIP* scip, /**< SCIP data structure of the covering problem */
1336  int nvars, /**< number of variables */
1337  SCIP_VAR** vars, /**< variable array */
1338  int coversize, /**< size of the cover */
1339  int* cover, /**< problem indices of the variables in the cover */
1340  int diversification, /**< how many unfixed variables have to change their value? */
1341  SCIP_Bool* success, /**< pointer to store whether the cutoff constraint was created successfully */
1342  SCIP_Bool* infeas /**< pointer to store whether the cutoff proves (local or global) infeasibility */
1343  )
1344 {
1345  SCIP_CONS* cons;
1346  SCIP_VAR** consvars;
1347 
1348  char name[SCIP_MAXSTRLEN];
1349  int nconsvars;
1350  int i;
1351 
1352  assert(scip != NULL);
1353  assert(vars != NULL);
1354  assert(nvars >= 1);
1355  assert(cover != NULL);
1356  assert(coversize >= 1);
1357  assert(coversize <= nvars);
1358  assert(diversification >= 1);
1359  assert(success != NULL);
1360  assert(infeas != NULL);
1361 
1362  *success = FALSE;
1363  *infeas = FALSE;
1364 
1365  /* allocate memory for constraint variables */
1366  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, coversize) );
1367  nconsvars = 0;
1368  cons = NULL;
1369 
1370  /* create constraint name */
1371  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "forbid_cover_assignment");
1372 
1373  /* if all variables in the cover are binary and we require only one variable to change its value, then we create a
1374  * set covering constraint
1375  */
1376  if( diversification == 1 )
1377  {
1378  /* build up constraint */
1379  for( i = coversize-1; i >= 0; i-- )
1380  {
1381  if( !SCIPisFeasGE(scip, SCIPvarGetLbLocal(vars[cover[i]]), 1.0) )
1382  {
1383  SCIP_CALL( SCIPgetNegatedVar(scip, vars[cover[i]], &consvars[nconsvars]) );
1384  nconsvars++;
1385  }
1386  }
1387 
1388  /* if all covering variables are fixed to one, the constraint cannot be satisfied */
1389  if( nconsvars == 0 )
1390  {
1391  *infeas = TRUE;
1392  }
1393  else
1394  {
1395  /* create constraint */
1396  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nconsvars, consvars,
1397  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
1398  }
1399  }
1400  /* if all variables in the cover are binary and we require more variables to change their value, then we create a
1401  * linear constraint
1402  */
1403  else
1404  {
1405  SCIP_Real* consvals;
1406  SCIP_Real rhs;
1407 
1408  /* build up constraint */
1409  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, coversize) );
1410  for( i = coversize-1; i >= 0; i-- )
1411  {
1412  if( !SCIPisFeasGE(scip, SCIPvarGetLbLocal(vars[cover[i]]), 1.0) )
1413  {
1414  consvars[nconsvars] = vars[cover[i]];
1415  consvals[nconsvars] = 1.0;
1416  nconsvars++;
1417  }
1418  }
1419  rhs = (SCIP_Real) (nconsvars-diversification);
1420 
1421  /* if too many covering variables are fixed to 1, the constraint cannot be satisfied */
1422  if( rhs < 0 )
1423  {
1424  *infeas = TRUE;
1425  }
1426  else
1427  {
1428  /* create constraint */
1429  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name,
1430  nconsvars, consvars, consvals, -SCIPinfinity(scip), rhs,
1431  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ) );
1432  }
1433 
1434  /* free memory */
1435  SCIPfreeBufferArray(scip, &consvals);
1436  }
1437 
1438  /* free memory */
1439  SCIPfreeBufferArray(scip, &consvars);
1440 
1441  /* if proven infeasible, we do not even add the constraint; otherwise we add and release the constraint if created
1442  * successfully
1443  */
1444  if( !(*infeas) && cons != NULL )
1445  {
1446  SCIP_CALL( SCIPaddCons(scip, cons) );
1447  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1448  *success = TRUE;
1449  }
1450 
1451  return SCIP_OKAY;
1452 }
1453 
1454 
1455 /** adds a set covering or bound disjunction constraint to the original problem */
1456 static
1458  SCIP* scip, /**< SCIP data structure */
1459  int bdlen, /**< length of bound disjunction */
1460  SCIP_VAR** bdvars, /**< array of variables in bound disjunction */
1461  SCIP_BOUNDTYPE* bdtypes, /**< array of bound types in bound disjunction */
1462  SCIP_Real* bdbounds, /**< array of bounds in bound disjunction */
1463  SCIP_Bool local, /**< is constraint valid only locally? */
1464  SCIP_Bool dynamic, /**< is constraint subject to aging? */
1465  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
1466  SCIP_Bool* success /**< pointer to store whether the cutoff constraint was created successfully */
1467  )
1468 {
1469  SCIP_CONS* cons;
1470  SCIP_VAR** consvars;
1471  SCIP_Bool isbinary;
1472  char name[SCIP_MAXSTRLEN];
1473  int i;
1474 
1475  assert(scip != NULL);
1476  assert(bdlen >= 1);
1477  assert(bdvars != NULL);
1478  assert(bdtypes != NULL);
1479  assert(bdbounds != NULL);
1480  assert(success != NULL);
1481 
1482  /* initialize */
1483  *success = FALSE;
1484  cons = NULL;
1485  consvars = NULL;
1486 
1487  /* create constraint name */
1488  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "undercover_cutoff");
1489 
1490  /* check if all variables in the cover are binary */
1491  isbinary = TRUE;
1492  for( i = bdlen-1; i >= 0 && isbinary; i-- )
1493  {
1494  isbinary = SCIPvarIsBinary(bdvars[i]);
1495  }
1496 
1497  /* if all variables in the cover are binary, then we create a logicor constraint */
1498  if( isbinary )
1499  {
1500  /* allocate memory for constraint variables */
1501  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, bdlen) );
1502 
1503  /* build up constraint */
1504  for( i = bdlen-1; i >= 0; i-- )
1505  {
1506  assert(bdtypes[i] == SCIP_BOUNDTYPE_LOWER || SCIPisFeasZero(scip, bdbounds[i]));
1507  assert(bdtypes[i] == SCIP_BOUNDTYPE_UPPER || SCIPisFeasEQ(scip, bdbounds[i], 1.0));
1508 
1509  if( bdtypes[i] == SCIP_BOUNDTYPE_LOWER )
1510  {
1511  consvars[i] = bdvars[i];
1512  }
1513  else
1514  {
1515  assert(bdtypes[i] == SCIP_BOUNDTYPE_UPPER);
1516  SCIP_CALL( SCIPgetNegatedVar(scip, bdvars[i], &consvars[i]) );
1517  }
1518  }
1519 
1520  /* create conflict constraint */
1521  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, bdlen, consvars,
1522  FALSE, TRUE, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
1523  }
1524  /* otherwise we create a bound disjunction constraint as given */
1525  else
1526  {
1527  /* create conflict constraint */
1528  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, bdlen, bdvars, bdtypes, bdbounds,
1529  FALSE, TRUE, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
1530  }
1531 
1532  /* add and release constraint if created successfully */
1533  if( cons != NULL )
1534  {
1535  if( local )
1536  {
1537  SCIP_CALL( SCIPaddConsLocal(scip, cons, NULL) );
1538  }
1539  else
1540  {
1541  SCIP_CALL( SCIPaddCons(scip, cons) );
1542  }
1543 
1544  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1545  *success = TRUE;
1546  }
1547 
1548  /* free memory */
1549  SCIPfreeBufferArrayNull(scip, &consvars);
1550 
1551  return SCIP_OKAY;
1552 }
1553 
1554 
1555 /** solve covering problem */
1556 static
1558  SCIP* coveringscip, /**< SCIP data structure for the covering problem */
1559  int ncoveringvars, /**< number of the covering problem's variables */
1560  SCIP_VAR** coveringvars, /**< array of the covering problem's variables */
1561  int* coversize, /**< size of the computed cover */
1562  int* cover, /**< array to store indices of the variables in the computed cover
1563  * (should be ready to hold ncoveringvars entries) */
1564  SCIP_Real timelimit, /**< time limit */
1565  SCIP_Real memorylimit, /**< memory limit */
1566  SCIP_Real objlimit, /**< upper bound on the cover size */
1567  SCIP_Bool* success /**< feasible cover found? */
1568  )
1569 {
1570  SCIP_Real* solvals;
1571  SCIP_Real totalpenalty;
1572  SCIP_RETCODE retcode;
1573  int i;
1574 
1575  assert(coveringscip != NULL);
1576  assert(coveringvars != NULL);
1577  assert(cover != NULL);
1578  assert(coversize != NULL);
1579  assert(timelimit > 0.0);
1580  assert(memorylimit > 0.0);
1581  assert(success != NULL);
1582 
1583  *success = FALSE;
1584 
1585  /* forbid call of heuristics and separators solving sub-CIPs */
1586  SCIP_CALL( SCIPsetSubscipsOff(coveringscip, TRUE) );
1587 
1588  /* set presolving and separation to fast */
1591 
1592  /* use inference branching */
1593  if( SCIPfindBranchrule(coveringscip, "inference") != NULL && !SCIPisParamFixed(coveringscip, "branching/inference/priority") )
1594  {
1595  SCIP_CALL( SCIPsetIntParam(coveringscip, "branching/inference/priority", INT_MAX/4) );
1596  }
1597 
1598  /* only solve root */
1599  SCIP_CALL( SCIPsetLongintParam(coveringscip, "limits/nodes", 1LL) );
1600 
1601  SCIPdebugMessage("timelimit = %g, memlimit = %g\n", timelimit, memorylimit);
1602 
1603  /* set time, memory, and objective limit */
1604  SCIP_CALL( SCIPsetRealParam(coveringscip, "limits/time", timelimit) );
1605  SCIP_CALL( SCIPsetRealParam(coveringscip, "limits/memory", memorylimit) );
1606  SCIP_CALL( SCIPsetObjlimit(coveringscip, objlimit) );
1607 
1608  /* do not abort on CTRL-C */
1609  SCIP_CALL( SCIPsetBoolParam(coveringscip, "misc/catchctrlc", FALSE) );
1610 
1611  /* disable output to console in optimized mode, enable in SCIP's debug mode */
1612 #ifdef SCIP_DEBUG
1613  SCIP_CALL( SCIPsetIntParam(coveringscip, "display/verblevel", 5) );
1614  SCIP_CALL( SCIPsetIntParam(coveringscip, "display/freq", 100000) );
1615 #else
1616  SCIP_CALL( SCIPsetIntParam(coveringscip, "display/verblevel", 0) );
1617 #endif
1618 
1619 
1620  /* solve covering problem */
1621  retcode = SCIPsolve(coveringscip);
1622 
1623  /* errors in solving the covering problem should not kill the overall solving process;
1624  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1625  */
1626  if( retcode != SCIP_OKAY )
1627  {
1628 #ifndef NDEBUG
1629  SCIP_CALL( retcode );
1630 #endif
1631  SCIPwarningMessage(coveringscip, "Error while solving covering problem in Undercover heuristic; sub-SCIP terminated with code <%d>\n",retcode);
1632  return SCIP_OKAY;
1633  }
1634 
1635  /* check, whether a feasible cover was found */
1636  if( SCIPgetNSols(coveringscip) == 0 )
1637  return SCIP_OKAY;
1638 
1639  /* store solution */
1640  SCIP_CALL( SCIPallocBufferArray(coveringscip, &solvals, ncoveringvars) );
1641  SCIP_CALL( SCIPgetSolVals(coveringscip, SCIPgetBestSol(coveringscip), ncoveringvars, coveringvars, solvals) );
1642 
1643  *coversize = 0;
1644  totalpenalty = 0.0;
1645  for( i = 0; i < ncoveringvars; i++ )
1646  {
1647  if( solvals[i] > 0.5 )
1648  {
1649  cover[*coversize] = i;
1650  (*coversize)++;
1651  }
1652  totalpenalty += SCIPvarGetObj(coveringvars[i]);
1653  }
1654 
1655  /* print solution if we are in SCIP's debug mode */
1656  assert(SCIPgetBestSol(coveringscip) != NULL);
1657  SCIPdebugMessage("found a feasible cover: %d/%d variables fixed, normalized penalty=%g\n\n",
1658  *coversize, SCIPgetNOrigVars(coveringscip), SCIPgetSolOrigObj(coveringscip, SCIPgetBestSol(coveringscip))/(totalpenalty+SCIPsumepsilon(coveringscip)));
1659  SCIPdebug( SCIP_CALL( SCIPprintSol(coveringscip, SCIPgetBestSol(coveringscip), NULL, FALSE) ) );
1660  SCIPdebugMessage("\r \n");
1661 
1662  *success = TRUE;
1663 
1664  /* free array of solution values */
1665  SCIPfreeBufferArray(coveringscip, &solvals);
1666 
1667  return SCIP_OKAY;
1668 }
1669 
1670 
1671 /** computes fixing order and returns whether order has really been changed */
1672 static
1674  SCIP* scip, /**< original SCIP data structure */
1675  SCIP_HEURDATA* heurdata, /**< heuristic data */
1676  int nvars, /**< number of variables in the original problem */
1677  SCIP_VAR** vars, /**< variables in the original problem */
1678  int coversize, /**< size of the cover */
1679  int* cover, /**< problem indices of the variables in the cover */
1680  int lastfailed, /**< position in cover array of the variable the fixing of which yielded
1681  * infeasibility in last dive (or >= coversize, in which case *success
1682  * is always TRUE) */
1683  SCIP_Bool* success /**< has order really been changed? */
1684  )
1685 {
1686  SCIP_Real* scores;
1687  SCIP_Real bestscore;
1688  SCIP_Bool sortdown;
1689  int i;
1690 
1691  assert(scip != NULL);
1692  assert(heurdata != NULL);
1693  assert(nvars >= 1);
1694  assert(vars != NULL);
1695  assert(coversize >= 1);
1696  assert(cover != NULL);
1697  assert(lastfailed >= 0);
1698 
1699  *success = FALSE;
1700 
1701  /* if fixing the first variable had failed, do not try with another order */
1702  if( lastfailed == 0 )
1703  return SCIP_OKAY;
1704 
1705  /* allocate buffer array for score values */
1706  SCIP_CALL( SCIPallocBufferArray(scip, &scores, coversize) );
1707 
1708  /* initialize best score to infinite value */
1709  sortdown = (heurdata->fixingorder == 'c' || heurdata->fixingorder == 'v' );
1710  bestscore = sortdown ? -SCIPinfinity(scip) : +SCIPinfinity(scip);
1711 
1712  /* compute score values */
1713  for( i = coversize-1; i >= 0; i-- )
1714  {
1715  SCIP_VAR* var;
1716 
1717  /* get variable in the cover */
1718  assert(cover[i] >= 0);
1719  assert(cover[i] < nvars);
1720  var = vars[cover[i]];
1721 
1722  if( heurdata->fixingorder == 'C' || heurdata->fixingorder == 'c' )
1723  scores[i] = heurdata->conflictweight * SCIPgetVarConflictScore(scip, var)
1724  + heurdata->inferenceweight * SCIPgetVarAvgInferenceCutoffScore(scip, var, heurdata->cutoffweight);
1725  else if( heurdata->fixingorder == 'V' || heurdata->fixingorder == 'v' )
1726  scores[i] = cover[i];
1727  else
1728  return SCIP_PARAMETERWRONGVAL;
1729 
1730  assert(scores[i] >= 0.0);
1731 
1732  /* update best score */
1733  if( sortdown )
1734  bestscore = MAX(bestscore, scores[i]);
1735  else
1736  bestscore = MIN(bestscore, scores[i]);
1737 
1738  }
1739 
1740  /* put integers to the front */
1741  if( heurdata->fixintfirst )
1742  {
1743  for( i = coversize-1; i >= 0; i-- )
1744  {
1745  if( SCIPvarIsIntegral(vars[cover[i]]) )
1746  {
1747  if( sortdown )
1748  scores[i] += bestscore+1.0;
1749  else
1750  scores[i] = bestscore - 1.0/(scores[i]+1.0);
1751  }
1752  }
1753  }
1754 
1755  /* put last failed variable to the front */
1756  if( lastfailed < coversize )
1757  {
1758  if( sortdown )
1759  scores[lastfailed] += bestscore+2.0;
1760  else
1761  scores[lastfailed] = bestscore - 2.0/(scores[lastfailed]+1.0);
1762  i = cover[lastfailed];
1763  }
1764 
1765  /* sort by non-decreasing (negative) score */
1766  if( sortdown )
1767  SCIPsortDownRealInt(scores, cover, coversize);
1768  else
1769  SCIPsortRealInt(scores, cover, coversize);
1770 
1771  assert(lastfailed >= coversize || cover[0] == i);
1772 
1773  /* free buffer memory */
1774  SCIPfreeBufferArray(scip, &scores);
1775 
1776  *success = TRUE;
1777 
1778  return SCIP_OKAY;
1779 }
1780 
1781 
1782 /** gets fixing value */
1783 static
1785  SCIP* scip, /**< original SCIP data structure */
1786  SCIP_HEURDATA* heurdata, /**< heuristic data */
1787  SCIP_VAR* var, /**< variable in the original problem */
1788  SCIP_Real* val, /**< buffer for returning fixing value */
1789  char fixalt, /**< source of the fixing value: 'l'p relaxation, 'n'lp relaxation, 'i'ncumbent solution */
1790  SCIP_Bool* success, /**< could value be retrieved successfully? */
1791  int bdlen, /**< current length of probing path */
1792  SCIP_VAR** bdvars, /**< array of variables with bound changes along probing path */
1793  SCIP_BOUNDTYPE* bdtypes, /**< array of bound types in bound disjunction */
1794  SCIP_Real* oldbounds /**< array of bounds before fixing */
1795  )
1796 {
1797  assert(scip != NULL);
1798  assert(heurdata != NULL);
1799  assert(var != NULL);
1800  assert(val != NULL);
1801  assert(success != NULL);
1802 
1803  *success = FALSE;
1804 
1805  switch( fixalt )
1806  {
1807  case 'l':
1808  /* get the last LP solution value */
1809  *val = SCIPvarGetLPSol(var);
1810  *success = TRUE;
1811  break;
1812  case 'n':
1813  /* only call this function if NLP relaxation is available */
1814  assert(SCIPisNLPConstructed(scip));
1815 
1816  /* the solution values are already available */
1817  if( heurdata->nlpsolved )
1818  {
1819  assert(!heurdata->nlpfailed);
1820 
1821  /* retrieve NLP solution value */
1822  *val = SCIPvarGetNLPSol(var);
1823  *success = TRUE;
1824  }
1825  /* solve NLP relaxation unless it has not failed too often before */
1826  else if( !heurdata->nlpfailed )
1827  { /*lint --e{850}*/
1828  SCIP_NLPSOLSTAT stat;
1829  int i;
1830 
1831  /* restore bounds at start of probing, since otherwise, if in backtrack mode, NLP solver becomes most likely
1832  * locally infeasible
1833  */
1834  SCIP_CALL( SCIPstartDiveNLP(scip) );
1835 
1836  for( i = bdlen-1; i >= 0; i-- )
1837  {
1838  SCIP_VAR* relaxvar;
1839  SCIP_Real lb;
1840  SCIP_Real ub;
1841 
1842  relaxvar = bdvars[i];
1843 
1844  /* both bounds were tightened */
1845  if( i > 0 && bdvars[i-1] == relaxvar )
1846  {
1847  assert(bdtypes[i] != bdtypes[i-1]);
1848 
1849  lb = bdtypes[i] == SCIP_BOUNDTYPE_UPPER ? oldbounds[i] : oldbounds[i-1];
1850  ub = bdtypes[i] == SCIP_BOUNDTYPE_UPPER ? oldbounds[i-1] : oldbounds[i];
1851  i--;
1852  }
1853  /* lower bound was tightened */
1854  else if( bdtypes[i] == SCIP_BOUNDTYPE_UPPER )
1855  {
1856  lb = oldbounds[i];
1857  ub = SCIPvarGetUbLocal(relaxvar);
1858  }
1859  /* upper bound was tightened */
1860  else
1861  {
1862  lb = SCIPvarGetLbLocal(relaxvar);
1863  ub = oldbounds[i];
1864  }
1865 
1866  assert(SCIPisLE(scip, lb, SCIPvarGetLbLocal(relaxvar)));
1867  assert(SCIPisGE(scip, ub, SCIPvarGetUbLocal(relaxvar)));
1868 
1869  /* relax bounds */
1870  SCIP_CALL( SCIPchgVarBoundsDiveNLP(scip, relaxvar, lb, ub) );
1871  }
1872 
1873  /* activate NLP solver output if we are in SCIP's debug mode */
1875 
1876  /* set starting point to lp solution */
1878 
1879  /* solve NLP relaxation */
1880  SCIP_CALL( SCIPsolveDiveNLP(scip) );
1881  stat = SCIPgetNLPSolstat(scip);
1882  *success = stat == SCIP_NLPSOLSTAT_GLOBOPT || stat == SCIP_NLPSOLSTAT_LOCOPT || stat == SCIP_NLPSOLSTAT_FEASIBLE;
1883 
1884  SCIPdebugMessage("solving NLP relaxation to obtain fixing values %s (stat=%d)\n", *success ? "successful" : "failed", stat);
1885 
1886  if( *success )
1887  {
1888  /* solving succeeded */
1889  heurdata->nnlpfails = 0;
1890  heurdata->nlpsolved = TRUE;
1891 
1892  /* retrieve NLP solution value */
1893  *val = SCIPvarGetNLPSol(var);
1894  }
1895  else
1896  {
1897  /* solving failed */
1898  heurdata->nnlpfails++;
1899  heurdata->nlpfailed = TRUE;
1900  heurdata->nlpsolved = FALSE;
1901 
1902  SCIPdebugMessage("solving NLP relaxation failed (%d time%s%s)\n",
1903  heurdata->nnlpfails, heurdata->nnlpfails > 1 ? "s" : "", heurdata->nnlpfails >= MAXNLPFAILS ? ", will not be called again" : "");
1904  }
1905  }
1906  break;
1907  case 'i':
1908  /* only call this function if a feasible solution is available */
1909  assert(SCIPgetBestSol(scip) != NULL);
1910 
1911  /* get value in the incumbent solution */
1912  *val = SCIPgetSolVal(scip, SCIPgetBestSol(scip), var);
1913  *success = TRUE;
1914  break;
1915  default:
1916  break;
1917  }
1918 
1919  return SCIP_OKAY;
1920 }
1921 
1922 
1923 /** calculates up to four alternative values for backtracking, if fixing the variable failed.
1924  * The alternatives are the two bounds of the variable, and the averages of the bounds and the fixing value.
1925  * For infinite bounds, fixval +/- abs(fixval) will be used instead.
1926  */
1927 static
1929  SCIP* scip, /**< original SCIP data structure */
1930  SCIP_VAR* var, /**< variable to calculate alternatives for */
1931  SCIP_Real fixval, /**< reference fixing value */
1932  int* nalternatives, /**< number of fixing values computed */
1933  SCIP_Real* alternatives /**< array to store the alternative fixing values */
1934  )
1935 {
1936  SCIP_Real lb;
1937  SCIP_Real ub;
1938 
1939  /* for binary variables, there is only two possible fixing values */
1940  if( SCIPvarIsBinary(var) )
1941  {
1942  if( SCIPisFeasEQ(scip, fixval, 0.0) || SCIPisFeasEQ(scip, fixval, 1.0) )
1943  {
1944  alternatives[0] = 1.0 - fixval;
1945  *nalternatives = 1;
1946  }
1947  else
1948  {
1949  alternatives[0] = 0.0;
1950  alternatives[1] = 1.0;
1951  *nalternatives = 2;
1952  }
1953  return;
1954  }
1955 
1956  /* get bounds */
1957  lb = SCIPvarGetLbLocal(var);
1958  ub = SCIPvarGetUbLocal(var);
1959 
1960  /* if lower bound is infinite, use x'-|x'|; if x' is zero, use -1.0 instead */
1961  if( SCIPisInfinity(scip, -lb) )
1962  lb = SCIPisFeasZero(scip, fixval) ? -1.0 : fixval - ABS(fixval);
1963 
1964  /* if upper bound is infinite, use x'+|x'|; if x' is zero, use 1.0 instead */
1965  if( SCIPisInfinity(scip, ub) )
1966  ub = SCIPisFeasZero(scip, fixval) ? 1.0 : fixval + ABS(fixval);
1967 
1968  assert(!SCIPisEQ(scip, lb, ub));
1969 
1970  /* collect alternatives */
1971  *nalternatives = 0;
1972 
1973  /* use lower bound if not equal to x' */
1974  if( !SCIPisFeasEQ(scip, lb, fixval) )
1975  {
1976  alternatives[*nalternatives] = lb;
1977  (*nalternatives)++;
1978  }
1979 
1980  /* use upper bound if not equal to x' */
1981  if( !SCIPisFeasEQ(scip, ub, fixval) )
1982  {
1983  alternatives[*nalternatives] = ub;
1984  (*nalternatives)++;
1985  }
1986 
1987  /* use the average of x' and lower bound as alternative value, if this is not equal to any of the other values */
1988  if( !SCIPisFeasEQ(scip, lb, fixval) && (!SCIPvarIsIntegral(var) || !SCIPisFeasEQ(scip, lb, fixval-1)) )
1989  {
1990  alternatives[*nalternatives] = (lb+fixval)/2.0;
1991  (*nalternatives)++;
1992  }
1993 
1994  /* use the average of x' and upper bound as alternative value, if this is not equal to any of the other values */
1995  if( !SCIPisFeasEQ(scip, ub, fixval) && (!SCIPvarIsIntegral(var) || !SCIPisFeasEQ(scip, ub, fixval+1)) )
1996  {
1997  alternatives[*nalternatives] = (ub+fixval)/2.0;
1998  (*nalternatives)++;
1999  }
2000 
2001  assert(*nalternatives <= 4);
2002 
2003  return;
2004 }
2005 
2006 
2007 /** rounds the given fixing value */
2008 static
2010  SCIP* scip, /**< original SCIP data structure */
2011  SCIP_Real* val, /**< fixing value to be rounded */
2012  SCIP_VAR* var, /**< corresponding variable */
2013  SCIP_Bool locksrounding /**< shall we round according to locks? (otherwise to nearest integer) */
2014  )
2015 {
2016  SCIP_Real x;
2017 
2018  x = *val;
2019 
2020  /* if integral within feasibility tolerance, only shift to nearest integer */
2021  if( SCIPisFeasIntegral(scip, x) )
2022  x = SCIPfeasFrac(scip, x) < 0.5 ? SCIPfeasFloor(scip, x) : SCIPfeasCeil(scip, x);
2023 
2024  /* round in the direction of least locks with fractionality as tie breaker */
2025  else if( locksrounding )
2026  {
2027  if( SCIPvarGetNLocksDown(var) < SCIPvarGetNLocksUp(var) )
2028  x = SCIPfeasFloor(scip, x);
2029  else if( SCIPvarGetNLocksDown(var) > SCIPvarGetNLocksUp(var) )
2030  x = SCIPfeasCeil(scip, x);
2031  else
2032  x = SCIPfeasFrac(scip, x) < 0.5 ? SCIPfeasFloor(scip, x) : SCIPfeasCeil(scip, x);
2033  }
2034  /* round in the direction of least fractionality with locks as tie breaker */
2035  else
2036  {
2037  if( SCIPfeasFrac(scip, x) < 0.5)
2038  x = SCIPfeasFloor(scip, x);
2039  else if( SCIPfeasFrac(scip, x) > 0.5 )
2040  x = SCIPfeasCeil(scip, x);
2041  else
2042  x = SCIPvarGetNLocksDown(var) < SCIPvarGetNLocksUp(var) ? SCIPfeasFloor(scip, x) : SCIPfeasCeil(scip, x);
2043  }
2044 
2045  /* return rounded fixing value */
2046  *val = x;
2047 
2048  return SCIP_OKAY;
2049 }
2050 
2051 
2052 /** copy the solution of the subproblem to newsol */
2053 static
2055  SCIP* scip, /**< original SCIP data structure */
2056  SCIP* subscip, /**< SCIP structure of the subproblem */
2057  SCIP_VAR** subvars, /**< the variables of the subproblem */
2058  SCIP_SOL* subsol, /**< solution of the subproblem */
2059  SCIP_SOL** newsol /**< solution to the original problem */
2060  )
2061 {
2062  SCIP_VAR** vars; /* the original problem's variables */
2063  SCIP_Real* subsolvals; /* solution values of the subproblem */
2064  int nvars;
2065 
2066  assert(scip != NULL);
2067  assert(subscip != NULL);
2068  assert(subvars != NULL);
2069  assert(subsol != NULL);
2070  assert(newsol != NULL);
2071  assert(*newsol != NULL);
2072 
2073  /* get variables' data */
2074  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2075 
2076  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
2077  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
2078  */
2079  assert(nvars <= SCIPgetNOrigVars(subscip));
2080 
2081  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
2082 
2083  /* copy the solution */
2084  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
2085  SCIP_CALL( SCIPsetSolVals(scip, *newsol, nvars, vars, subsolvals) );
2086 
2087  SCIPfreeBufferArray(scip, &subsolvals);
2088 
2089  return SCIP_OKAY;
2090 }
2091 
2092 
2093 /** solve subproblem and pass best feasible solution to original SCIP instance */
2094 static
2096  SCIP* scip, /**< SCIP data structure of the original problem */
2097  SCIP_HEUR* heur, /**< heuristic data structure */
2098  int coversize, /**< size of the cover */
2099  int* cover, /**< problem indices of the variables in the cover */
2100  SCIP_Real* fixingvals, /**< fixing values for the variables in the cover */
2101  SCIP_Real timelimit, /**< time limit */
2102  SCIP_Real memorylimit, /**< memory limit */
2103  SCIP_Longint nodelimit, /**< node limit */
2104  SCIP_Longint nstallnodes, /**< number of stalling nodes for the subproblem */
2105  SCIP_Bool* validsolved, /**< was problem constructed from a valid copy and solved (proven optimal or infeasible)? */
2106  SCIP_SOL** sol, /**< best solution found in subproblem (if feasible); *sol must be NULL, solution will be created */
2107  SCIP_Longint* nusednodes /**< number of nodes used for solving the subproblem */
2108  )
2109 {
2110  SCIP_HEURDATA* heurdata;
2111  SCIP* subscip;
2112  SCIP_VAR** subvars;
2113  SCIP_VAR** vars;
2114  SCIP_HASHMAP* varmap;
2115 
2116  SCIP_RETCODE retcode;
2117 
2118  int nvars;
2119  int i;
2120 
2121  assert(scip != NULL);
2122  assert(heur != NULL);
2123  assert(cover != NULL);
2124  assert(fixingvals != NULL);
2125  assert(coversize >= 1);
2126  assert(timelimit > 0.0);
2127  assert(memorylimit > 0.0);
2128  assert(nodelimit >= 1);
2129  assert(nstallnodes >= 1);
2130  assert(validsolved != NULL);
2131  assert(sol != NULL);
2132  assert(*sol == NULL);
2133  assert(nusednodes != NULL);
2134 
2135  *validsolved = FALSE;
2136  *nusednodes = 0;
2137 
2138  /* get heuristic data */
2139  heurdata = SCIPheurGetData(heur);
2140  assert(heurdata != NULL);
2141 
2142  /* get required data of the original problem */
2143  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2144 
2145  /* create subproblem */
2146  SCIP_CALL( SCIPcreate(&subscip) );
2147  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
2148 
2149  /* create the variable mapping hash map */
2150  SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
2151 
2152  /* copy original problem to subproblem; do not copy pricers */
2153  SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "undercoversub", heurdata->globalbounds, FALSE, TRUE, validsolved) );
2154 
2155  if( heurdata->copycuts )
2156  {
2157  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
2158  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, heurdata->globalbounds, NULL) );
2159  }
2160 
2161  SCIPdebugMessage("problem copied, copy %svalid\n", *validsolved ? "" : "in");
2162 
2163  /* store subproblem variables */
2164  for( i = nvars-1; i >= 0; i-- )
2165  {
2166  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
2167  assert(subvars[i] != NULL);
2168  }
2169 
2170  /* fix subproblem variables in the cover */
2171  SCIPdebugMessage("fixing variables\n");
2172  for( i = coversize-1; i >= 0; i-- )
2173  {
2174  assert(cover[i] >= 0);
2175  assert(cover[i] < nvars);
2176 
2177  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[cover[i]], fixingvals[i]) );
2178  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[cover[i]], fixingvals[i]) );
2179  }
2180 
2181  /* set the parameters such that good solutions are found fast */
2182  SCIPdebugMessage("setting subproblem parameters\n");
2186 
2187  /* deactivate expensive pre-root heuristics, since it may happen that the lp relaxation of the subproblem is already
2188  * infeasible; in this case, we do not want to waste time on heuristics before solving the root lp */
2189  if( !SCIPisParamFixed(subscip, "heuristics/shiftandpropagate/freq") )
2190  {
2191  SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/shiftandpropagate/freq", -1) );
2192  }
2193 
2194  /* forbid recursive call of undercover heuristic */
2195  if( SCIPisParamFixed(subscip, "heuristics/" HEUR_NAME "/freq") )
2196  {
2197  SCIPwarningMessage(scip, "unfixing parameter heuristics/" HEUR_NAME "/freq in subscip of undercover heuristic to avoid recursive calls\n");
2198  SCIP_CALL( SCIPunfixParam(subscip, "heuristics/" HEUR_NAME "/freq") );
2199  }
2200  SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/" HEUR_NAME "/freq", -1) );
2201 
2202  SCIPdebugMessage("timelimit = %g, memlimit = %g, nodelimit = %" SCIP_LONGINT_FORMAT ", nstallnodes = %" SCIP_LONGINT_FORMAT "\n", timelimit, memorylimit, nodelimit, nstallnodes);
2203 
2204  SCIPdebugMessage("timelimit = %g, memlimit = %g, nodelimit = %" SCIP_LONGINT_FORMAT ", nstallnodes = %" SCIP_LONGINT_FORMAT "\n", timelimit, memorylimit, nodelimit, nstallnodes);
2205 
2206  /* disable statistic timing inside sub SCIP */
2207  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
2208 
2209  /* set time, memory and node limits */
2210  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
2211  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
2212  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) );
2213  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
2214 
2215  /* do not abort subproblem on CTRL-C */
2216  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
2217 
2218  /* disable output to console in optimized mode, enable in SCIP's debug mode */
2219 #ifdef SCIP_DEBUG
2220  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
2221  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000) );
2222 #else
2223  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
2224 #endif
2225 
2226  /* if there is already a solution, add an objective cutoff; note: this does not affect the validity of the subproblem
2227  * if we find solutions later, thus we do not set *validsolved to FALSE */
2228  if( SCIPgetNSols(scip) > 0 )
2229  {
2230  SCIP_Real cutoff;
2231  SCIP_Real upperbound;
2232 
2233  assert(!SCIPisInfinity(scip, SCIPgetUpperbound(scip)));
2234  upperbound = SCIPgetUpperbound(scip);
2235 
2236  if( SCIPisInfinity(scip, -SCIPgetLowerbound(scip)) )
2237  cutoff = (upperbound >= 0 ? 1.0 - heurdata->minimprove : 1.0 + heurdata->minimprove) * upperbound;
2238  else
2239  cutoff = (1.0 - heurdata->minimprove) * upperbound + heurdata->minimprove * SCIPgetLowerbound(scip);
2240 
2241  cutoff = MIN(upperbound, cutoff);
2242  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
2243 
2244  SCIPdebugMessage("adding objective cutoff=%g (minimprove=%g)\n", cutoff, heurdata->minimprove);
2245  }
2246 
2247  /* solve subproblem */
2248  SCIPdebugMessage("solving subproblem started\n");
2249  retcode = SCIPsolve(subscip);
2250 
2251  /* Errors in solving the subproblem should not kill the overall solving process
2252  * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
2253  */
2254  if( retcode != SCIP_OKAY )
2255  {
2256 #ifndef NDEBUG
2257  SCIP_CALL( retcode );
2258 #endif
2259  SCIPwarningMessage(scip, "Error while solving subproblem in Undercover heuristic; sub-SCIP terminated with code <%d>\n",retcode);
2260  return SCIP_OKAY;
2261  }
2262 
2263  /* print solving statistics of subproblem if we are in SCIP's debug mode */
2264  SCIPdebug( SCIP_CALL( SCIPprintStatistics(subscip, NULL) ) );
2265 
2266  /* store solving status; note: if we proved infeasibility in presence of an objective cutoff beyond the primal bound,
2267  * the subproblem was not a valid copy */
2268  *validsolved = *validsolved && (SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL
2269  || (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE && (SCIPgetNSols(scip) == 0 || heurdata->minimprove <= 0.0)));
2270  *nusednodes = SCIPgetNNodes(subscip);
2271 
2272  /* if a solution was found for the subproblem, create corresponding solution in the original problem */
2273  if( SCIPgetNSols(subscip) > 0 && (SCIPgetStatus(subscip) != SCIP_STATUS_INFEASIBLE || heurdata->minimprove > 0.0) )
2274  {
2275  SCIP_SOL** subsols;
2276  SCIP_Bool success;
2277  int nsubsols;
2278 
2279  /* create solution */
2280  SCIP_CALL( SCIPcreateSol(scip, sol, heur) );
2281 
2282  /* check, whether a solution was found;
2283  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
2284  nsubsols = SCIPgetNSols(subscip);
2285  subsols = SCIPgetSols(subscip);
2286  assert(subsols != NULL);
2287 
2288  success = FALSE;
2289  for( i = 0; i < nsubsols && !success; i++ )
2290  {
2291  /* transform solution to original problem */
2292  SCIP_CALL( copySol(scip, subscip, subvars, subsols[i], sol) );
2293 
2294  /* try to add new solution to scip */
2295  SCIP_CALL( SCIPtrySol(scip, *sol, FALSE, TRUE, TRUE, TRUE, &success) );
2296  }
2297 
2298  if( success )
2299  {
2300  assert(i >= 1);
2301  SCIPdebugMessage("heuristic found %d solutions in subproblem; solution %d feasible in original problem\n", nsubsols, i);
2302  }
2303  else
2304  {
2305  /* free solution structure, since we found no feasible solution */
2306  SCIP_CALL( SCIPfreeSol(scip, sol) );
2307  *sol = NULL;
2308  }
2309 
2310  /* if the best subproblem solution was not accepted in the original problem, we do not trust the solving status */
2311  *validsolved = *validsolved && i == 1;
2312  }
2313 
2314  if( *validsolved )
2315  {
2316  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
2317  }
2318 
2319  /* free variable mapping hash map, array of subproblem variables, and subproblem */
2320  SCIPhashmapFree(&varmap);
2321  SCIPfreeBufferArray(scip, &subvars);
2322  SCIP_CALL( SCIPfree(&subscip) );
2323 
2324  return SCIP_OKAY;
2325 }
2326 
2327 
2328 /** perform fixing of a variable and record bound disjunction information */
2329 static
2331  SCIP* scip, /**< SCIP data structure */
2332  SCIP_VAR* var, /**< variable to fix */
2333  SCIP_Real val, /**< fixing value */
2334  SCIP_Bool* infeas, /**< pointer to store whether the fixing lead to infeasibility */
2335  int* bdlen, /**< current length of bound disjunction */
2336  SCIP_VAR** bdvars, /**< array of variables in bound disjunction */
2337  SCIP_BOUNDTYPE* bdtypes, /**< array of bound types in bound disjunction */
2338  SCIP_Real* bdbounds, /**< array of bounds in bound disjunction */
2339  SCIP_Real* oldbounds /**< array of bounds before fixing */
2340  )
2341 {
2342  SCIP_Longint ndomredsfound;
2343  SCIP_Real oldlb;
2344  SCIP_Real oldub;
2345  int oldbdlen;
2346 
2347  assert(scip != NULL);
2348  assert(var != NULL);
2349  assert(val >= SCIPvarGetLbLocal(var));
2350  assert(val <= SCIPvarGetUbLocal(var));
2351  assert(infeas != NULL);
2352  assert(bdlen != NULL);
2353  assert(*bdlen >= 0);
2354  assert(*bdlen < 2*SCIPgetNVars(scip)-1);
2355  assert(bdvars != NULL);
2356  assert(bdtypes != NULL);
2357  assert(bdbounds != NULL);
2358 
2359  assert(!SCIPvarIsIntegral(var) || SCIPisFeasIntegral(scip, val));
2360 
2361  /* remember length of probing path */
2362  oldbdlen = *bdlen;
2363 
2364  /* get bounds of the variable to fix */
2365  oldlb = SCIPvarGetLbLocal(var);
2366  oldub = SCIPvarGetUbLocal(var);
2367 
2368  /* decrease upper bound to fixing value */
2369  *infeas = FALSE;
2370  if( SCIPisUbBetter(scip, val, oldlb, oldub) )
2371  {
2372  /* we only want to open a new probing node if we do not exceed the maximal tree depth */
2373  if( SCIPgetDepth(scip) < SCIPgetDepthLimit(scip) )
2374  {
2375  /* create next probing node */
2376  SCIP_CALL( SCIPnewProbingNode(scip) );
2377  }
2378  SCIP_CALL( SCIPchgVarUbProbing(scip, var, val) );
2379 
2380  SCIPdebugMessage("tentatively decreasing upper bound of variable <%s> to %g for probing\n",
2381  SCIPvarGetName(var), val);
2382 
2383  /* store bound disjunction information */
2384  bdvars[*bdlen] = var;
2385  bdtypes[*bdlen] = SCIP_BOUNDTYPE_LOWER;
2386  bdbounds[*bdlen] = SCIPvarIsIntegral(var) ? SCIPfeasCeil(scip, val)+1.0 : val;
2387  oldbounds[*bdlen] = oldub;
2388  (*bdlen)++;
2389 
2390  /* propagate the bound change; conflict analysis is performed automatically */
2391  SCIP_CALL( SCIPpropagateProbing(scip, 0, infeas, &ndomredsfound) );
2392  SCIPdebugMessage(" --> propagation reduced %" SCIP_LONGINT_FORMAT " further domains\n", ndomredsfound);
2393 
2394  /* if propagation led to a cutoff, we backtrack immediately */
2395  if( *infeas )
2396  {
2397  *bdlen = oldbdlen;
2398  return SCIP_OKAY;
2399  }
2400 
2401  /* store bound before propagation */
2402  oldbounds[*bdlen] = oldlb;
2403 
2404  /* move fixing value into the new domain, since it may be outside due to numerical issues or previous propagation */
2405  oldlb = SCIPvarGetLbLocal(var);
2406  oldub = SCIPvarGetUbLocal(var);
2407  val = MIN(val, oldub);
2408  val = MAX(val, oldlb);
2409 
2410  assert(!SCIPvarIsIntegral(var) || SCIPisFeasIntegral(scip, val));
2411  }
2412 
2413  /* update lower bound to fixing value */
2414  *infeas = FALSE;
2415  if( SCIPisLbBetter(scip, val, oldlb, oldub) )
2416  {
2417  /* we only want to open a new probing node if we do not exceed the maximal tree depth */
2418  if( SCIPgetDepth(scip) < SCIPgetDepthLimit(scip) )
2419  {
2420  /* create next probing node */
2421  SCIP_CALL( SCIPnewProbingNode(scip) );
2422  }
2423  SCIP_CALL( SCIPchgVarLbProbing(scip, var, val) );
2424 
2425  SCIPdebugMessage("tentatively increasing lower bound of variable <%s> to %g for probing\n",
2426  SCIPvarGetName(var), val);
2427 
2428  /* store bound disjunction information */
2429  bdvars[*bdlen] = var;
2430  bdtypes[*bdlen] = SCIP_BOUNDTYPE_UPPER;
2431  bdbounds[*bdlen] = SCIPvarIsIntegral(var) ? SCIPfeasCeil(scip, val)-1.0 : val;
2432  (*bdlen)++;
2433 
2434  /* propagate the bound change */
2435  SCIP_CALL( SCIPpropagateProbing(scip, 0, infeas, &ndomredsfound) );
2436  SCIPdebugMessage(" --> propagation reduced %" SCIP_LONGINT_FORMAT " further domains\n", ndomredsfound);
2437 
2438  /* if propagation led to a cutoff, we backtrack immediately */
2439  if( *infeas )
2440  {
2441  *bdlen = oldbdlen;
2442  return SCIP_OKAY;
2443  }
2444  }
2445 
2446  return SCIP_OKAY;
2447 }
2448 
2449 static
2451  SCIP* scip, /**< original SCIP data structure */
2452  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
2453  int* cover, /**< array with indices of the variables in the computed cover */
2454  int coversize, /**< size of the cover */
2455  SCIP_Real* fixingvals, /**< fixing values for the variables in the cover */
2456  int* bdlen, /**< current length of bound disjunction along the probing path */
2457  SCIP_VAR** bdvars, /**< array of variables in bound disjunction */
2458  SCIP_BOUNDTYPE* bdtypes, /**< array of bound types in bound disjunction */
2459  SCIP_Real* bdbounds, /**< array of bounds in bound disjunction */
2460  SCIP_Real* oldbounds, /**< array of bounds before fixing */
2461  int* nfixedints, /**< pointer to store number of fixed integer variables */
2462  int* nfixedconts, /**< pointer to store number of fixed continuous variables */
2463  int* lastfailed, /**< position in cover array of the variable the fixing of which yielded
2464  * infeasibility */
2465  SCIP_Bool* infeas /**< pointer to store whether fix-and-propagate led to an infeasibility */
2466  )
2467 {
2468  SCIP_VAR** vars; /* original problem's variables */
2469 
2470  int i;
2471  SCIP_Bool lpsolved;
2472 
2473  /* start probing in original problem */
2474  lpsolved = SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL;
2475  SCIP_CALL( SCIPstartProbing(scip) );
2476 
2477  /* initialize data */
2478  *nfixedints = 0;
2479  *nfixedconts = 0;
2480  *bdlen = 0;
2481  vars = SCIPgetVars(scip);
2482 
2483  /* round-fix-propagate-analyze-backtrack for each variable in the cover */
2484  for( i = 0; i < coversize && !(*infeas); i++ )
2485  {
2486  SCIP_Real* boundalts;
2487  SCIP_Real* usedvals;
2488  SCIP_Real val;
2489  int nbacktracks;
2490  int nboundalts;
2491  int nfailedvals;
2492  int nusedvals;
2493  int probingdepth;
2494  int idx;
2495 
2496  /* get probindex of next variable in the cover */
2497  idx = cover[i];
2498 
2499  /* nothing to do if the variable was already fixed, e.g., by propagation */
2500  if( SCIPisEQ(scip, SCIPvarGetLbLocal(vars[idx]), SCIPvarGetUbLocal(vars[idx])) )
2501  {
2502  fixingvals[i] = SCIPvarGetLbLocal(vars[idx]);
2503  continue;
2504  }
2505 
2506  /* we will store the fixing values already used to avoid try the same value twice */
2507  SCIP_CALL( SCIPallocBufferArray(scip, &usedvals, heurdata->maxbacktracks+1) );
2508  nusedvals = 0;
2509 
2510  /* backtracking loop */
2511  *infeas = TRUE;
2512  nfailedvals = 0;
2513  nboundalts = 0;
2514  boundalts = NULL;
2515  val = 0.0;
2516  for( nbacktracks = 0; nbacktracks <= heurdata->maxbacktracks+nfailedvals && *infeas; nbacktracks++ )
2517  {
2518  SCIP_Real oldlb;
2519  SCIP_Real oldub;
2520  SCIP_Bool usedbefore;
2521  int j;
2522 
2523  probingdepth = SCIPgetProbingDepth(scip);
2524 
2525  /* get fixing value */
2526  if( nbacktracks < heurdata->nfixingalts )
2527  {
2528  SCIP_Bool success;
2529 
2530  /* if the lp relaxation is not solved, we do not even try to retrieve the lp solution value;
2531  * if the NLP relaxation is not constructed, we do not even try to retrieve the NLP solution value;
2532  * if there is no feasible solution yet, we do not even try to obtain the value in the incumbent */
2533  success = FALSE;
2534  if( (heurdata->fixingalts[nbacktracks] != 'l' || lpsolved)
2535  && (heurdata->fixingalts[nbacktracks] != 'n' || !heurdata->nlpfailed)
2536  && (heurdata->fixingalts[nbacktracks] != 'i' || SCIPgetBestSol(scip) != NULL) )
2537  {
2538  SCIP_CALL( getFixingValue(scip, heurdata, vars[idx], &val, heurdata->fixingalts[nbacktracks], &success, *bdlen, bdvars, bdtypes, oldbounds) );
2539  }
2540 
2541  if( !success )
2542  {
2543  SCIPdebugMessage("retrieving fixing value '%c' for variable <%s> failed, trying next in the list\n",
2544  heurdata->fixingalts[nbacktracks], SCIPvarGetName(vars[idx]));
2545  nfailedvals++;
2546  continue;
2547  }
2548 
2549  /* for the first (successfully retrieved) fixing value, compute (at most 4) bound dependent
2550  * alternative fixing values */
2551  if( boundalts == NULL )
2552  {
2553  SCIP_CALL( SCIPallocBufferArray(scip, &boundalts, 4) );
2554  nboundalts = 0;
2555  calculateAlternatives(scip, vars[idx], val, &nboundalts, boundalts);
2556  assert(nboundalts >= 0);
2557  assert(nboundalts <= 4);
2558  }
2559  }
2560  /* get alternative fixing value */
2561  else if( boundalts != NULL && nbacktracks < heurdata->nfixingalts+nboundalts )
2562  {
2563  assert(nbacktracks-heurdata->nfixingalts >= 0);
2564  val = boundalts[nbacktracks-heurdata->nfixingalts];
2565  }
2566  else
2567  break;
2568 
2569  /* round fixing value */
2570  if( SCIPvarIsIntegral(vars[idx]) && !SCIPisIntegral(scip, val) )
2571  {
2572  SCIP_CALL( roundFixingValue(scip, &val, vars[idx], heurdata->locksrounding) );
2573  assert(SCIPisIntegral(scip, val));
2574  }
2575 
2576  /* move value into the domain, since it may be outside due to numerical issues or previous propagation */
2577  oldlb = SCIPvarGetLbLocal(vars[idx]);
2578  oldub = SCIPvarGetUbLocal(vars[idx]);
2579  val = MIN(val, oldub);
2580  val = MAX(val, oldlb);
2581 
2582  assert(!SCIPvarIsIntegral(vars[idx]) || SCIPisFeasIntegral(scip, val));
2583 
2584  /* check if this fixing value was already used */
2585  usedbefore = FALSE;
2586  for( j = nusedvals-1; j >= 0 && !usedbefore; j-- )
2587  usedbefore = SCIPisFeasEQ(scip, val, usedvals[j]);
2588 
2589  if( usedbefore )
2590  {
2591  nfailedvals++;
2592  continue;
2593  }
2594 
2595  /* store fixing value */
2596  assert(nusedvals < heurdata->maxbacktracks);
2597  usedvals[nusedvals] = val;
2598  nusedvals++;
2599 
2600  /* fix-propagate-analyze */
2601  SCIP_CALL( performFixing(scip, vars[idx], val, infeas, bdlen, bdvars, bdtypes, bdbounds, oldbounds) );
2602 
2603  /* if infeasible, backtrack and try alternative fixing value */
2604  if( *infeas )
2605  {
2606  SCIPdebugMessage(" --> cutoff detected - backtracking\n");
2607  SCIP_CALL( SCIPbacktrackProbing(scip, probingdepth) );
2608  }
2609  }
2610 
2611  /* free array of alternative backtracking values */
2612  if( boundalts != NULL)
2613  SCIPfreeBufferArray(scip, &boundalts);
2614  SCIPfreeBufferArray(scip, &usedvals);
2615 
2616  /* backtracking loop unsuccessful */
2617  if( *infeas )
2618  {
2619  SCIPdebugMessage("no feasible fixing value found for variable <%s> in fixing order\n",
2620  SCIPvarGetName(vars[idx]));
2621  break;
2622  }
2623  /* fixing successful */
2624  else
2625  {
2626  /* store successful fixing value */
2627  fixingvals[i] = val;
2628 
2629  /* statistics */
2630  if( SCIPvarGetType(vars[idx]) == SCIP_VARTYPE_CONTINUOUS )
2631  (*nfixedconts)++;
2632  else
2633  (*nfixedints)++;
2634  }
2635  }
2636  assert(*infeas || i == coversize);
2637  assert(!(*infeas) || i < coversize);
2638 
2639  /* end of dive */
2640  SCIP_CALL( SCIPendProbing(scip) );
2641 
2642  *lastfailed = i;
2643 
2644  return SCIP_OKAY;
2645 }
2646 
2647 /** main procedure of the undercover heuristic */
2648 static
2650  SCIP* scip, /**< original SCIP data structure */
2651  SCIP_HEUR* heur, /**< heuristic data structure */
2652  SCIP_RESULT* result, /**< result data structure */
2653  SCIP_Real timelimit, /**< time limit */
2654  SCIP_Real memorylimit, /**< memory limit */
2655  SCIP_Longint nstallnodes /**< number of stalling nodes for the subproblem */
2656  )
2657 {
2658  SCIP_HEURDATA* heurdata; /* heuristic data */
2659  SCIP_VAR** vars; /* original problem's variables */
2660  SCIP_CLOCK* clock; /* clock for updating time limit */
2661 
2662  SCIP* coveringscip; /* SCIP data structure for covering problem */
2663  SCIP_VAR** coveringvars; /* covering variables */
2664  SCIP_Real* fixingvals; /* array for storing fixing values used */
2665  int* cover; /* array to store problem indices of variables in the computed cover */
2666 
2667  SCIP_VAR** bdvars; /* array of variables in bound disjunction along the probing path */
2668  SCIP_BOUNDTYPE* bdtypes; /* array of bound types in bound disjunction along the probing path */
2669  SCIP_Real* bdbounds; /* array of bounds in bound disjunction along the probing path */
2670  SCIP_Real* oldbounds; /* array of bounds before fixing along the probing path */
2671 
2672  SCIP_Real maxcoversize;
2673 
2674  int coversize;
2675  int nvars;
2676  int ncovers;
2677  int nunfixeds;
2678  int nnlconss;
2679  int i;
2680 
2681  SCIP_Bool success;
2682  SCIP_Bool reusecover;
2683 
2684  assert(scip != NULL);
2685  assert(heur != NULL);
2686  assert(result != NULL);
2687  assert(*result == SCIP_DIDNOTFIND);
2688 
2689  /* create and start timing */
2690  SCIP_CALL( SCIPcreateClock(scip, &clock) );
2691  SCIP_CALL( SCIPstartClock(scip, clock) );
2692 
2693  /* initialize */
2694  fixingvals = NULL;
2695  cover = NULL;
2696  bdvars = NULL;
2697  bdtypes = NULL;
2698  bdbounds = NULL;
2699  oldbounds = NULL;
2700  coversize = 0;
2701 
2702  /* get heuristic data */
2703  heurdata = SCIPheurGetData(heur);
2704  assert(heurdata != NULL);
2705 
2706  /* NLP relaxation has not been solved yet (only solve once, not again for each cover or dive, because it is expensive) */
2707  heurdata->nlpsolved = FALSE;
2708 
2709  /* if solving the NLP relaxation has failed too often in previous runs, or NLP and NLP solver is not available, we do
2710  * not even try
2711  */
2712  heurdata->nlpfailed = heurdata->nnlpfails >= MAXNLPFAILS || !SCIPisNLPConstructed(scip) || SCIPgetNNlpis(scip) == 0;
2713 
2714  /* get variable data of original problem */
2715  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2716 
2717  /* get number of nonlinear constraints */
2718  nnlconss = 0;
2719  for( i = 0; i < heurdata->nnlconshdlrs; ++i )
2720  nnlconss += SCIPconshdlrGetNActiveConss(heurdata->nlconshdlrs[i]);
2721  assert(nnlconss >= 0);
2722  assert(nnlconss <= SCIPgetNConss(scip));
2723 
2724  /* run only if problem is sufficiently nonlinear */
2725  if( nnlconss < (SCIP_Real) SCIPgetNConss(scip) * heurdata->mincoveredrel || nnlconss < heurdata->mincoveredabs )
2726  {
2727  SCIPdebugMessage("too few nonlinear constraints present, not running\n");
2728 
2729  /* free clock */
2730  SCIP_CALL( SCIPfreeClock(scip, &clock) );
2731 
2732  return SCIP_OKAY;
2733  }
2734 
2735  /* calculate upper bound for cover size */
2736  maxcoversize = nvars*heurdata->maxcoversizevars;
2737  if( heurdata->maxcoversizeconss < SCIP_REAL_MAX )
2738  {
2739  SCIP_Real maxcoversizeconss;
2740  maxcoversizeconss = heurdata->maxcoversizeconss * nnlconss / ((SCIP_Real) SCIPgetNConss(scip));
2741  maxcoversize = MIN(maxcoversize, maxcoversizeconss);
2742  }
2743 
2744  /* create covering problem */
2745  success = FALSE;
2746  SCIP_CALL( SCIPcreate(&coveringscip) );
2747  SCIP_CALL( SCIPincludeDefaultPlugins(coveringscip) );
2748  SCIP_CALL( SCIPallocBufferArray(scip, &coveringvars, nvars) );
2749  SCIP_CALL( createCoveringProblem(scip, coveringscip, coveringvars, heurdata->globalbounds, heurdata->onlyconvexify,
2750  heurdata->coverbd, heurdata->coveringobj, &success) );
2751 
2752  if( !success )
2753  {
2754  SCIPdebugMessage("creating covering problem failed, terminating\n");
2755  goto TERMINATE;
2756  }
2757  else
2758  {
2759  SCIPdebugMessage("covering problem created successfully\n");
2760  }
2761 
2762  /* count number of unfixed covering variables */
2763  nunfixeds = 0;
2764  for( i = nvars-1; i >= 0; i-- )
2765  {
2766  if( SCIPisFeasEQ(coveringscip, SCIPvarGetLbGlobal(coveringvars[i]), 1.0) )
2767  nunfixeds++;
2768  }
2769 
2770  /* update time limit */
2771  SCIP_CALL( updateTimelimit(scip, clock, &timelimit) );
2772 
2773  if( timelimit <= MINTIMELEFT )
2774  {
2775  SCIPdebugMessage("time limit hit, terminating\n");
2776  goto TERMINATE;
2777  }
2778 
2779  /* update memory left */
2780  memorylimit -= SCIPgetMemUsed(coveringscip)/1048576.0;
2781  memorylimit -= SCIPgetMemExternEstim(coveringscip)/1048576.0;
2782 
2783  /* allocate memory for storing bound disjunction information along probing path */
2784  SCIP_CALL( SCIPallocBufferArray(scip, &bdvars, 2*nvars) );
2785  SCIP_CALL( SCIPallocBufferArray(scip, &bdtypes, 2*nvars) );
2786  SCIP_CALL( SCIPallocBufferArray(scip, &bdbounds, 2*nvars) );
2787  SCIP_CALL( SCIPallocBufferArray(scip, &oldbounds, 2*nvars) );
2788 
2789  /* initialize data for recovering loop */
2790  SCIP_CALL( SCIPallocBufferArray(scip, &cover, nvars) );
2791  SCIP_CALL( SCIPallocBufferArray(scip, &fixingvals, nvars) );
2792  ncovers = 0;
2793  success = FALSE;
2794  reusecover = FALSE;
2795 
2796  heurdata->nfixingalts = (int) strlen(heurdata->fixingalts);
2797  assert(heurdata->nfixingalts >= 1);
2798 
2799  /* recovering loop */
2800  while( (ncovers <= heurdata->maxrecovers || reusecover) && !success )
2801  {
2802  int lastfailed;
2803  int ndives;
2804  int nfixedints;
2805  int nfixedconts;
2806  int bdlen; /* current length of bound disjunction along the probing path */
2807 
2808  SCIP_Bool conflictcreated;
2809 
2810  SCIPdebugMessage("solving covering problem\n\n");
2811  success = FALSE;
2812  bdlen = 0;
2813  conflictcreated = FALSE;
2814 
2815  /* solve covering problem */
2816  if( !reusecover )
2817  {
2818  SCIP_CALL( solveCoveringProblem(coveringscip, nvars, coveringvars, &coversize, cover,
2819  timelimit, memorylimit + (SCIPgetMemExternEstim(coveringscip)+SCIPgetMemUsed(coveringscip))/1048576.0, maxcoversize, &success) );
2820 
2821  SCIPstatistic(
2822  if( ncovers == 0 && success )
2823  SCIPstatisticPrintf("UCstats coversize abs: %6d rel: %9.6f\n", coversize, 100.0*coversize /(SCIP_Real)nvars);
2824  );
2825 
2826  assert(coversize >= 0);
2827  assert(coversize <= nvars);
2828  ncovers++;
2829 
2830  /* free transformed covering problem immediately */
2831  SCIP_CALL( SCIPfreeTransform(coveringscip) );
2832 
2833  /* terminate if no feasible cover was found */
2834  if( !success )
2835  {
2836  SCIPdebugMessage("no feasible cover found in covering problem %d, terminating\n", ncovers);
2837  goto TERMINATE;
2838  }
2839 
2840  /* terminate, if cover is empty or too large */
2841  if( coversize == 0 || coversize > maxcoversize )
2842  {
2843  SCIPdebugMessage("terminating due to coversize=%d\n", coversize);
2844  goto TERMINATE;
2845  }
2846 
2847  /* terminate, if cover too large for the ratio of nonlinear constraints */
2848  if( heurdata->maxcoversizeconss < SCIP_REAL_MAX && coversize > heurdata->maxcoversizeconss * nnlconss / (SCIP_Real) SCIPgetNConss(scip) )
2849  {
2850  SCIPdebugMessage("terminating due to coversize=%d\n", coversize);
2851  goto TERMINATE;
2852  }
2853  }
2854 
2855  /* data setup */
2856  ndives = 0;
2857  nfixedints = 0;
2858  nfixedconts = 0;
2859  success = FALSE;
2860  lastfailed = reusecover ? MAX(1, coversize-1) : coversize;
2861 
2862  /* round-fix-propagate-analyze-backtrack-reorder loop */
2863  while( ndives <= heurdata->maxreorders && !success )
2864  {
2865  SCIP_Bool reordered;
2866  SCIP_Bool infeas;
2867 
2868  /* compute fixing order */
2869  SCIP_CALL( computeFixingOrder(scip, heurdata, nvars, vars, coversize, cover, lastfailed, &reordered) );
2870  reordered = reordered || ndives == 0;
2871  SCIPdebugMessage("%sordering variables in cover %s\n", ndives == 0 ? "" : "re", reordered ? "" : "failed");
2872 
2873  /* stop if order has not changed */
2874  if( !reordered )
2875  break;
2876 
2877  infeas = FALSE;
2878  SCIP_CALL( fixAndPropagate(scip, heurdata, cover, coversize, fixingvals, &bdlen, bdvars, bdtypes, bdbounds, oldbounds,
2879  &nfixedints, &nfixedconts, &lastfailed, &infeas) );
2880  ndives++;
2881  success = !infeas;
2882  }
2883 
2884  /* update time limit */
2885  SCIPdebugMessage("%d dive%s of fix-and-propagate for cover %d took %.1f seconds\n", ndives, ndives > 1 ? "s" : "", ncovers, SCIPgetClockTime(scip, clock));
2886  SCIP_CALL( updateTimelimit(scip, clock, &timelimit) );
2887 
2888  if( timelimit <= MINTIMELEFT )
2889  {
2890  SCIPdebugMessage("time limit hit, terminating\n");
2891  goto TERMINATE;
2892  }
2893 
2894  /* no feasible fixing could be found for the current cover */
2895  if( !success )
2896  {
2897  SCIPdebugMessage("no feasible fixing values found for cover %d\n", ncovers);
2898  }
2899  else
2900  {
2901  SCIP_SOL* sol;
2902  SCIP_Longint nsubnodes;
2903  SCIP_Bool validsolved;
2904 
2905  SCIPdebugMessage("heuristic successfully fixed %d variables (%d integral, %d continuous) during probing\n",
2906  nfixedints+nfixedconts, nfixedints, nfixedconts); /*lint !e771*/
2907 
2908  /* solve sub-CIP and pass feasible solutions to original problem */
2909  success = FALSE;
2910  validsolved = FALSE;
2911  sol = NULL;
2912  nsubnodes = 0;
2913 
2914  SCIP_CALL( solveSubproblem(scip, heur, coversize, cover, fixingvals,
2915  timelimit, memorylimit, heurdata->maxnodes, nstallnodes, &validsolved, &sol, &nsubnodes) );
2916 
2917  /* update number of sub-CIP nodes used by heuristic so far */
2918  heurdata->nusednodes += nsubnodes;
2919 
2920  /* if the subproblem was constructed from a valid copy and solved, try to forbid the assignment of fixing
2921  * values to variables in the cover
2922  */
2923  if( validsolved )
2924  {
2925  SCIP_Real maxvarsfac;
2926  SCIP_Bool useconf;
2927  int minmaxvars;
2928 
2929  SCIP_CALL( SCIPgetIntParam(scip, "conflict/minmaxvars", &minmaxvars) );
2930  SCIP_CALL( SCIPgetRealParam(scip, "conflict/maxvarsfac", &maxvarsfac) );
2931 
2932  useconf = bdlen > 0 && (bdlen <= minmaxvars || bdlen < maxvarsfac*nvars);
2933 
2934  if( useconf )
2935  {
2936  /* even if we had reset the global bounds at start of probing, the constraint might be only locally valid due to local constraints/cuts */
2937  SCIP_CALL( createConflict(scip, bdlen, bdvars, bdtypes, bdbounds, SCIPgetDepth(scip) > 0, TRUE, TRUE, &success) );
2938  conflictcreated = success;
2939  }
2940 
2941  SCIPdebugMessage("subproblem solved (%s), forbidding assignment in original problem %s, %sconflict length=%d\n",
2942  sol == NULL ? "infeasible" : "optimal",
2943  success ? "successful" : "failed", useconf ? "" : "skipped due to ", bdlen);
2944  }
2945 
2946  /* heuristic succeeded */
2947  success = (sol != NULL);
2948  if( success )
2949  {
2950  *result = SCIP_FOUNDSOL;
2951  success = TRUE;
2952 
2953  /* update time limit */
2954  SCIP_CALL( updateTimelimit(scip, clock, &timelimit) );
2955 
2956  /* call NLP local search heuristic unless it has failed too often */
2957  if( heurdata->postnlp && heurdata->npostnlpfails < MAXPOSTNLPFAILS )
2958  {
2959  if( nfixedconts == 0 && validsolved )
2960  {
2961  SCIPdebugMessage("subproblem solved to optimality while all covering variables are integral, hence skipping NLP local search\n");
2962  }
2963  else if( timelimit <= MINTIMELEFT )
2964  {
2965  SCIPdebugMessage("time limit hit, skipping NLP local search\n");
2966  }
2967  else if( heurdata->nlpheur == NULL )
2968  {
2969  SCIPdebugMessage("NLP heuristic not found, skipping NLP local search\n");
2970  }
2971  else
2972  {
2973  SCIP_RESULT nlpresult;
2974 
2975  SCIP_CALL( SCIPapplyHeurSubNlp(scip, heurdata->nlpheur, &nlpresult, sol, -1LL, timelimit, heurdata->minimprove, NULL) );
2976  SCIPdebugMessage("NLP local search %s\n", nlpresult == SCIP_FOUNDSOL ? "successful" : "failed");
2977 
2978  if( nlpresult == SCIP_FOUNDSOL )
2979  heurdata->npostnlpfails = 0;
2980  else
2981  heurdata->npostnlpfails++;
2982  }
2983  }
2984 
2985  /* free solution */
2986  SCIP_CALL( SCIPfreeSol(scip, &sol) );
2987  }
2988  }
2989 
2990  /* heuristic failed but we have another recovering try, hence we forbid the current cover in the covering problem */
2991  if( !success && ncovers <= heurdata->maxrecovers )
2992  {
2993  SCIP_Bool infeas;
2994  int diversification;
2995 
2996  /* compute minimal number of unfixed covering variables (in the cover) which have to change their value */
2997  diversification = (int) SCIPfeasCeil(scip, (heurdata->recoverdiv) * (SCIP_Real) nunfixeds);
2998  diversification = MAX(diversification, 1);
2999 
3000  /* forbid unsuccessful cover globally in covering problem */
3001  SCIP_CALL( forbidCover(coveringscip, nvars, coveringvars, coversize, cover, diversification, &success, &infeas) );
3002 
3003  if( infeas )
3004  {
3005  SCIPdebugMessage("recovering problem infeasible (diversification=%d), terminating\n", diversification);
3006  goto TERMINATE;
3007  }
3008  else if( !success )
3009  {
3010  SCIPdebugMessage("failed to forbid current cover in the covering problem, terminating\n");
3011  goto TERMINATE;
3012  }
3013  else
3014  {
3015  SCIPdebugMessage("added constraint to the covering problem in order to forbid current cover\n");
3016  success = FALSE;
3017  }
3018  }
3019 
3020  /* try to re-use the same cover at most once */
3021  if( heurdata->reusecover && !reusecover && conflictcreated )
3022  reusecover = TRUE;
3023  else
3024  reusecover = FALSE;
3025  }
3026 
3027  TERMINATE:
3028  if( *result != SCIP_FOUNDSOL && *result != SCIP_DELAYED )
3029  {
3030  SCIPdebugMessage("heuristic terminating unsuccessfully\n");
3031  }
3032 
3033  /* we must remain in NLP diving mode until here to be able to retrieve NLP solution values easily */
3034  /* assert((SCIPisNLPConstructed(scip) == FALSE && heurdata->nlpsolved == FALSE) ||
3035  * (SCIPisNLPConstructed(scip) == TRUE && heurdata->nlpsolved == SCIPnlpIsDiving(SCIPgetNLP(scip))));
3036  */
3037  if( heurdata->nlpsolved )
3038  {
3039  SCIP_CALL( SCIPendDiveNLP(scip) );
3040  }
3041 
3042  /* free arrays for storing the cover */
3043  SCIPfreeBufferArrayNull(scip, &fixingvals);
3044  SCIPfreeBufferArrayNull(scip, &cover);
3045 
3046  /* free arrays for storing bound disjunction information along probing path */
3047  SCIPfreeBufferArrayNull(scip, &oldbounds);
3048  SCIPfreeBufferArrayNull(scip, &bdbounds);
3049  SCIPfreeBufferArrayNull(scip, &bdtypes);
3050  SCIPfreeBufferArrayNull(scip, &bdvars);
3051 
3052  /* free covering problem */
3053  for( i = nvars-1; i >= 0; i-- )
3054  {
3055  SCIP_CALL( SCIPreleaseVar(coveringscip, &coveringvars[i]) );
3056  }
3057  SCIPfreeBufferArray(scip, &coveringvars);
3058  SCIP_CALL( SCIPfree(&coveringscip) );
3059 
3060  /* free clock */
3061  SCIP_CALL( SCIPfreeClock(scip, &clock) );
3062 
3063  return SCIP_OKAY;
3064 }
3065 
3066 
3067 /*
3068  * Callback methods of primal heuristic
3069  */
3070 
3071 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
3072 static
3073 SCIP_DECL_HEURCOPY(heurCopyUndercover)
3074 { /*lint --e{715}*/
3075  assert(scip != NULL);
3076  assert(heur != NULL);
3077  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
3078 
3079  /* call inclusion method of primal heuristic */
3081 
3082  return SCIP_OKAY;
3083 }
3084 
3085 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
3086 static
3087 SCIP_DECL_HEURFREE(heurFreeUndercover)
3088 { /*lint --e{715}*/
3089  SCIP_HEURDATA* heurdata;
3090 
3091  assert(scip != NULL);
3092  assert(heur != NULL);
3093 
3094  /* get heuristic data */
3095  heurdata = SCIPheurGetData(heur);
3096  assert(heurdata != NULL);
3097 
3098  /* free heuristic data */
3099  SCIPfreeMemory(scip, &heurdata);
3100  SCIPheurSetData(heur, NULL);
3101 
3102  return SCIP_OKAY;
3103 }
3104 
3105 
3106 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
3107 static
3108 SCIP_DECL_HEURINITSOL(heurInitsolUndercover)
3109 { /*lint --e{715}*/
3110  SCIP_HEURDATA* heurdata;
3111  int h;
3112 
3113  assert(heur != NULL);
3114  assert(scip != NULL);
3115 
3116  /* get heuristic's data */
3117  heurdata = SCIPheurGetData(heur);
3118  assert(heurdata != NULL);
3119 
3120  /* initialize counters to zero */
3121  heurdata->nusednodes = 0;
3122  heurdata->npostnlpfails = 0;
3123  heurdata->nnlpfails = 0;
3124 
3125  /* if the heuristic is called at the root node, we may want to be called directly after the initial root LP solve */
3126  if( heurdata->beforecuts && SCIPheurGetFreqofs(heur) == 0 )
3128 
3129  /* find nonlinear constraint handlers */
3130  SCIP_CALL( SCIPallocMemoryArray(scip, &heurdata->nlconshdlrs, 7) );/*lint !e506*/
3131  h = 0;
3132 
3133  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "and");
3134  if( heurdata->nlconshdlrs[h] != NULL )
3135  h++;
3136 
3137  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "quadratic");
3138  if( heurdata->nlconshdlrs[h] != NULL )
3139  h++;
3140 
3141  if( heurdata->coverbd )
3142  {
3143  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "bounddisjunction");
3144  if( heurdata->nlconshdlrs[h] != NULL )
3145  h++;
3146  }
3147 
3148  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "indicator");
3149  if( heurdata->nlconshdlrs[h] != NULL )
3150  h++;
3151 
3152  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "soc");
3153  if( heurdata->nlconshdlrs[h] != NULL )
3154  h++;
3155 
3156  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "nonlinear");
3157  if( heurdata->nlconshdlrs[h] != NULL )
3158  h++;
3159 
3160  heurdata->nlconshdlrs[h] = SCIPfindConshdlr(scip, "abspower");
3161  if( heurdata->nlconshdlrs[h] != NULL )
3162  h++;
3163 
3164  heurdata->nnlconshdlrs = h;
3165 
3166  /* find NLP local search heuristic */
3167  heurdata->nlpheur = SCIPfindHeur(scip, "subnlp");
3168 
3169  /* add global linear constraints to NLP relaxation */
3170  if( SCIPisNLPConstructed(scip) && heurdata->nlpheur != NULL )
3171  {
3172  SCIP_CALL( SCIPaddLinearConsToNlpHeurSubNlp(scip, heurdata->nlpheur, TRUE, TRUE) );
3173  }
3174 
3175  return SCIP_OKAY;
3176 }
3177 
3178 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
3179 static
3180 SCIP_DECL_HEUREXITSOL(heurExitsolUndercover)
3181 {
3182  SCIP_HEURDATA* heurdata;
3183 
3184  assert(heur != NULL);
3185  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
3186 
3187  /* get heuristic's data */
3188  heurdata = SCIPheurGetData(heur);
3189  assert(heurdata != NULL);
3190 
3191  /* free array of nonlinear constraint handlers */
3192  SCIPfreeMemoryArray(scip, &heurdata->nlconshdlrs);
3193 
3194  /* reset timing, if it was changed temporary (at the root node) */
3196 
3197  return SCIP_OKAY;
3198 }
3199 
3200 /** execution method of primal heuristic */
3201 static
3202 SCIP_DECL_HEUREXEC(heurExecUndercover)
3203 { /*lint --e{715}*/
3204  SCIP_HEURDATA* heurdata; /* heuristic data */
3205  SCIP_Real timelimit; /* time limit for the subproblem */
3206  SCIP_Real memorylimit; /* memory limit for the subproblem */
3207  SCIP_Longint nstallnodes; /* number of stalling nodes for the subproblem */
3208  SCIP_Bool run;
3209 
3210  int h;
3211 
3212  assert(heur != NULL);
3213  assert(scip != NULL);
3214  assert(result != NULL);
3215 
3216  *result = SCIP_DIDNOTRUN;
3217 
3218  /* do not call heuristic of node was already detected to be infeasible */
3219  if( nodeinfeasible )
3220  return SCIP_OKAY;
3221 
3222  /* get heuristic's data */
3223  heurdata = SCIPheurGetData(heur);
3224  assert(heurdata != NULL);
3225 
3226  /* only call heuristic once at the root */
3227  if( SCIPgetDepth(scip) == 0 && SCIPheurGetNCalls(heur) > 0 )
3228  return SCIP_OKAY;
3229 
3230  /* if we want to use NLP fixing values exclusively and no NLP solver is available, we cannot run */
3231  if( strcmp(heurdata->fixingalts, "n") == 0 && SCIPgetNNlpis(scip) == 0 )
3232  {
3233  SCIPdebugMessage("skipping undercover heuristic: want to use NLP fixing values exclusively, but no NLP solver available\n");
3234  return SCIP_OKAY;
3235  }
3236 
3237  /* calculate stallnode limit */
3238  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
3239 
3240  /* reward heuristic if it succeeded often */
3241  nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur) + 1.0)/(SCIPheurGetNCalls(heur) + 1.0));
3242  nstallnodes -= SUBMIPSETUPCOSTS * SCIPheurGetNCalls(heur); /* account for the setup costs of the sub-CIP */
3243  nstallnodes += heurdata->nodesofs;
3244 
3245  /* determine the node limit for the current process */
3246  nstallnodes -= heurdata->nusednodes;
3247  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
3248  nstallnodes = MAX(nstallnodes, 1);
3249 
3250  /* only call heuristics if we have enough nodes left to call sub-CIP solving */
3251  if( nstallnodes < heurdata->minnodes )
3252  {
3253  SCIPdebugMessage("skipping undercover heuristic: nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
3254  return SCIP_OKAY;
3255  }
3256 
3257  /* only call heuristics if we have enough time left */
3258  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
3259  if( !SCIPisInfinity(scip, timelimit) )
3260  timelimit -= SCIPgetSolvingTime(scip);
3261  if( timelimit <= 2*MINTIMELEFT )
3262  {
3263  SCIPdebugMessage("skipping undercover heuristic: time left=%g\n", timelimit);
3264  return SCIP_OKAY;
3265  }
3266 
3267  /* only call heuristics if we have enough memory left */
3268  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
3269  if( !SCIPisInfinity(scip, memorylimit) )
3270  {
3271  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
3272  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
3273  }
3274 
3275  if( memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
3276  {
3277  SCIPdebugMessage("skipping undercover heuristic: too little memory\n");
3278  return SCIP_OKAY;
3279  }
3280 
3281  /* only call heuristic if nonlinear constraints are present */
3282  run = FALSE;
3283  for( h = heurdata->nnlconshdlrs-1; h >= 0 && !run; h-- )
3284  {
3285  run = (SCIPconshdlrGetNActiveConss(heurdata->nlconshdlrs[h]) > 0);
3286  }
3287 
3288  /* go through all nlrows and check for general nonlinearities */
3289  if( SCIPisNLPConstructed(scip) )
3290  {
3291  SCIP_NLROW** nlrows;
3292  int nnlrows;
3293  int i;
3294 
3295  /* get nlrows */
3296  nnlrows = SCIPgetNNLPNlRows(scip);
3297  nlrows = SCIPgetNLPNlRows(scip);
3298 
3299  /* check for an nlrow with nontrivial expression tree or quadratic terms; start from 0 since we expect the linear
3300  * nlrows at the end */
3301  for( i = nnlrows-1; i >= 0 && !run; i-- )
3302  {
3303  assert(nlrows[i] != NULL);
3304  run = SCIPnlrowGetExprtree(nlrows[i]) != NULL && SCIPexprtreeGetNVars(SCIPnlrowGetExprtree(nlrows[i])) > 0;
3305  run = run || SCIPnlrowGetNQuadVars(nlrows[i]) > 0;
3306  }
3307  }
3308 
3309  if( !run )
3310  {
3311  SCIPdebugMessage("skipping undercover heuristic: no nonlinear constraints found\n");
3312  return SCIP_OKAY;
3313  }
3314 
3315  /* only call heuristics if solving has not stopped yet */
3316  if( SCIPisStopped(scip) )
3317  return SCIP_OKAY;
3318 
3319  /* reset timing, if it was changed temporary (at the root node) */
3320  if( heurtiming != HEUR_TIMING )
3322 
3323  /* call heuristic */
3324  *result = SCIP_DIDNOTFIND;
3325  SCIPdebugMessage("calling undercover heuristic for <%s> at depth %d\n", SCIPgetProbName(scip), SCIPgetDepth(scip));
3326 
3327  SCIP_CALL( SCIPapplyUndercover(scip, heur, result, timelimit, memorylimit, nstallnodes) );
3328 
3329  return SCIP_OKAY;
3330 }
3331 
3332 
3333 /*
3334  * primal heuristic specific interface methods
3335  */
3336 
3337 /** creates the undercover primal heuristic and includes it in SCIP */
3339  SCIP* scip /**< SCIP data structure */
3340  )
3341 {
3342  SCIP_HEURDATA* heurdata;
3343  SCIP_HEUR* heur;
3344 
3345  /* create undercover primal heuristic data */
3346  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
3347 
3348  /* always use local bounds */
3349  heurdata->globalbounds = FALSE;
3350 
3351  /* include primal heuristic */
3352  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
3354  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecUndercover, heurdata) );
3355 
3356  assert(heur != NULL);
3357 
3358  /* set non-NULL pointers to callback methods */
3359  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyUndercover) );
3360  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeUndercover) );
3361  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolUndercover) );
3362  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolUndercover) );
3363 
3364  /* add string parameters */
3365  heurdata->fixingalts = NULL;
3366  SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/fixingalts",
3367  "prioritized sequence of fixing values used ('l'p relaxation, 'n'lp relaxation, 'i'ncumbent solution)",
3368  &heurdata->fixingalts, FALSE, DEFAULT_FIXINGALTS, NULL, NULL) );
3369 
3370  /* add longint parameters */
3371  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
3372  "maximum number of nodes to regard in the subproblem",
3373  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3374 
3375  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
3376  "minimum number of nodes required to start the subproblem",
3377  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3378 
3379  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
3380  "number of nodes added to the contingent of the total nodes",
3381  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3382 
3383  /* add real parameters */
3384  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/conflictweight",
3385  "weight for conflict score in fixing order",
3386  &heurdata->conflictweight, TRUE, DEFAULT_CONFLICTWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
3387 
3388  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/cutoffweight",
3389  "weight for cutoff score in fixing order",
3390  &heurdata->cutoffweight, TRUE, DEFAULT_CUTOFFWEIGHT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
3391 
3392  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/inferenceweight",
3393  "weight for inference score in fixing order",
3394  &heurdata->inferenceweight, TRUE, DEFAULT_INFERENCEWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
3395 
3396  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxcoversizevars",
3397  "maximum coversize (as fraction of total number of variables)",
3398  &heurdata->maxcoversizevars, TRUE, DEFAULT_MAXCOVERSIZEVARS, 0.0, 1.0, NULL, NULL) );
3399 
3400  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxcoversizeconss",
3401  "maximum coversize maximum coversize (as ratio to the percentage of non-affected constraints)",
3402  &heurdata->maxcoversizeconss, TRUE, DEFAULT_MAXCOVERSIZECONSS, 0.0, SCIP_REAL_MAX, NULL, NULL) );
3403 
3404  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/mincoveredrel",
3405  "minimum percentage of nonlinear constraints in the original problem",
3406  &heurdata->mincoveredrel, TRUE, DEFAULT_MINCOVEREDREL, 0.0, 1.0, NULL, NULL) );
3407 
3408  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
3409  "factor by which the heuristic should at least improve the incumbent",
3410  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, -1.0, 1.0, NULL, NULL) );
3411 
3412  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
3413  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
3414  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
3415 
3416  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/recoverdiv",
3417  "fraction of covering variables in the last cover which need to change their value when recovering",
3418  &heurdata->recoverdiv, TRUE, DEFAULT_RECOVERDIV, 0.0, 1.0, NULL, NULL) );
3419 
3420  /* add int parameters */
3421  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/mincoveredabs",
3422  "minimum number of nonlinear constraints in the original problem",
3423  &heurdata->mincoveredabs, TRUE, DEFAULT_MINCOVEREDABS, 0, INT_MAX, NULL, NULL) );
3424 
3425  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxbacktracks",
3426  "maximum number of backtracks in fix-and-propagate",
3427  &heurdata->maxbacktracks, TRUE, DEFAULT_MAXBACKTRACKS, 0, INT_MAX, NULL, NULL) );
3428 
3429  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxrecovers",
3430  "maximum number of recoverings",
3431  &heurdata->maxrecovers, TRUE, DEFAULT_MAXRECOVERS, 0, INT_MAX, NULL, NULL) );
3432 
3433  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxreorders",
3434  "maximum number of reorderings of the fixing order",
3435  &heurdata->maxreorders, TRUE, DEFAULT_MAXREORDERS, 0, INT_MAX, NULL, NULL) );
3436 
3437  /* add char parameters */
3438  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/coveringobj",
3439  "objective function of the covering problem (influenced nonlinear 'c'onstraints/'t'erms, 'd'omain size, 'l'ocks, 'm'in of up/down locks, 'u'nit penalties)",
3440  &heurdata->coveringobj, TRUE, DEFAULT_COVERINGOBJ, COVERINGOBJS, NULL, NULL) );
3441 
3442  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/fixingorder",
3443  "order in which variables should be fixed (increasing 'C'onflict score, decreasing 'c'onflict score, increasing 'V'ariable index, decreasing 'v'ariable index",
3444  &heurdata->fixingorder, TRUE, DEFAULT_FIXINGORDER, FIXINGORDERS, NULL, NULL) );
3445 
3446  /* add bool parameters */
3447  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/beforecuts",
3448  "should the heuristic be called at root node before cut separation?",
3449  &heurdata->beforecuts, TRUE, DEFAULT_BEFORECUTS, NULL, NULL) );
3450 
3451  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/fixintfirst",
3452  "should integer variables in the cover be fixed first?",
3453  &heurdata->fixintfirst, TRUE, DEFAULT_FIXINTFIRST, NULL, NULL) );
3454 
3455  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/locksrounding",
3456  "shall LP values for integer vars be rounded according to locks?",
3457  &heurdata->locksrounding, TRUE, DEFAULT_LOCKSROUNDING, NULL, NULL) );
3458 
3459  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/onlyconvexify",
3460  "should we only fix variables in order to obtain a convex problem?",
3461  &heurdata->onlyconvexify, FALSE, DEFAULT_ONLYCONVEXIFY, NULL, NULL) );
3462 
3463  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/postnlp",
3464  "should the NLP heuristic be called to polish a feasible solution?",
3465  &heurdata->postnlp, FALSE, DEFAULT_POSTNLP, NULL, NULL) );
3466 
3467  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/coverbd",
3468  "should bounddisjunction constraints be covered (or just copied)?",
3469  &heurdata->coverbd, TRUE, DEFAULT_COVERBD, NULL, NULL) );
3470 
3471  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
3472  "should all active cuts from cutpool be copied to constraints in subproblem?",
3473  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
3474 
3475  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/reusecover",
3476  "shall the cover be reused if a conflict was added after an infeasible subproblem?",
3477  &heurdata->reusecover, TRUE, DEFAULT_REUSECOVER, NULL, NULL) );
3478 
3479  return SCIP_OKAY;
3480 }
3481 
3482 
3483 /** computes a minimal set of covering variables */
3485  SCIP* scip, /**< SCIP data structure */
3486  int* coversize, /**< buffer for the size of the computed cover */
3487  SCIP_VAR** cover, /**< pointer to store the variables (of the original SCIP) in the computed cover
3488  * (should be ready to hold SCIPgetNVars(scip) entries) */
3489  SCIP_Real timelimit, /**< time limit */
3490  SCIP_Real memorylimit, /**< memory limit */
3491  SCIP_Real objlimit, /**< objective limit: upper bound on coversize */
3492  SCIP_Bool globalbounds, /**< should global bounds on variables be used instead of local bounds at focus node? */
3493  SCIP_Bool onlyconvexify, /**< should we only fix/dom.red. variables creating nonconvexity? */
3494  SCIP_Bool coverbd, /**< should bounddisjunction constraints be covered (or just copied)? */
3495  char coveringobj, /**< objective function of the covering problem ('b'ranching status,
3496  * influenced nonlinear 'c'onstraints/'t'erms, 'd'omain size, 'l'ocks,
3497  * 'm'in of up/down locks, 'u'nit penalties, constraint 'v'iolation) */
3498  SCIP_Bool* success /**< feasible cover found? */
3499  )
3500 {
3501  SCIP* coveringscip; /* SCIP instance for covering problem */
3502  SCIP_VAR** coveringvars; /* covering variables */
3503  SCIP_VAR** vars; /* original variables */
3504  int* coverinds; /* indices of variables in the cover */
3505  int nvars; /* number of original variables */
3506  int i;
3507 
3508  assert(scip != NULL);
3509  assert(coversize != NULL);
3510  assert(success != NULL);
3511 
3512  *success = FALSE;
3513 
3514  /* allocate memory for variables of the covering problem */
3515  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL ) );
3516  SCIP_CALL( SCIPallocBufferArray(scip, &coveringvars, nvars) );
3517  SCIP_CALL( SCIPallocBufferArray(scip, &coverinds, nvars) );
3518 
3519  /* create covering problem */
3520  SCIP_CALL( SCIPcreate(&coveringscip) );
3521  SCIP_CALL( SCIPincludeDefaultPlugins(coveringscip) );
3522  SCIP_CALL( createCoveringProblem(scip, coveringscip, coveringvars, globalbounds, onlyconvexify, coverbd, coveringobj, success) );
3523 
3524  if( *success )
3525  {
3526  /* solve covering problem */
3527  SCIPdebugMessage("solving covering problem\n\n");
3528 
3529  SCIP_CALL( solveCoveringProblem(coveringscip, nvars, coveringvars, coversize, coverinds,
3530  timelimit, memorylimit + (SCIPgetMemExternEstim(coveringscip)+SCIPgetMemUsed(coveringscip))/1048576.0, objlimit, success) );
3531 
3532  if( *success )
3533  {
3534  assert(*coversize >= 0);
3535  assert(*coversize <= nvars);
3536 
3537  /* return original variables in the cover */
3538  for( i = *coversize-1; i >= 0; i-- )
3539  {
3540  assert(coverinds[i] >= 0);
3541  assert(coverinds[i] < nvars);
3542  cover[i] = vars[coverinds[i]];
3543  }
3544  }
3545  }
3546  else
3547  {
3548  SCIPdebugMessage("failure: covering problem could not be created\n");
3549  }
3550 
3551  /* free covering problem */
3552  for( i = nvars-1; i >= 0; i-- )
3553  {
3554  SCIP_CALL( SCIPreleaseVar(coveringscip, &coveringvars[i]) );
3555  }
3556  SCIP_CALL( SCIPfree(&coveringscip) );
3557  SCIPfreeBufferArray(scip, &coverinds);
3558  SCIPfreeBufferArray(scip, &coveringvars);
3559 
3560  return SCIP_OKAY;
3561 }
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:7361
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:22777
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPexprintCompile(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree)
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:69
SCIP_RETCODE SCIPsetNLPIntPar(SCIP *scip, SCIP_NLPPARAM type, int ival)
Definition: scip.c:28969
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16883
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40767
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
static SCIP_RETCODE processNlRow(SCIP *scip, SCIP_NLROW *nlrow, SCIP_EXPRINT *exprint, struct HessianData *hessiandata, SCIP *coveringscip, int nvars, SCIP_VAR **coveringvars, int *termcounter, int *conscounter, SCIP_Bool *consmarker, SCIP_Bool globalbounds, SCIP_Bool onlyconvexify, SCIP_Bool *success)
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:40329
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
#define HEUR_TIMING
int SCIPgetNVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19748
#define DEFAULT_FIXINGORDER
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:908
static SCIP_Bool termIsConvex(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool sign)
methods to interpret (evaluate) an expression tree "fast"
#define HEUR_DISPCHAR
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
int SCIPnlrowGetNQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3312
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
static SCIP_RETCODE getFixingValue(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real *val, char fixalt, SCIP_Bool *success, int bdlen, SCIP_VAR **bdvars, SCIP_BOUNDTYPE *bdtypes, SCIP_Real *oldbounds)
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
static SCIP_RETCODE computeFixingOrder(SCIP *scip, SCIP_HEURDATA *heurdata, int nvars, SCIP_VAR **vars, int coversize, int *cover, int lastfailed, SCIP_Bool *success)
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7297
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:32250
#define DEFAULT_MAXRECOVERS
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:10378
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
#define DEFAULT_MAXREORDERS
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:15737
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
#define SCIP_MAXSTRLEN
Definition: def.h:201
#define DEFAULT_MINCOVEREDABS
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
#define DEFAULT_COPYCUTS
#define DEFAULT_RECOVERDIV
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4258
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:42032
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40801
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, unsigned int timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:7252
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40950
static SCIP_RETCODE solveCoveringProblem(SCIP *coveringscip, int ncoveringvars, SCIP_VAR **coveringvars, int *coversize, int *cover, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Real objlimit, SCIP_Bool *success)
static SCIP_RETCODE roundFixingValue(SCIP *scip, SCIP_Real *val, SCIP_VAR *var, SCIP_Bool locksrounding)
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSetpack(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:8948
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4322
#define DEFAULT_MAXCOVERSIZECONSS
SCIP_RETCODE SCIPunfixParam(SCIP *scip, const char *name)
Definition: scip.c:3875
Undercover primal heuristic for MINLPs.
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32552
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:7393
#define FALSE
Definition: def.h:56
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:41009
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
#define DEFAULT_MINIMPROVE
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4046
SCIP_EXPRINTCAPABILITY SCIPexprintGetCapability(void)
#define MAXPOSTNLPFAILS
static SCIP_DECL_HEUREXITSOL(heurExitsolUndercover)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:28790
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4109
#define DEFAULT_INFERENCEWEIGHT
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:19590
#define DEFAULT_MINCOVEREDREL
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
int SCIPgetNLhsVarsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5240
#define DEFAULT_NODESOFS
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
Definition: scip.c:15373
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
SCIP_RETCODE SCIPcomputeCoverUndercover(SCIP *scip, int *coversize, SCIP_VAR **cover, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Real objlimit, SCIP_Bool globalbounds, SCIP_Bool onlyconvexify, SCIP_Bool coverbd, char coveringobj, SCIP_Bool *success)
SCIP_Real * SCIPgetLhsCoefsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5266
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
#define DEFAULT_FIXINTFIRST
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define COVERINGOBJS
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
#define SCIP_LONGINT_MAX
Definition: def.h:113
#define DEFAULT_BEFORECUTS
static SCIP_DECL_HEURCOPY(heurCopyUndercover)
#define DEFAULT_CONFLICTWEIGHT
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
static SCIP_RETCODE createConflict(SCIP *scip, int bdlen, SCIP_VAR **bdvars, SCIP_BOUNDTYPE *bdtypes, SCIP_Real *bdbounds, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool *success)
SCIP_RETCODE SCIPexprintCreate(BMS_BLKMEM *blkmem, SCIP_EXPRINT **exprint)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:42255
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:38393
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40784
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2883
#define HEUR_NAME
SCIP_RETCODE SCIPendDiveNLP(SCIP *scip)
Definition: scip.c:29214
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:35668
#define DEFAULT_MINNODES
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:11138
int SCIPgetNNLPNlRows(SCIP *scip)
Definition: scip.c:28636
#define DEFAULT_ONLYCONVEXIFY
#define DEFAULT_MAXNODES
SCIP_Real SCIPgetRhsCoefSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5318
SCIP_Real coef
Definition: type_expr.h:102
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:17233
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_VAR ** SCIPgetLhsVarsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5253
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:11736
SCIP_VAR * SCIPgetRhsVarSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5305
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5075
SCIP_RETCODE SCIPcopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:3254
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:20049
#define SCIPerrorMessage
Definition: pub_message.h:45
#define HEUR_USESSUBSCIP
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip.c:2260
static SCIP_DECL_HEUREXEC(heurExecUndercover)
#define FIXINGORDERS
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:32223
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:28407
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41598
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:17163
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
SCIP_VAR ** SCIPgetVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
SCIPInterval sign(const SCIPInterval &x)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16598
#define DEFAULT_NODESQUOT
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
#define SUBMIPSETUPCOSTS
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4457
#define DEFAULT_POSTNLP
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5100
SCIP_Bool SCIPisConcaveQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8452
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9019
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:35020
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
Definition: heur.c:1187
#define SCIPstatisticPrintf
Definition: pub_message.h:107
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:35717
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2330
#define DEFAULT_CUTOFFWEIGHT
int SCIPgetDepthLimit(SCIP *scip)
Definition: scip.c:38190
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20598
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
SCIP_RETCODE SCIPincludeHeurUndercover(SCIP *scip)
static SCIP_Bool varIsFixed(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_Bool global)
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3684
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:38534
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16873
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3373
SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
Definition: scip.c:28614
#define SCIP_EXPRINTCAPABILITY_HESSIAN
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17444
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
static void incCounters(int *termcounter, int *conscounter, SCIP_Bool *consmarker, int idx)
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4001
#define DEFAULT_LOCKSROUNDING
SCIP_RETCODE SCIPlinkCurrentSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34753
SCIP_Real SCIPgetVarConflictScore(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23645
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:3709
static void calculateAlternatives(SCIP *scip, SCIP_VAR *var, SCIP_Real fixval, int *nalternatives, SCIP_Real *alternatives)
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:4382
#define HEUR_FREQ
static SCIP_RETCODE updateTimelimit(SCIP *scip, SCIP_CLOCK *clck, SCIP_Real *timelimit)
#define MAX(x, y)
Definition: tclique_def.h:75
int SCIPnlrowGetNQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3265
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:41396
SCIP_RETCODE SCIPgetNlRowQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
#define DEFAULT_COVERINGOBJ
SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_Longint itercontingent, SCIP_Real timelimit, SCIP_Real minimprove, SCIP_Longint *iterused)
Definition: heur_subnlp.c:1620
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:32153
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3363
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip.c:7377
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:32285
static SCIP_RETCODE performFixing(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_Bool *infeas, int *bdlen, SCIP_VAR **bdvars, SCIP_BOUNDTYPE *bdtypes, SCIP_Real *bdbounds, SCIP_Real *oldbounds)
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4431
#define SCIPstatistic(x)
Definition: pub_message.h:101
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
#define HEUR_DESC
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17431
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
#define SCIP_REAL_MIN
Definition: def.h:129
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14503
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
SCIP_RETCODE SCIPsetHeuristics(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4405
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1293
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
#define DEFAULT_MAXBACKTRACKS
#define DEFAULT_FIXINGALTS
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3275
#define MAXNLPFAILS
SCIP_RETCODE SCIPstartDiveNLP(SCIP *scip)
Definition: scip.c:29186
#define MINTIMELEFT
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3353
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:32352
static SCIP_RETCODE fixAndPropagate(SCIP *scip, SCIP_HEURDATA *heurdata, int *cover, int coversize, SCIP_Real *fixingvals, int *bdlen, SCIP_VAR **bdvars, SCIP_BOUNDTYPE *bdtypes, SCIP_Real *bdbounds, SCIP_Real *oldbounds, int *nfixedints, int *nfixedconts, int *lastfailed, SCIP_Bool *infeas)
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7313
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8436
static SCIP_Bool termIsConstant(SCIP *scip, SCIP_VAR *var, SCIP_Real coeff, SCIP_Bool global)
static SCIP_RETCODE solveSubproblem(SCIP *scip, SCIP_HEUR *heur, int coversize, int *cover, SCIP_Real *fixingvals, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Longint nodelimit, SCIP_Longint nstallnodes, SCIP_Bool *validsolved, SCIP_SOL **sol, SCIP_Longint *nusednodes)
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:3383
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:32190
SCIP_RETCODE SCIPcreateConsSetcover(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9007
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3657
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:32318
#define MIN(x, y)
Definition: memory.c:67
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
SCIP_RETCODE SCIPgetNlRowSOC(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
Definition: cons_soc.c:5214
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19972
SCIP_RETCODE SCIPchgVarBoundsDiveNLP(SCIP *scip, SCIP_VAR *var, SCIP_Real lb, SCIP_Real ub)
Definition: scip.c:29270
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:10194
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
SCIP_RETCODE SCIPsetNLPInitialGuessSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:28735
#define SCIP_Longint
Definition: def.h:112
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40716
static SCIP_RETCODE copySol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_SOL *subsol, SCIP_SOL **newsol)
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip.c:3759
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:8685
SCIP_RETCODE SCIPsetEmphasis(SCIP *scip, SCIP_PARAMEMPHASIS paramemphasis, SCIP_Bool quiet)
Definition: scip.c:4360
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:34885
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:3938
SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
Definition: scip.c:42068
#define HEUR_FREQOFS
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3797
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11999
SCIP_RETCODE SCIPexprintHessianSparsityDense(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Bool *sparsity)
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
static SCIP_RETCODE forbidCover(SCIP *scip, int nvars, SCIP_VAR **vars, int coversize, int *cover, int diversification, SCIP_Bool *success, SCIP_Bool *infeas)
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_REUSECOVER
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:35767
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3629
#define HEUR_PRIORITY
SCIP_RETCODE SCIPcreateConsLogicor(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)
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:41132
static SCIP_RETCODE SCIPapplyUndercover(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Longint nstallnodes)
static SCIP_DECL_HEURINITSOL(heurInitsolUndercover)
SCIP_RETCODE SCIPsolveDiveNLP(SCIP *scip)
Definition: scip.c:29331
SCIP_Real SCIPgetVarAvgInferenceCutoffScore(SCIP *scip, SCIP_VAR *var, SCIP_Real cutoffweight)
Definition: scip.c:24194
default SCIP plugins
#define DEFAULT_MAXCOVERSIZEVARS
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:36217
SCIP_RETCODE SCIPexprintFree(SCIP_EXPRINT **exprint)
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
#define HEUR_MAXDEPTH
#define DEFAULT_COVERBD
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:37372
static SCIP_RETCODE createCoveringProblem(SCIP *scip, SCIP *coveringscip, SCIP_VAR **coveringvars, SCIP_Bool globalbounds, SCIP_Bool onlyconvexify, SCIP_Bool coverbd, char coveringobj, SCIP_Bool *success)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:42270
SCIP callable library.
SCIP_Bool SCIPisConvexQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3322
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:35397
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34607
static SCIP_DECL_HEURFREE(heurFreeUndercover)
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:41409
int SCIPheurGetFreqofs(SCIP_HEUR *heur)
Definition: heur.c:1253
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5051