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