Scippy

SCIP

Solving Constraint Integer Programs

heur_clique.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-2015 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_clique.c
17  * @brief LNS heuristic using a clique partition to restrict the search neighborhood
18  * @brief clique primal heuristic
19  * @author Stefan Heinz
20  * @author Michael Winkler
21  *
22  * @todo allow smaller fixing rate for probing LP?
23  * @todo allow smaller fixing rate after presolve if total number of variables is small (<= 1000)?
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 
28 #include <assert.h>
29 #include <string.h>
30 
31 #include "scip/scip.h"
32 #include "scip/heur_clique.h"
33 #include "scip/cons_logicor.h"
34 
35 
36 #define HEUR_NAME "clique"
37 #define HEUR_DESC "LNS heuristic using a clique partition to restrict the search neighborhood"
38 #define HEUR_DISPCHAR 'Q'
39 #define HEUR_PRIORITY -1000500
40 #define HEUR_FREQ -1
41 #define HEUR_FREQOFS 0
42 #define HEUR_MAXDEPTH -1
43 #define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
44 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
45 
46 #define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
47 #define DEFAULT_MINFIXINGRATE 0.25 /**< minimum percentage of variables that have to be fixed */
48 #define DEFAULT_MINIMPROVE 0.01 /**< factor by which clique heuristic should at least improve the
49  * incumbent
50  */
51 #define DEFAULT_MINNODES 500LL /**< minimum number of nodes to regard in the subproblem */
52 #define DEFAULT_NODESOFS 500LL /**< number of nodes added to the contingent of the total nodes */
53 #define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
54 #define DEFAULT_MAXPROPROUNDS 2 /**< maximum number of propagation rounds during probing */
55 #define DEFAULT_INITSEED 0 /**< random seed value to initialize the random permutation
56  * value for variables
57  */
58 #define DEFAULT_MULTIPLIER 1.1 /**< value to increase node number to determine the next run */
59 #define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the
60  * original scip be copied to constraints of the subscip
61  */
62 
63 
64 /*
65  * Data structures
66  */
67 
68 /** primal heuristic data */
69 struct SCIP_HeurData
70 {
71  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
72  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
73  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
74  SCIP_Longint usednodes; /**< nodes already used by clique heuristic in earlier calls */
75  SCIP_Real minfixingrate; /**< minimum percentage of variables that have to be fixed */
76  SCIP_Real minimprove; /**< factor by which clique heuristic should at least improve the incumbent */
77  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
78  int maxproprounds; /**< maximum number of propagation rounds during probing */
79  SCIP_Longint nnodefornextrun; /**< node number for next run */
80  SCIP_Real multiplier; /**< multiplier to determine next node number */
81  int initseed; /**< initial random seed value */
82  unsigned int seed; /**< seed value for random number generator */
83  SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
84  * subproblem?
85  */
86 };
87 
88 /*
89  * Local methods
90  */
91 
92 /** comparison method for sorting variables by non-decreasing index */
93 static
94 SCIP_DECL_SORTPTRCOMP(varObjSort)
95 {
96  SCIP_VAR* var1;
97  SCIP_VAR* var2;
98 
99  assert(elem1 != NULL);
100  assert(elem2 != NULL);
101 
102  var1 = (SCIP_VAR*)elem1;
103  var2 = (SCIP_VAR*)elem2;
104 
105  if( SCIPvarGetObj(var1) < SCIPvarGetObj(var2) )
106  return -1;
107  else if( SCIPvarGetObj(var1) > SCIPvarGetObj(var2) )
108  return +1;
109  else
110  return 0;
111 }
112 
113 /** sort the binary variable array w.r.t. the clique partition; thereby ensure the current order within the cliques are
114  * not changed
115  */
116 static
118  SCIP* scip, /**< SCIP data structure */
119  SCIP_VAR** binvars, /**< array of binary variables to sort */
120  int nbinvars, /**< number of binary variables */
121  int* cliquepartition, /**< clique partition to use */
122  int ncliques /**< number of cliques */
123  )
124 {
125  SCIP_VAR*** varpointers;
126  SCIP_VAR** vars;
127  int* cliquecount;
128  int nextpos;
129  int c;
130  int v;
131  int cliquenumber;
132 
133  assert(scip != NULL);
134  assert(binvars != NULL);
135  assert(cliquepartition != NULL);
136 
137  /* @note: we don't want to loose order from same clique numbers, so we need a stable sorting algorithm, or we first
138  * count all clique items and alloc temporary memory for a bucket sort */
139  /* sort variables after clique-numbers */
140  SCIP_CALL( SCIPallocBufferArray(scip, &cliquecount, ncliques) );
141  BMSclearMemoryArray(cliquecount, ncliques);
142 
143  /* first we count for each clique the number of elements */
144  for( v = nbinvars - 1; v >= 0; --v )
145  {
146  assert(0 <= cliquepartition[v] && cliquepartition[v] < ncliques);
147  ++(cliquecount[cliquepartition[v]]);
148  }
149 
150  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbinvars) );
151 #ifndef NDEBUG
152  BMSclearMemoryArray(vars, nbinvars);
153 #endif
154  SCIP_CALL( SCIPallocBufferArray(scip, &varpointers, ncliques) );
155 
156  nextpos = 0;
157  /* now we initialize all start pointers for each clique, so they will be ordered */
158  for( c = 0; c < ncliques; ++c )
159  {
160  /* to reach the goal that all variables of each clique will be standing next to each other we will initialize the
161  * starting pointers for each clique by adding the number of each clique to the last clique starting pointer
162  * e.g. clique1 has 4 elements and clique2 has 3 elements the the starting pointer for clique1 will be the pointer
163  * to vars[0], the starting pointer to clique2 will be the pointer to vars[4] and to clique3 it will be
164  * vars[7]
165  *
166  */
167  varpointers[c] = (SCIP_VAR**) (vars + nextpos);
168  assert(cliquecount[c] > 0);
169  nextpos += cliquecount[c];
170  assert(nextpos > 0);
171  }
172  assert(nextpos == nbinvars);
173 
174  /* now we copy all variable to the right order in our temporary variable array */
175  for( v = 0; v < nbinvars; ++v )
176  {
177  *(varpointers[cliquepartition[v]]) = binvars[v];
178  ++(varpointers[cliquepartition[v]]);
179  }
180 #ifndef NDEBUG
181  for( v = 0; v < nbinvars; ++v )
182  assert(vars[v] != NULL);
183 #endif
184 
185  /* move all variables back to our variable array */
186  BMScopyMemoryArray(binvars, vars, nbinvars);
187 
188  cliquenumber = 0;
189  nextpos = cliquecount[0];
190 
191  c = 1;
192  for( v = 0; v < nbinvars; ++v )
193  {
194  if( v == nextpos )
195  {
196  nextpos += cliquecount[c];
197  ++c;
198  ++cliquenumber;
199  }
200  cliquepartition[v] = cliquenumber;
201  }
202  assert(cliquepartition[v - 1] == ncliques - 1);
203 
204 #ifndef NDEBUG
205  for( v = 1; v < nbinvars; ++v )
206  assert(SCIPvarGetObj(binvars[v - 1]) <= SCIPvarGetObj(binvars[v - 1]));
207 #endif
208 
209  /* free temporary memory */
210  SCIPfreeBufferArray(scip, &varpointers);
211  SCIPfreeBufferArray(scip, &vars);
212  SCIPfreeBufferArray(scip, &cliquecount);
213 
214  return SCIP_OKAY;
215 }
216 
217 /** apply clique fixing using probing */
218 static
220  SCIP* scip, /**< original SCIP data structure */
221  SCIP_HEURDATA* heurdata, /**< structure containing heurdata */
222  SCIP_VAR** binvars, /**< binary variables order w.r.t. to clique partition */
223  int nbinvars, /**< number of binary variables */
224  int* cliquepartition, /**< clique partition of all binary variables */
225  int ncliques, /**< number of cliques */
226  SCIP_VAR** onefixvars, /**< array to store all variables which are stored to one */
227  int* nonefixvars, /**< pointer to store the number of variables fixed to one */
228  SCIP_SOL* sol, /**< working solution */
229  int* probingdepthofonefix,/**< pointer to store in which depth the last fixing to was applied */
230  SCIP_Bool* cutoff, /**< pointer to store whether the propagation stopped with infeasibility */
231  SCIP_RESULT* result /**< pointer to store the result (solution found) */
232  )
233 {
234 #if 0
235  SCIP_Bool success;
236 #endif
237  SCIP_Bool alreadyone;
238  SCIP_Bool allfixed;
239  int bestpos;
240  int v;
241  int c;
242 #ifdef SCIP_DEBUG
243  int nsolsround;
244  int nsolstried;
245 #endif
246 
247  assert(scip != NULL);
248  assert(heurdata != NULL);
249  assert(binvars != NULL);
250  assert(onefixvars != NULL);
251  assert(nonefixvars != NULL);
252  assert(sol != NULL);
253  assert(probingdepthofonefix != NULL);
254  assert(cutoff != NULL);
255  assert(result != NULL);
256 
257  *cutoff = FALSE;
258  *probingdepthofonefix = 0;
259 
260 #ifdef SCIP_DEBUG
261  nsolsround = 0;
262  nsolstried = 0;
263 #endif
264  v = 0;
265  /* @todo maybe try to fix more than one variable to one in each probing node, to gain faster results */
266  for( c = 0; c < ncliques; ++c )
267  {
268  alreadyone = FALSE;
269  allfixed = TRUE;
270  bestpos = nbinvars;
271 
272  /* find first unfixed variable in this clique */
273  while( v < nbinvars && cliquepartition[v] == c )
274  {
275  if( SCIPvarGetLbLocal(binvars[v]) > 0.5 )
276  alreadyone = TRUE;
277  else if( allfixed && SCIPvarGetUbLocal(binvars[v]) > 0.5 )
278  {
279  bestpos = v;
280  allfixed = FALSE;
281  }
282 
283  ++v;
284  }
285  if( v == nbinvars && allfixed )
286  break;
287 
288  /* if all clique variables are fixed, continue with the next clique */
289  if( allfixed )
290  continue;
291 
292  assert(bestpos < nbinvars);
293  assert(c == cliquepartition[bestpos]);
294 
295  SCIP_CALL( SCIPnewProbingNode(scip) );
296 
297  v = bestpos;
298  if( !alreadyone )
299  {
300  *probingdepthofonefix = SCIPgetProbingDepth(scip);
301  onefixvars[(*nonefixvars)] = binvars[v];
302  ++(*nonefixvars);
303 
304  /* fix best possible clique variable to 1 */
305  SCIP_CALL( SCIPfixVarProbing(scip, binvars[v], 1.0) );
306  SCIPdebugMessage("probing: fixing variable <%s> to 1\n", SCIPvarGetName(binvars[v]));
307 
308  ++v;
309  }
310 
311  /* fix rest of unfixed clique variables to 0 */
312  while( v < nbinvars && cliquepartition[v] == c )
313  {
314  if( SCIPvarGetUbLocal(binvars[v]) > 0.5 && SCIPvarGetLbLocal(binvars[v]) < 0.5 )
315  {
316  SCIP_CALL( SCIPfixVarProbing(scip, binvars[v], 0.0) );
317  SCIPdebugMessage("probing: fixing variable <%s> to 0\n", SCIPvarGetName(binvars[v]));
318  }
319  ++v;
320  }
321 
322  /* propagate fixings */
323  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, cutoff, NULL) );
324 
325  if( *cutoff )
326  break;
327 
328  /* @todo need to be check if it's ok to always try to round and check the solution in each probing step */
329 #if 0
330 
331 #ifdef SCIP_DEBUG
332  ++nsolsround;
333 #endif
334  /* create solution from probing run and try to round it */
335  SCIP_CALL( SCIPlinkCurrentSol(scip, sol) );
336  SCIP_CALL( SCIProundSol(scip, sol, &success) );
337 
338  if( success )
339  {
340  SCIPdebugMessage("clique heuristic found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, sol));
341 
342 #ifdef SCIP_DEBUG
343  ++nsolstried;
344 #endif
345  /* try to add solution to SCIP */
346  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, TRUE, &success) );
347 
348  /* check, if solution was feasible and good enough */
349  if( success )
350  {
351  SCIPdebugMessage(" -> solution was feasible and good enough\n");
352  *result = SCIP_FOUNDSOL;
353  }
354  }
355 #endif
356 
357  if( SCIPisStopped(scip) )
358  return SCIP_OKAY;
359 
360 #if 0
361  /* if the rest of all variables are in cliques with one variable stop */
362  if( nbinvars - v == ncliques - c )
363  break;
364 #endif
365  }
366  assert((*probingdepthofonefix > 0 && *nonefixvars > 0) || (*probingdepthofonefix == 0 && *nonefixvars == 0));
367  assert(*cutoff || (nbinvars - v == ncliques - c) || (v == nbinvars && (c == ncliques || c == ncliques - 1)));
368 
369  SCIPdebugMessage("fixed %d of %d variables in probing\n", v, nbinvars);
370  SCIPdebugMessage("applied %d of %d cliques in probing\n", c, ncliques);
371  SCIPdebugMessage("probing was %sfeasible\n", (*cutoff) ? "in" : "");
372 #ifdef SCIP_DEBUG
373  SCIPdebugMessage("clique heuristic rounded %d solutions and tried %d of them\n", nsolsround, nsolstried);
374 #endif
375  return SCIP_OKAY;
376 }
377 
378 /** creates a new solution for the original problem by copying the solution of the subproblem */
379 static
381  SCIP* scip, /**< original SCIP data structure */
382  SCIP* subscip, /**< SCIP structure of the subproblem */
383  SCIP_VAR** subvars, /**< the variables of the subproblem */
384  SCIP_SOL* newsol, /**< working solution */
385  SCIP_SOL* subsol, /**< solution of the subproblem */
386  SCIP_Bool* success /**< used to store whether new solution was found or not */
387  )
388 {
389  SCIP_VAR** vars; /* the original problem's variables */
390  int nvars;
391  SCIP_Real* subsolvals; /* solution values of the subproblem */
392 
393  assert(scip != NULL);
394  assert(subscip != NULL);
395  assert(subvars != NULL);
396  assert(subsol != NULL);
397  assert(success != NULL);
398 
399  /* get variables' data */
400  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
401 
402  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
403  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
404  */
405  assert(nvars <= SCIPgetNOrigVars(subscip));
406 
407  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
408 
409  /* copy the solution */
410  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
411 
412  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
413 
414  /* try to add new solution to scip and free it immediately */
415  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, TRUE, TRUE, TRUE, success) );
416 
417  SCIPfreeBufferArray(scip, &subsolvals);
418 
419  return SCIP_OKAY;
420 }
421 
422 /*
423  * Callback methods of primal heuristic
424  */
425 
426 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
427 static
428 SCIP_DECL_HEURCOPY(heurCopyClique)
429 { /*lint --e{715}*/
430  assert(scip != NULL);
431  assert(heur != NULL);
432  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
433 
434  /* call inclusion method of primal heuristic */
436 
437  return SCIP_OKAY;
438 }
439 
440 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
441 static
442 SCIP_DECL_HEURFREE(heurFreeClique)
443 { /*lint --e{715}*/
444  SCIP_HEURDATA* heurdata;
445 
446  assert(heur != NULL);
447  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
448  assert(scip != NULL);
449 
450  /* free heuristic data */
451  heurdata = SCIPheurGetData(heur);
452  assert(heurdata != NULL);
453 
454  SCIPfreeMemory(scip, &heurdata);
455  SCIPheurSetData(heur, NULL);
456 
457  return SCIP_OKAY;
458 }
459 
460 
461 /** initialization method of primal heuristic (called after problem was transformed) */
462 static
463 SCIP_DECL_HEURINIT(heurInitClique)
464 { /*lint --e{715}*/
465  SCIP_HEURDATA* heurdata;
466 
467  assert(heur != NULL);
468  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
469  assert(scip != NULL);
470 
471  /* reset heuristic data */
472  heurdata = SCIPheurGetData(heur);
473  assert(heurdata != NULL);
474 
475  /* set the seed value to the initial random seed value */
476  heurdata->seed = (unsigned int) heurdata->initseed;
477 
478  heurdata->usednodes = 0;
479 
480  return SCIP_OKAY;
481 }
482 
483 
484 /** execution method of primal heuristic */
485 static
486 SCIP_DECL_HEUREXEC(heurExecClique)
487 { /*lint --e{715}*/
488  SCIP_HEURDATA* heurdata;
489  SCIP_VAR** vars;
490  int nvars;
491  SCIP_VAR** binvars;
492  int nbinvars;
493  int* cliquepartition;
494  int ncliques;
495  int oldnpscands;
496  int npscands;
497  int i;
498 #if 0
499  SCIP_Longint tmpnnodes;
500 #endif
501  SCIP_Bool cutoff;
502  SCIP_Bool backtrackcutoff;
503  SCIP_Bool lperror;
504 
505  int probingdepthofonefix;
506  SCIP_VAR** onefixvars;
507  int nonefixvars;
508  SCIP_Bool enabledconflicts;
509  SCIP_LPSOLSTAT lpstatus;
510  SCIP_CONS* conflictcons;
511  SCIP_Bool shortconflict;
512  SCIP_Bool allfixsolfound;
513  SCIP_Bool backtracked;
514  SCIP_Bool solvelp;
515  char consname[SCIP_MAXSTRLEN];
516 
517  SCIP_Real timelimit; /* timelimit for the subproblem */
518  SCIP_Real memorylimit;
519  SCIP_Longint nstallnodes; /* number of stalling nodes for the subproblem */
520 
521  SCIP_SOL* sol;
522 
523  assert(heur != NULL);
524  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
525  assert(scip != NULL);
526  assert(result != NULL);
527 
528  *result = SCIP_DIDNOTRUN;
529 
530  /* get heuristic's data */
531  heurdata = SCIPheurGetData(heur);
532  assert(heurdata != NULL);
533 
534 #if 0
535  if( heurdata->nnodefornextrun != SCIPgetNNodes(scip) )
536  return SCIP_OKAY;
537 #endif
538  /* get all binary variables */
539  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );
540 
541  if( nbinvars < 2 )
542  {
543  heurdata->nnodefornextrun = INT_MAX;
544  return SCIP_OKAY;
545  }
546 
547  /* check for necessary information to apply this heuristic */
548  if( SCIPgetNCliques(scip) == 0 )
549  {
550  heurdata->nnodefornextrun = INT_MAX;
551  return SCIP_OKAY;
552  }
553 
554  /* calculate the maximal number of branching nodes until heuristic is aborted */
555  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
556 
557  /* reward variable bounds heuristic if it succeeded often */
558  nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
559  nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
560  nstallnodes += heurdata->nodesofs;
561 
562  /* determine the node limit for the current process */
563  nstallnodes -= heurdata->usednodes;
564  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
565 
566  /* check whether we have enough nodes left to call subproblem solving */
567  if( nstallnodes < heurdata->minnodes )
568  {
569  SCIPdebugMessage("skipping " HEUR_NAME ": nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
570  return SCIP_OKAY;
571  }
572 
573  oldnpscands = SCIPgetNPseudoBranchCands(scip);
574  onefixvars = NULL;
575  sol = NULL;
576 
577  /* allocate memory */
578  SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, vars, nbinvars) );
579  SCIP_CALL( SCIPallocBufferArray(scip, &cliquepartition, nbinvars) );
580 
581 #if 1
582  /* @todo change sorting after some attempts to random variable order */
583  if( SCIPgetNNodes(scip) == 1 )
584  {
585  /* sort variables after increasing objective value */
586  SCIPsortPtr((void**)binvars, varObjSort, nbinvars);
587  }
588  else
589  {
590  SCIPpermuteArray((void**)binvars, 0, nbinvars, &(heurdata->seed));
591  }
592 #endif
593 
594  /* get clique partitions */
595  SCIP_CALL( SCIPcalcCliquePartition(scip, binvars, nbinvars, cliquepartition, &ncliques) );
596  /* @todo get negated clique partition and use this too, or maybe mix both */
597 
598  SCIPdebugMessage("found %d cliques\n", ncliques);
599 
600  /* disable conflict analysis, because we can it better than SCIP itself, cause we have more information */
601  SCIP_CALL( SCIPgetBoolParam(scip, "conflict/enable", &enabledconflicts) );
602 
603  if( !SCIPisParamFixed(scip, "conflict/enable") )
604  {
605  SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", FALSE) );
606  }
607 
608  if( ncliques == nbinvars )
609  {
610  heurdata->nnodefornextrun = INT_MAX;
611  goto TERMINATE;
612  }
613 
614  /* sort the cliques together by respecting the current order (which is w.r.t. the objective coefficients */
615  SCIP_CALL( stableSortBinvars(scip, binvars, nbinvars, cliquepartition, ncliques) );
616 
617  for( i = nbinvars - 1; i >= 0; --i )
618  {
619  if( cliquepartition[i] != ncliques - nbinvars + i )
620  {
621  assert(cliquepartition[i] > ncliques - nbinvars + i);
622  break;
623  }
624  }
625 
626  if( i + 2 < heurdata->minfixingrate * nbinvars )
627  {
628  SCIPdebugMessage("--> too few variables in nontrivial cliques\n");
629 
630  goto TERMINATE;
631  }
632 
633 
634  solvelp = SCIPhasCurrentNodeLP(scip);
635 
636  if( !SCIPisLPConstructed(scip) && solvelp )
637  {
638  SCIP_Bool nodecutoff;
639 
640  SCIP_CALL( SCIPconstructLP(scip, &nodecutoff) );
641  SCIP_CALL( SCIPflushLP(scip) );
642  if( nodecutoff )
643  goto TERMINATE;
644  }
645 
646  *result = SCIP_DIDNOTFIND;
647 
648  /* start probing */
649  SCIP_CALL( SCIPstartProbing(scip) );
650 
651  /* create a solution */
652  SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
653 
654  /* allocate memory for all variables which will be fixed to one during probing */
655  SCIP_CALL(SCIPallocBufferArray(scip, &onefixvars, ncliques) );
656  nonefixvars = 0;
657 
658  /* apply fixings due to clique information */
659  SCIP_CALL( applyCliqueFixings(scip, heurdata, binvars, nbinvars, cliquepartition, ncliques, onefixvars, &nonefixvars, sol, &probingdepthofonefix, &cutoff, result) );
660 
661  if( SCIPisStopped(scip) )
662  goto TERMINATE;
663 
664  backtrackcutoff = FALSE;
665  backtracked = FALSE;
666 
667  /* try to repair probing */
668  if( cutoff && nonefixvars > 0)
669  {
670  assert(probingdepthofonefix > 0);
671 
672  SCIP_CALL( SCIPbacktrackProbing(scip, probingdepthofonefix - 1) );
673 
674  /* fix the last variable, which was fixed to 1 and led to the cutoff, to 0 */
675  SCIP_CALL( SCIPfixVarProbing(scip, onefixvars[nonefixvars - 1], 0.0) );
676 
677  backtracked = TRUE;
678 
679  /* propagate fixings */
680  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, &backtrackcutoff, NULL) );
681 
682  SCIPdebugMessage("backtrack was %sfeasible\n", (backtrackcutoff ? "in" : ""));
683  }
684 
685  /* check that we had enough fixings */
686  npscands = SCIPgetNPseudoBranchCands(scip);
687 
688  SCIPdebugMessage("npscands=%d, oldnpscands=%d, heurdata->minfixingrate=%g\n", npscands, oldnpscands, heurdata->minfixingrate);
689 
690  if( npscands > oldnpscands * (1 - heurdata->minfixingrate) )
691  {
692  SCIPdebugMessage("--> too few fixings\n");
693 
694  goto TERMINATE;
695  }
696 
697  /*************************** Probing LP Solving ***************************/
698 
699  lpstatus = SCIP_LPSOLSTAT_ERROR;
700  lperror = FALSE;
701  allfixsolfound = FALSE;
702  /* solve lp only if the problem is still feasible */
703  if( !backtrackcutoff && solvelp )
704  {
705 #if 1
706  SCIPdebugMessage("starting solving clique-lp at time %g\n", SCIPgetSolvingTime(scip));
707 
708  /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
709  * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
710  * SCIP will stop.
711  */
712 #ifdef NDEBUG
713  {
714  SCIP_Bool retstat;
715  retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
716  if( retstat != SCIP_OKAY )
717  {
718  SCIPwarningMessage(scip, "Error while solving LP in clique heuristic; LP solve terminated with code <%d>\n",
719  retstat);
720  }
721  }
722 #else
723  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
724 #endif
725  SCIPdebugMessage("ending solving clique-lp at time %g\n", SCIPgetSolvingTime(scip));
726 
727  lpstatus = SCIPgetLPSolstat(scip);
728 
729  SCIPdebugMessage(" -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
730  SCIPdebugMessage(" -> error=%u, status=%d\n", lperror, lpstatus);
731  }
732 
733  /* check if this is a feasible solution */
734  if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
735  {
736  SCIP_Bool stored;
737  SCIP_Bool success;
738 
739  /* copy the current LP solution to the working solution */
740  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
741 
742  SCIP_CALL( SCIProundSol(scip, sol, &success) );
743 
744  if( success )
745  {
746  SCIPdebugMessage("clique heuristic found roundable primal solution: obj=%g\n",
747  SCIPgetSolOrigObj(scip, sol));
748 
749  /* check solution for feasibility, and add it to solution store if possible.
750  * Neither integrality nor feasibility of LP rows have to be checked, because they
751  * are guaranteed by the heuristic at this stage.
752  */
753 #ifdef SCIP_DEBUG
754  SCIP_CALL( SCIPtrySol(scip, sol, TRUE, TRUE, TRUE, TRUE, &stored) );
755 #else
756  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, TRUE, FALSE, FALSE, &stored) );
757 #endif
758  allfixsolfound = TRUE;
759 
760  if( stored )
761  {
762  SCIPdebugMessage("found feasible solution:\n");
763  SCIPdebug( SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) ) );
764  *result = SCIP_FOUNDSOL;
765  }
766  }
767  }
768 #endif
769 
770  /*************************** END Probing LP Solving ***************************/
771  /*************************** Create Conflict ***************************/
772 
773  if( lpstatus == SCIP_LPSOLSTAT_INFEASIBLE || lpstatus == SCIP_LPSOLSTAT_OBJLIMIT || backtrackcutoff )
774  {
775  /* in case the last fixing in both direction led to infeasibility or to a reached objlimit than our conflict will
776  * only include all variable before that last fixing
777  */
778  shortconflict = cutoff && (nonefixvars > 0);
779 
780  /* create own conflict */
781  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "conf%" SCIP_LONGINT_FORMAT "", SCIPgetNNodes(scip));
782 
783  /* get negated variables for our conflict */
784  SCIP_CALL( SCIPgetNegatedVars(scip, nonefixvars, onefixvars, onefixvars) );
785 
786  /* create conflict constraint */
787  SCIP_CALL( SCIPcreateConsLogicor(scip, &conflictcons, consname, (shortconflict ? nonefixvars - 1 : nonefixvars), onefixvars,
789  SCIP_CALL( SCIPaddConsNode(scip, SCIPgetCurrentNode(scip), conflictcons, NULL) );
790  SCIPdebugPrintCons(scip, conflictcons, NULL);
791  SCIP_CALL( SCIPreleaseCons(scip, &conflictcons) );
792  }
793 
794  /*************************** End Conflict ***************************/
795 
796  /*************************** Start Subscip Solving ***************************/
797 
798  /* if no solution has been found yet and the subproblem is still feasible --> fix all other variables by subscip if
799  * necessary
800  */
801  if( !allfixsolfound && lpstatus != SCIP_LPSOLSTAT_INFEASIBLE && lpstatus != SCIP_LPSOLSTAT_OBJLIMIT && !backtrackcutoff )
802  {
803  SCIP* subscip;
804  SCIP_VAR** subvars;
805  SCIP_HASHMAP* varmap;
806  SCIP_Bool valid;
807 
808  valid = FALSE;
809 
810  /* get all variables again because SCIPconstructLP() might have changed the variables array */
811  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
812 
813  /* create subproblem */
814  SCIP_CALL( SCIPcreate(&subscip) );
815 
816  /* allocate temporary memory for subscip variables */
817  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
818 
819  /* create the variable mapping hash map */
820  SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
821 
822  SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "_clique", FALSE, FALSE, TRUE, &valid) );
823 
824  if( heurdata->copycuts )
825  {
826  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
827  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
828  }
829 
830  for( i = 0; i < nvars; i++ )
831  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
832 
833  /* free hash map */
834  SCIPhashmapFree(&varmap);
835 
836  /* do not abort subproblem on CTRL-C */
837  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
838 
839  /* disable output to console */
840  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
841 
842  /* check whether there is enough time and memory left */
843  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
844  if( !SCIPisInfinity(scip, timelimit) )
845  timelimit -= SCIPgetSolvingTime(scip);
846  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
847 
848  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
849  if( !SCIPisInfinity(scip, memorylimit) )
850  {
851  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
852  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
853  }
854 
855  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
856  if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
857  {
858  /* free subproblem */
859  SCIPfreeBufferArray(scip, &subvars);
860  SCIP_CALL( SCIPfree(&subscip) );
861 
862  goto TERMINATE;
863  }
864 
865 #ifndef SCIP_DEBUG
866  /* disable statistic timing inside sub SCIP */
867  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
868 #endif
869  /* set limits for the subproblem */
870  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
871  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
872  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
873  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
874 
875  /* forbid call of heuristics and separators solving sub-CIPs */
876  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
877 
878  /* disable cutting plane separation */
880 
881  /* disable expensive presolving */
883 
884  /* use inference branching */
885  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
886  {
887  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
888  }
889 
890  /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
891  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
892  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
893  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
894  * made for the original SCIP
895  */
896  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
897  {
898  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
899  }
900 
901 #ifdef SCIP_DEBUG
902  /* for debugging clique heuristic, enable MIP output */
903  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
904  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
905 #endif
906 
907  /* if there is already a solution, add an objective cutoff */
908  if( SCIPgetNSols(scip) > 0 )
909  {
910  SCIP_Real upperbound;
911  SCIP_Real minimprove;
912  SCIP_Real cutoffbound;
913 
914  minimprove = heurdata->minimprove;
915  cutoffbound = SCIPinfinity(scip);
916  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
917 
918  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
919 
920  if( !SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
921  {
922  cutoffbound = (1-minimprove) * SCIPgetUpperbound(scip) + minimprove * SCIPgetLowerbound(scip);
923  }
924  else
925  {
926  if( SCIPgetUpperbound ( scip ) >= 0 )
927  cutoffbound = (1 - minimprove) * SCIPgetUpperbound(scip);
928  else
929  cutoffbound = (1 + minimprove) * SCIPgetUpperbound(scip);
930  }
931  cutoffbound = MIN(upperbound, cutoffbound);
932  SCIP_CALL( SCIPsetObjlimit(subscip, cutoffbound) );
933  SCIPdebugMessage("setting objlimit for subscip to %g\n", cutoffbound);
934  }
935 
936  SCIPdebugMessage("starting solving clique-submip at time %g\n", SCIPgetSolvingTime(scip));
937 
938  /* solve the subproblem */
939  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
940  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
941  */
942 #ifdef NDEBUG
943  {
944  SCIP_RETCODE retstat;
945  retstat = SCIPpresolve(subscip);
946  if( retstat != SCIP_OKAY )
947  {
948  SCIPwarningMessage(scip, "Error while presolving subMIP in clique heuristic; sub-SCIP terminated with code <%d>\n", retstat);
949  }
950  }
951 #else
952  SCIP_CALL( SCIPpresolve(subscip) );
953 #endif
954 
955  SCIPdebugMessage("clique heuristic presolved subproblem: %d vars, %d cons; fixing value = %g\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars));
956 
957  /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
958  * to ensure that not only the MIP but also the LP relaxation is easy enough
959  */
960  if( ((nvars - SCIPgetNVars(subscip)) / (SCIP_Real)nvars) >= heurdata->minfixingrate )
961  {
962  SCIP_SOL** subsols;
963  SCIP_Bool success;
964  int nsubsols;
965 
966  SCIPdebugMessage("solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
967 
968 #ifdef NDEBUG
969  {
970  SCIP_RETCODE retstat;
971  retstat = SCIPsolve(subscip);
972  if( retstat != SCIP_OKAY )
973  {
974  SCIPwarningMessage(scip, "Error while solving subMIP in clique heuristic; sub-SCIP terminated with code <%d>\n",retstat);
975  }
976  }
977 #else
978  SCIP_CALL( SCIPsolve(subscip) );
979 #endif
980  SCIPdebugMessage("ending solving clique-submip at time %g, status = %d\n", SCIPgetSolvingTime(scip), SCIPgetStatus(subscip));
981 
982  /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
983  * try all solutions until one was accepted
984  */
985  nsubsols = SCIPgetNSols(subscip);
986  subsols = SCIPgetSols(subscip);
987  success = FALSE;
988 
989  for( i = 0; i < nsubsols && !success; ++i )
990  {
991  SCIP_CALL( createNewSol(scip, subscip, subvars, sol, subsols[i], &success) );
992  }
993  if( success )
994  *result = SCIP_FOUNDSOL;
995 
996  /* if subscip was infeasible we can add a conflict too */
997  if( SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE )
998  {
999  /* in case the last fixing in both direction led to infeasibility or to a reached objlimit than our conflict will only include all variable before that last fixing */
1000  shortconflict = backtracked;
1001 
1002  /* create own conflict */
1003  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "conf%" SCIP_LONGINT_FORMAT "", SCIPgetNNodes(scip));
1004 
1005  /* get negated variables for our conflict */
1006  SCIP_CALL( SCIPgetNegatedVars(scip, nonefixvars, onefixvars, onefixvars) );
1007 
1008  /* create conflict constraint */
1009  SCIP_CALL( SCIPcreateConsLogicor(scip, &conflictcons, consname, (shortconflict ? nonefixvars - 1 : nonefixvars), onefixvars,
1010  FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
1011  SCIP_CALL( SCIPaddConsNode(scip, SCIPgetCurrentNode(scip), conflictcons, NULL) );
1012  SCIPdebugPrintCons(scip, conflictcons, NULL);
1013  SCIP_CALL( SCIPreleaseCons(scip, &conflictcons) );
1014  }
1015 
1016  }
1017 
1018 #ifdef SCIP_DEBUG
1019  SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
1020 #endif
1021 
1022  /* free subproblem */
1023  SCIPfreeBufferArray(scip, &subvars);
1024  SCIP_CALL( SCIPfree(&subscip) );
1025  }
1026 
1027  /*************************** End Subscip Solving ***************************/
1028 
1029  TERMINATE:
1030 
1031  /* reset the conflict analysis */
1032  if( !SCIPisParamFixed(scip, "conflict/enable") )
1033  {
1034  SCIP_CALL( SCIPsetBoolParam(scip, "conflict/enable", enabledconflicts) );
1035  }
1036 
1037  /* free conflict variables */
1038  if( onefixvars != NULL )
1039  SCIPfreeBufferArray(scip, &onefixvars);
1040 
1041  /* freeing solution */
1042  if( sol != NULL )
1043  {
1044  SCIP_CALL( SCIPfreeSol(scip, &sol) );
1045  }
1046 
1047  /* end probing */
1048  if( SCIPinProbing(scip) )
1049  {
1050  SCIP_CALL( SCIPendProbing(scip) );
1051  }
1052 
1053  SCIPfreeBufferArray(scip, &cliquepartition);
1054  SCIPfreeBufferArray(scip, &binvars);
1055 
1056 #if 0
1057  /* calculate next node number to run this heuristic */
1058  tmpnnodes = (SCIP_Longint) SCIPceil(scip, heurdata->nnodefornextrun * heurdata->multiplier);
1059  heurdata->nnodefornextrun = MIN(tmpnnodes, INT_MAX);
1060  SCIPdebugMessage("Next run will be at node %" SCIP_LONGINT_FORMAT ".\n", heurdata->nnodefornextrun);
1061 #endif
1062  return SCIP_OKAY;
1063 }
1064 
1065 /*
1066  * primal heuristic specific interface methods
1067  */
1068 
1069 /** creates the clique primal heuristic and includes it in SCIP */
1071  SCIP* scip /**< SCIP data structure */
1072  )
1073 {
1074  SCIP_HEURDATA* heurdata;
1075  SCIP_HEUR* heur;
1077  /* create clique primal heuristic data */
1078  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1079 
1080  /* include primal heuristic */
1081  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1083  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecClique, heurdata) );
1084 
1085  assert(heur != NULL);
1086 
1087  /* set non-NULL pointers to callback methods */
1088  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyClique) );
1089  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeClique) );
1090  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitClique) );
1091 
1092  /* add clique primal heuristic parameters */
1093 
1094  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/multiplier",
1095  "value to increase nodenumber to determine the next run",
1096  &heurdata->multiplier, TRUE, DEFAULT_MULTIPLIER, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1097 
1098  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/initseed",
1099  "initial random seed value to permutate variables",
1100  &(heurdata->initseed), TRUE, DEFAULT_INITSEED, 0, INT_MAX, NULL, NULL) );
1101 
1102  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1103  "minimum percentage of integer variables that have to be fixable",
1104  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1105 
1106  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1107  "maximum number of nodes to regard in the subproblem",
1108  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1109 
1110  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1111  "number of nodes added to the contingent of the total nodes",
1112  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1113 
1114  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1115  "minimum number of nodes required to start the subproblem",
1116  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1117 
1118  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1119  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1120  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1121 
1122  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1123  "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
1124  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1125 
1126  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
1127  "maximum number of propagation rounds during probing (-1 infinity)",
1128  &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
1129 
1130  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1131  "should all active cuts from cutpool be copied to constraints in subproblem?",
1132  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1133 
1134  return SCIP_OKAY;
1135 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:7879
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32398
#define DEFAULT_MULTIPLIER
Definition: heur_clique.c:62
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:39903
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5847
LNS heuristic using a clique partition to restrict the search neighborhood.
#define HEUR_TIMING
Definition: heur_clique.c:43
#define DEFAULT_MAXNODES
Definition: heur_clique.c:46
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:908
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41256
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7266
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:31860
#define HEUR_FREQ
Definition: heur_clique.c:40
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1220
#define HEUR_MAXDEPTH
Definition: heur_clique.c:42
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:37064
#define SCIP_MAXSTRLEN
Definition: def.h:198
static SCIP_DECL_HEURFREE(heurFreeClique)
Definition: heur_clique.c:448
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_DECL_HEUREXEC(heurExecClique)
Definition: heur_clique.c:492
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPgetNegatedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **negvars)
Definition: scip.c:17279
#define HEUR_DESC
Definition: heur_clique.c:37
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:7221
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32162
#define FALSE
Definition: def.h:53
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2052
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:40583
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4015
#define DEFAULT_NODESQUOT
Definition: heur_clique.c:55
int SCIPgetNPseudoBranchCands(SCIP *scip)
Definition: scip.c:33099
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8169
#define TRUE
Definition: def.h:52
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4078
#define DEFAULT_MAXPROPROUNDS
Definition: heur_clique.c:56
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define HEUR_FREQOFS
Definition: heur_clique.c:41
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26426
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:3570
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_INITSEED
Definition: heur_clique.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16803
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2111
#define SCIP_LONGINT_MAX
Definition: def.h:110
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24936
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:37979
#define DEFAULT_MINNODES
Definition: heur_clique.c:53
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34676
SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2852
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_SOL *newsol, SCIP_SOL *subsol, SCIP_Bool *success)
Definition: heur_clique.c:386
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:35278
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:3516
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:3542
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:11175
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip.c:26359
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:11773
static SCIP_RETCODE stableSortBinvars(SCIP *scip, SCIP_VAR **binvars, int nbinvars, int *cliquepartition, int ncliques)
Definition: heur_clique.c:123
#define HEUR_DISPCHAR
Definition: heur_clique.c:38
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:26382
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:3223
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20355
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
#define DEFAULT_MINFIXINGRATE
Definition: heur_clique.c:47
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1152
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:31833
#define HEUR_USESSUBSCIP
Definition: heur_clique.c:44
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:33612
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:40927
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2070
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4426
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:34630
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41245
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip.c:14378
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26341
#define DEFAULT_MINIMPROVE
Definition: heur_clique.c:48
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:35327
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:31741
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11966
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:38120
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
#define DEFAULT_NODESOFS
Definition: heur_clique.c:54
#define SCIP_Bool
Definition: def.h:50
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:3970
SCIP_RETCODE SCIPcalcCliquePartition(SCIP *const scip, SCIP_VAR **const vars, int const nvars, int *const cliquepartition, int *const ncliques)
Definition: scip.c:21846
SCIP_RETCODE SCIPlinkCurrentSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34363
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:3678
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:4351
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:40970
int SCIPgetNCliques(SCIP *scip)
Definition: scip.c:22095
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
Definition: scip.c:32025
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:31763
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:31895
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4400
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36389
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34258
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7298
#define SCIP_REAL_MAX
Definition: def.h:125
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14539
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41378
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1293
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
#define HEUR_NAME
Definition: heur_clique.c:36
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20422
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7282
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8405
#define SCIP_Real
Definition: def.h:124
static SCIP_RETCODE applyCliqueFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **binvars, int nbinvars, int *cliquepartition, int ncliques, SCIP_VAR **onefixvars, int *nonefixvars, SCIP_SOL *sol, int *probingdepthofonefix, SCIP_Bool *cutoff, SCIP_RESULT *result)
Definition: heur_clique.c:225
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:31800
static SCIP_DECL_SORTPTRCOMP(varObjSort)
Definition: heur_clique.c:100
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition: scip.c:26406
#define MIN(x, y)
Definition: memory.c:63
#define HEUR_PRIORITY
Definition: heur_clique.c:39
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:10231
#define SCIP_Longint
Definition: def.h:109
static SCIP_DECL_HEURINIT(heurInitClique)
Definition: heur_clique.c:469
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:34495
#define DEFAULT_COPYCUTS
Definition: heur_clique.c:63
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:3907
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:10609
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3766
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
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:3598
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:40706
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:3709
static SCIP_DECL_HEURCOPY(heurCopyClique)
Definition: heur_clique.c:434
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:35827
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:36982
SCIP callable library.
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:35007
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34217
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:40983
SCIP_RETCODE SCIPincludeHeurClique(SCIP *scip)
Definition: heur_clique.c:1076
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:35519