Scippy

SCIP

Solving Constraint Integer Programs

sepa_disjunctive.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 sepa_disjunctive.c
17  * @brief disjunctive cut separator
18  * @author Tobias Fischer
19  * @author Marc Pfetsch
20  *
21  * We separate disjunctive cuts for two term disjunctions of the form \f$x_1 = 0 \vee x_2 = 0\f$. They can be generated
22  * directly from the simplex tableau. For further information, we refer to@n
23  * "A complementarity-based partitioning and disjunctive cut algorithm for mathematical programming problems with
24  * equilibrium constraints"@n
25  * Júdice, J.J., Sherali, H.D., Ribeiro, I.M., Faustino, A.M., Journal of Global Optimization 36(1), 89–114 (2006)
26  */
27 
28 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 
30 #include <assert.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include "scip/sepa_disjunctive.h"
34 #include "scip/cons_sos1.h"
35 
36 
37 #define SEPA_NAME "disjunctive"
38 #define SEPA_DESC "disjunctive cut separator"
39 #define SEPA_PRIORITY 10 /**< priority for separation */
40 #define SEPA_FREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
41 #define SEPA_MAXBOUNDDIST 0.0 /**< maximal relative distance from the current node's dual bound to primal bound
42  * compared to best node's dual bound for applying separation.*/
43 #define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
44 #define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
45 
46 #define DEFAULT_MAXRANK 20 /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
47 #define DEFAULT_MAXRANKINTEGRAL -1 /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
48 #define DEFAULT_MAXWEIGHTRANGE 1e+03 /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
49 
50 #define DEFAULT_MAXDEPTH -1 /**< node depth of separating cuts (-1: no limit) */
51 #define DEFAULT_MAXROUNDS 25 /**< maximal number of separation rounds in a branching node (-1: no limit) */
52 #define DEFAULT_MAXROUNDSROOT 100 /**< maximal number of separation rounds in the root node (-1: no limit) */
53 #define DEFAULT_MAXINVCUTS 50 /**< maximal number of cuts investigated per iteration in a branching node */
54 #define DEFAULT_MAXINVCUTSROOT 250 /**< maximal number of cuts investigated per iteration in the root node */
55 #define DEFAULT_MAXCONFSDELAY 100000 /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
56 
57 
58 /** separator data */
59 struct SCIP_SepaData
60 {
61  SCIP_CONSHDLR* conshdlr; /**< SOS1 constraint handler */
62  SCIP_Real maxweightrange; /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
63  int maxrank; /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
64  int maxrankintegral; /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
65  int maxdepth; /**< node depth of separating cuts (-1: no limit) */
66  int maxrounds; /**< maximal number of separation rounds in a branching node (-1: no limit) */
67  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: no limit) */
68  int maxinvcuts; /**< maximal number of cuts separated per iteration in a branching node */
69  int maxinvcutsroot; /**< maximal number of cuts separated per iteration in the root node */
70  int maxconfsdelay; /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
71  int lastncutsfound; /**< total number of cuts found after last call of separator */
72 };
73 
74 
75 /** gets rank of variable corresponding to row of \f$B^{-1}\f$ */
76 static
77 int getVarRank(
78  SCIP* scip, /**< SCIP pointer */
79  SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
80  SCIP_Real* rowsmaxval, /**< maximal row multiplicator from nonbasic matrix A_N */
81  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
82  SCIP_ROW** rows, /**< rows of LP relaxation of scip */
83  int nrows /**< number of rows */
84  )
85 {
86  SCIP_Real maxweight = 0.0;
87  int maxrank = 0;
88  int r;
89 
90  assert( scip != NULL );
91  assert( binvrow != NULL || nrows == 0 );
92  assert( rowsmaxval != NULL || nrows == 0 );
93  assert( rows != NULL || nrows == 0 );
94 
95  /* compute maximum row weights resulting from multiplication */
96  for (r = 0; r < nrows; ++r)
97  {
98  SCIP_Real val;
99 
100  val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
101  if ( SCIPisGT(scip, val, maxweight) )
102  maxweight = val;
103  }
104 
105  /* compute rank */
106  for (r = 0; r < nrows; ++r)
107  {
108  SCIP_Real val;
109  int rank;
110 
111  val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
112  rank = SCIProwGetRank(rows[r]);/*lint !e613*/
113  if ( rank > maxrank && SCIPisGT(scip, val * maxweightrange, maxweight) )
114  maxrank = rank;
115  }
116 
117  return maxrank;
118 }
119 
120 
121 /** gets the nonbasic coefficients of a simplex row */
122 static
124  SCIP* scip, /**< SCIP pointer */
125  SCIP_ROW** rows, /**< LP rows */
126  int nrows, /**< number LP rows */
127  SCIP_COL** cols, /**< LP columns */
128  int ncols, /**< number of LP columns */
129  SCIP_Real* coef, /**< row of \f$B^{-1} \cdot A\f$ */
130  SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
131  SCIP_Real* simplexcoefs, /**< pointer to store the nonbasic simplex-coefficients */
132  int* nonbasicnumber /**< pointer to store the number of nonbasic simplex-coefficients */
133  )
134 {
135  int r;
136  int c;
137 
138  assert( scip != NULL );
139  assert( rows != NULL );
140  assert( nonbasicnumber != NULL );
141  assert( simplexcoefs != NULL );
142  assert( cols != NULL );
143 
144  *nonbasicnumber = 0;
145 
146  /* note: the non-slack variables have to be added first (see the function generateDisjCutSOS1()) */
147 
148  /* get simplex-coefficients of the non-basic non-slack variables */
149  for (c = 0; c < ncols; ++c)
150  {
151  SCIP_COL* col;
152 
153  col = cols[c];
154  assert( col != NULL );
156  simplexcoefs[(*nonbasicnumber)++] = coef[c];
157  }
158 
159  /* get simplex-coefficients of the non-basic slack variables */
160  for (r = 0; r < nrows; ++r)
161  {
162  SCIP_ROW* row;
163  row = rows[r];
164  assert( row != NULL );
165 
167  {
168  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, row) - SCIProwGetRhs(row)) || SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, row) - SCIProwGetLhs(row)) );
169 
170  simplexcoefs[(*nonbasicnumber)++] = binvrow[r];
171  }
172  }
173 
174  return SCIP_OKAY;
175 }
176 
177 
178 /** computes a disjunctive cut inequality based on two simplex taubleau rows */
179 static
181  SCIP* scip, /**< SCIP pointer */
182  SCIP_SEPA* sepa, /**< separator */
183  SCIP_ROW** rows, /**< LP rows */
184  int nrows, /**< number of LP rows */
185  SCIP_COL** cols, /**< LP columns */
186  int ncols, /**< number of LP columns */
187  int ndisjcuts, /**< number of disjunctive cuts found so far */
188  SCIP_Bool scale, /**< should cut be scaled */
189  SCIP_Real cutlhs1, /**< left hand side of the first sum of simplex rows */
190  SCIP_Real cutlhs2, /**< left hand side of the second sum of simplex rows */
191  SCIP_Real* simplexcoefs1, /**< simplex coefficients of first row */
192  SCIP_Real* simplexcoefs2, /**< simplex coefficients of second row */
193  SCIP_Real* cutcoefs, /**< pointer to store cut coefficients (length: nscipvars) */
194  SCIP_ROW** row, /**< pointer to store disjunctive cut inequality */
195  SCIP_Bool* madeintegral /**< pointer to store whether cut has been scaled to integral values */
196  )
197 {
198  char cutname[SCIP_MAXSTRLEN];
199  SCIP_COL** rowcols;
200  SCIP_COL* col;
201  SCIP_Real* rowvals;
202  SCIP_Real lhsrow;
203  SCIP_Real rhsrow;
204  SCIP_Real cutlhs;
205  SCIP_Real sgn;
206  SCIP_Real lb;
207  SCIP_Real ub;
208  int nonbasicnumber = 0;
209  int rownnonz;
210  int ind;
211  int r;
212  int c;
213 
214  assert( scip != NULL );
215  assert( row != NULL );
216  assert( rows != NULL );
217  assert( cols != NULL );
218  assert( simplexcoefs1 != NULL );
219  assert( simplexcoefs2 != NULL );
220  assert( cutcoefs != NULL );
221  assert( sepa != NULL );
222  assert( madeintegral != NULL );
223 
224  *madeintegral = FALSE;
225 
226  /* check signs */
227  if ( SCIPisFeasPositive(scip, cutlhs1) == SCIPisFeasPositive(scip, cutlhs2) )
228  sgn = 1.0;
229  else
230  sgn = -1.0;
231 
232  /* compute left hand side of row (a later update is possible, see below) */
233  cutlhs = sgn * cutlhs1 * cutlhs2;
234 
235  /* add cut-coefficients of the non-basic non-slack variables */
236  for (c = 0; c < ncols; ++c)
237  {
238  col = cols[c];
239  assert( col != NULL );
240  ind = SCIPcolGetLPPos(col);
241  assert( ind >= 0 );
242 
244  {
245  lb = SCIPcolGetLb(col);
246 
247  cutcoefs[ind] = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
248  cutlhs += cutcoefs[ind] * lb;
249  ++nonbasicnumber;
250  }
251  else if ( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_UPPER )
252  {
253  ub = SCIPcolGetUb(col);
254 
255  cutcoefs[ind] = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
256  cutlhs += cutcoefs[ind] * ub;
257  ++nonbasicnumber;
258  }
259  else
260  {
261  assert( SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_ZERO );
262  cutcoefs[ind] = 0.0;
263  }
264  }
265 
266  /* add cut-coefficients of the non-basic slack variables */
267  for (r = 0; r < nrows; ++r)
268  {
269  rhsrow = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]);
270  lhsrow = SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]);
271 
272  assert( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_ZERO );
273  assert( SCIPisFeasZero(scip, lhsrow - rhsrow) || SCIPisNegative(scip, lhsrow - rhsrow) );
274  assert( SCIProwIsInLP(rows[r]) );
275 
276  if ( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_BASIC )
277  {
278  SCIP_Real cutcoef;
279 
280  if ( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_UPPER )
281  {
282  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetRhs(rows[r])) );
283 
284  cutcoef = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
285  cutlhs -= cutcoef * rhsrow;
286  ++nonbasicnumber;
287  }
288  else /* SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER */
289  {
290  assert( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER );
291  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetLhs(rows[r])) );
292 
293  cutcoef = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
294  cutlhs -= cutcoef * lhsrow;
295  ++nonbasicnumber;
296  }
297 
298  rownnonz = SCIProwGetNNonz(rows[r]);
299  rowvals = SCIProwGetVals(rows[r]);
300  rowcols = SCIProwGetCols(rows[r]);
301 
302  for (c = 0; c < rownnonz; ++c)
303  {
304  ind = SCIPcolGetLPPos(rowcols[c]);
305 
306  /* if column is not in LP, then return without generating cut */
307  if ( ind < 0 )
308  {
309  *row = NULL;
310  return SCIP_OKAY;
311  }
312 
313  cutcoefs[ind] -= cutcoef * rowvals[c];
314  }
315  }
316  }
317 
318  /* create cut */
319  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "%s_%d_%d", SCIPsepaGetName(sepa), SCIPgetNLPs(scip), ndisjcuts);
320  if ( SCIPgetDepth(scip) == 0 )
321  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
322  else
323  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), TRUE, FALSE, TRUE) );
324 
325  SCIP_CALL( SCIPcacheRowExtensions(scip, *row) );
326  for (c = 0; c < ncols; ++c)
327  {
328  ind = SCIPcolGetLPPos(cols[c]);
329  assert( ind >= 0 );
330  if ( ! SCIPisFeasZero(scip, cutcoefs[ind]) )
331  {
332  SCIP_CALL( SCIPaddVarToRow(scip, *row, SCIPcolGetVar(cols[c]), cutcoefs[ind] ) );
333  }
334  }
335  SCIP_CALL( SCIPflushRowExtensions(scip, *row) );
336 
337  /* try to scale the cut to integral values
338  * @todo find better but still stable disjunctive cut settings
339  */
340  if ( scale )
341  {
342  int maxdepth;
343  int depth;
344  SCIP_Longint maxdnom;
345  SCIP_Real maxscale;
346 
347  depth = SCIPgetDepth(scip);
348  assert( depth >= 0 );
349  maxdepth = SCIPgetMaxDepth(scip);
350  if ( depth == 0 )
351  {
352  maxdnom = 1000;
353  maxscale = 1000.0;
354  }
355  else if ( depth <= maxdepth/4 )
356  {
357  maxdnom = 1000;
358  maxscale = 1000.0;
359  }
360  else if ( depth <= maxdepth/2 )
361  {
362  maxdnom = 100;
363  maxscale = 100.0;
364  }
365  else
366  {
367  maxdnom = 10;
368  maxscale = 10.0;
369  }
370 
371  SCIP_CALL( SCIPmakeRowIntegral(scip, *row, -SCIPepsilon(scip), SCIPsumepsilon(scip), maxdnom, maxscale, TRUE, madeintegral) );
372  }
373 
374  return SCIP_OKAY;
375 }
376 
377 
378 /*
379  * Callback methods
380  */
381 
382 /** copy method for separator plugins (called when SCIP copies plugins) */
383 static
384 SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
385 {
386  assert( scip != NULL );
387  assert( sepa != NULL );
388  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
389 
390  /* call inclusion method of constraint handler */
392 
393  return SCIP_OKAY;
394 }
395 
396 
397 /** destructor of separator to free user data (called when SCIP is exiting) */
398 static
399 SCIP_DECL_SEPAFREE(sepaFreeDisjunctive)/*lint --e{715}*/
400 {
401  SCIP_SEPADATA* sepadata;
402 
403  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
404 
405  /* free separator data */
406  sepadata = SCIPsepaGetData(sepa);
407  assert( sepadata != NULL );
408 
409  SCIPfreeMemory(scip, &sepadata);
410 
411  SCIPsepaSetData(sepa, NULL);
412 
413  return SCIP_OKAY;
414 }
415 
416 
417 /** solving process initialization method of separator */
418 static
419 SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
420 { /*lint --e{715}*/
421  SCIP_SEPADATA* sepadata;
422 
423  sepadata = SCIPsepaGetData(sepa);
424  assert(sepadata != NULL);
425 
426  sepadata->conshdlr = SCIPfindConshdlr(scip, "SOS1");
427 
428  return SCIP_OKAY;
429 }
430 
431 
432 /** LP solution separation method for disjunctive cuts */
433 static
434 SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
435 {
436  SCIP_SEPADATA* sepadata;
437  SCIP_CONSHDLR* conshdlr;
438  SCIP_DIGRAPH* conflictgraph;
439  SCIP_ROW** rows;
440  SCIP_COL** cols;
441  SCIP_Real* cutcoefs = NULL;
442  SCIP_Real* simplexcoefs1 = NULL;
443  SCIP_Real* simplexcoefs2 = NULL;
444  SCIP_Real* coef = NULL;
445  SCIP_Real* binvrow = NULL;
446  SCIP_Real* rowsmaxval = NULL;
447  SCIP_Real* violationarray = NULL;
448  int* fixings1 = NULL;
449  int* fixings2 = NULL;
450  int* basisind = NULL;
451  int* basisrow = NULL;
452  int* varrank = NULL;
453  int* edgearray = NULL;
454  int nedges;
455  int ndisjcuts;
456  int nrelevantedges;
457  int nsos1vars;
458  int nconss;
459  int maxcuts;
460  int ncalls;
461  int depth;
462  int ncols;
463  int nrows;
464  int ind;
465  int j;
466  int i;
467 
468  assert( sepa != NULL );
469  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
470  assert( scip != NULL );
471  assert( result != NULL );
472 
473  *result = SCIP_DIDNOTRUN;
474 
475  /* only generate disjunctive cuts if we are not close to terminating */
476  if ( SCIPisStopped(scip) )
477  return SCIP_OKAY;
478 
479  /* only generate disjunctive cuts if an optimal LP solution is at hand */
481  return SCIP_OKAY;
482 
483  /* only generate disjunctive cuts if the LP solution is basic */
484  if ( ! SCIPisLPSolBasic(scip) )
485  return SCIP_OKAY;
486 
487  /* get LP data */
488  SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
489  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
490 
491  /* return if LP has no columns or no rows */
492  if ( ncols == 0 || nrows == 0 )
493  return SCIP_OKAY;
494 
495  assert( cols != NULL );
496  assert( rows != NULL );
497 
498  /* get sepa data */
499  sepadata = SCIPsepaGetData(sepa);
500  assert( sepadata != NULL );
501 
502  /* get constraint handler */
503  conshdlr = sepadata->conshdlr;
504  if ( conshdlr == NULL )
505  return SCIP_OKAY;
506 
507  /* get number of constraints */
508  nconss = SCIPconshdlrGetNConss(conshdlr);
509  if ( nconss == 0 )
510  return SCIP_OKAY;
511 
512  /* check for maxdepth < depth, maxinvcutsroot = 0 and maxinvcuts = 0 */
513  depth = SCIPgetDepth(scip);
514  if ( ( sepadata->maxdepth >= 0 && sepadata->maxdepth < depth )
515  || ( depth == 0 && sepadata->maxinvcutsroot == 0 )
516  || ( depth > 0 && sepadata->maxinvcuts == 0 ) )
517  return SCIP_OKAY;
518 
519  /* only call the cut separator a given number of times at each node */
520  ncalls = SCIPsepaGetNCallsAtNode(sepa);
521  if ( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
522  || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
523  return SCIP_OKAY;
524 
525  /* get conflict graph and number of conflict graph edges (note that the digraph arcs were added in both directions) */
526  conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
527  nedges = (int)SCIPceil(scip, (SCIP_Real)SCIPdigraphGetNArcs(conflictgraph)/2);
528 
529  /* if too many conflict graph edges, the separator can be slow: delay it until no other cuts have been found */
530  if ( sepadata->maxconfsdelay >= 0 && nedges >= sepadata->maxconfsdelay )
531  {
532  int ncutsfound;
533 
534  ncutsfound = SCIPgetNCutsFound(scip);
535  if ( ncutsfound > sepadata->lastncutsfound || ! SCIPsepaWasLPDelayed(sepa) )
536  {
537  sepadata->lastncutsfound = ncutsfound;
538  *result = SCIP_DELAYED;
539  return SCIP_OKAY;
540  }
541  }
542 
543  /* check basis status */
544  for (j = 0; j < ncols; ++j)
545  {
546  if ( SCIPcolGetBasisStatus(cols[j]) == SCIP_BASESTAT_ZERO )
547  return SCIP_OKAY;
548  }
549 
550  /* get number of SOS1 variables */
551  nsos1vars = SCIPgetNSOS1Vars(conshdlr);
552 
553  /* allocate buffer arrays */
554  SCIP_CALL( SCIPallocBufferArray(scip, &edgearray, nedges) );
555  SCIP_CALL( SCIPallocBufferArray(scip, &fixings1, nedges) );
556  SCIP_CALL( SCIPallocBufferArray(scip, &fixings2, nedges) );
557  SCIP_CALL( SCIPallocBufferArray(scip, &violationarray, nedges) );
558 
559  /* get all violated conflicts {i, j} in the conflict graph and sort them based on the degree of a violation value */
560  nrelevantedges = 0;
561  for (j = 0; j < nsos1vars; ++j)
562  {
563  SCIP_VAR* var;
564 
565  var = SCIPnodeGetVarSOS1(conflictgraph, j);
566 
568  {
569  int* succ;
570  int nsucc;
571 
572  /* get successors and number of successors */
573  nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
574  succ = SCIPdigraphGetSuccessors(conflictgraph, j);
575 
576  for (i = 0; i < nsucc; ++i)
577  {
578  SCIP_VAR* varsucc;
579  int succind;
580 
581  succind = succ[i];
582  varsucc = SCIPnodeGetVarSOS1(conflictgraph, succind);
583  if ( SCIPvarIsActive(varsucc) && succind < j && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, varsucc) ) &&
585  {
586  fixings1[nrelevantedges] = j;
587  fixings2[nrelevantedges] = succind;
588  edgearray[nrelevantedges] = nrelevantedges;
589  violationarray[nrelevantedges++] = SCIPgetSolVal(scip, NULL, var) * SCIPgetSolVal(scip, NULL, varsucc);
590  }
591  }
592  }
593  }
594 
595  /* sort violation score values */
596  if ( nrelevantedges > 0)
597  SCIPsortDownRealInt(violationarray, edgearray, nrelevantedges);
598  else
599  {
600  SCIPfreeBufferArrayNull(scip, &violationarray);
601  SCIPfreeBufferArrayNull(scip, &fixings2);
602  SCIPfreeBufferArrayNull(scip, &fixings1);
603  SCIPfreeBufferArrayNull(scip, &edgearray);
604 
605  return SCIP_OKAY;
606  }
607  SCIPfreeBufferArrayNull(scip, &violationarray);
608 
609  /* compute maximal number of cuts */
610  if ( SCIPgetDepth(scip) == 0 )
611  maxcuts = MIN(sepadata->maxinvcutsroot, nrelevantedges);
612  else
613  maxcuts = MIN(sepadata->maxinvcuts, nrelevantedges);
614  assert( maxcuts > 0 );
615 
616  /* allocate buffer arrays */
617  SCIP_CALL( SCIPallocBufferArray(scip, &varrank, ncols) );
618  SCIP_CALL( SCIPallocBufferArray(scip, &rowsmaxval, nrows) );
619  SCIP_CALL( SCIPallocBufferArray(scip, &basisrow, ncols) );
620  SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
621  SCIP_CALL( SCIPallocBufferArray(scip, &coef, ncols) );
622  SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs1, ncols) );
623  SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs2, ncols) );
624  SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
625  SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
626 
627  /* get basis indices */
628  SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
629 
630  /* create vector "basisrow" with basisrow[column of non-slack basis variable] = corresponding row of B^-1;
631  * compute maximum absolute value of nonbasic row coefficients */
632  for (j = 0; j < nrows; ++j)
633  {
634  SCIP_COL** rowcols;
635  SCIP_Real* rowvals;
636  SCIP_ROW* row;
637  SCIP_Real val;
638  SCIP_Real max = 0.0;
639  int nnonz;
640 
641  /* fill basisrow vector */
642  ind = basisind[j];
643  if ( ind >= 0 )
644  basisrow[ind] = j;
645 
646  /* compute maximum absolute value of nonbasic row coefficients */
647  row = rows[j];
648  assert( row != NULL );
649  rowvals = SCIProwGetVals(row);
650  nnonz = SCIProwGetNNonz(row);
651  rowcols = SCIProwGetCols(row);
652 
653  for (i = 0; i < nnonz; ++i)
654  {
656  {
657  val = REALABS(rowvals[i]);
658  if ( SCIPisFeasGT(scip, val, max) )
659  max = REALABS(val);
660  }
661  }
662 
663  /* handle slack variable coefficient and save maximum value */
664  rowsmaxval[j] = MAX(max, 1.0);
665  }
666 
667  /* initialize variable ranks with -1 */
668  for (j = 0; j < ncols; ++j)
669  varrank[j] = -1;
670 
671  /* free buffer array */
672  SCIPfreeBufferArrayNull(scip, &basisind);
673 
674  /* for the most promising disjunctions: try to generate disjunctive cuts */
675  ndisjcuts = 0;
676  for (i = 0; i < maxcuts; ++i)
677  {
678  SCIP_Bool madeintegral;
679  SCIP_Real cutlhs1;
680  SCIP_Real cutlhs2;
681  SCIP_ROW* row = NULL;
682  SCIP_VAR* var;
683  SCIP_COL* col;
684 
685  int nonbasicnumber;
686  int cutrank = 0;
687  int edgenumber;
688  int rownnonz;
689 
690  edgenumber = edgearray[i];
691 
692  /* determine first simplex row */
693  var = SCIPnodeGetVarSOS1(conflictgraph, fixings1[edgenumber]);
694  col = SCIPvarGetCol(var);
695  ind = SCIPcolGetLPPos(col);
696  assert( ind >= 0 );
697  assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );
698 
699  /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
700  SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
701  SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
702 
703  /* get the simplex-coefficients of the non-basic variables */
704  SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs1, &nonbasicnumber) );
705 
706  /* get rank of variable if not known already */
707  if ( varrank[ind] < 0 )
708  varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
709  cutrank = MAX(cutrank, varrank[ind]);
710 
711  /* get right hand side of simplex talbeau row */
712  cutlhs1 = SCIPcolGetPrimsol(col);
713 
714 
715  /* determine second simplex row */
716  var = SCIPnodeGetVarSOS1(conflictgraph, fixings2[edgenumber]);
717  col = SCIPvarGetCol(var);
718  ind = SCIPcolGetLPPos(col);
719  assert( ind >= 0 );
720  assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );
721 
722  /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
723  SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
724  SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
725 
726  /* get the simplex-coefficients of the non-basic variables */
727  SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs2, &nonbasicnumber) );
728 
729  /* get rank of variable if not known already */
730  if ( varrank[ind] < 0 )
731  varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
732  cutrank = MAX(cutrank, varrank[ind]);
733 
734  /* get right hand side of simplex talbeau row */
735  cutlhs2 = SCIPcolGetPrimsol(col);
736 
737  /* add coefficients to cut */
738  SCIP_CALL( generateDisjCutSOS1(scip, sepa, rows, nrows, cols, ncols, ndisjcuts, TRUE, cutlhs1, cutlhs2, simplexcoefs1, simplexcoefs2, cutcoefs, &row, &madeintegral) );
739  if ( row == NULL )
740  continue;
741 
742  /* raise cutrank for present cut */
743  ++cutrank;
744 
745  /* check if there are numerical evidences */
746  if ( ( madeintegral && ( sepadata->maxrankintegral == -1 || cutrank <= sepadata->maxrankintegral ) )
747  || ( ! madeintegral && ( sepadata->maxrank == -1 || cutrank <= sepadata->maxrank ) ) )
748  {
749  /* possibly add cut to LP if it is useful; in case the lhs of the cut is minus infinity (due to scaling) the cut is useless */
750  rownnonz = SCIProwGetNNonz(row);
751  if ( rownnonz > 0 && ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
752  {
753  SCIP_Bool infeasible;
754 
755  /* set cut rank */
756  SCIProwChgRank(row, cutrank);
757 
758  /* add cut */
759  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
760  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
761  if ( infeasible )
762  {
763  *result = SCIP_CUTOFF;
764  break;
765  }
766  ++ndisjcuts;
767  }
768  }
769 
770  /* release row */
771  SCIP_CALL( SCIPreleaseRow(scip, &row) );
772  }
773 
774  /* save total number of cuts found so far */
775  sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
776 
777  /* evaluate the result of the separation */
778  if ( *result != SCIP_CUTOFF )
779  {
780  if ( ndisjcuts > 0 )
781  *result = SCIP_SEPARATED;
782  else
783  *result = SCIP_DIDNOTFIND;
784  }
785 
786  SCIPdebugMessage("Number of found disjunctive cuts: %d.\n", ndisjcuts);
787 
788  /* free buffer arrays */
789  SCIPfreeBufferArrayNull(scip, &cutcoefs);
790  SCIPfreeBufferArrayNull(scip, &simplexcoefs2);
791  SCIPfreeBufferArrayNull(scip, &simplexcoefs1);
792  SCIPfreeBufferArrayNull(scip, &coef);
793  SCIPfreeBufferArrayNull(scip, &binvrow);
794  SCIPfreeBufferArrayNull(scip, &basisrow);
795  SCIPfreeBufferArrayNull(scip, &fixings2);
796  SCIPfreeBufferArrayNull(scip, &fixings1);
797  SCIPfreeBufferArrayNull(scip, &edgearray);
798  SCIPfreeBufferArrayNull(scip, &rowsmaxval);
799  SCIPfreeBufferArrayNull(scip, &varrank);
800 
801  return SCIP_OKAY;
802 }
803 
804 
805 /** creates the disjunctive cut separator and includes it in SCIP */
807  SCIP* scip /**< SCIP data structure */
808  )
809 {
810  SCIP_SEPADATA* sepadata = NULL;
811  SCIP_SEPA* sepa = NULL;
812 
813  /* create separator data */
814  SCIP_CALL( SCIPallocMemory(scip, &sepadata) );
815  sepadata->conshdlr = NULL;
816  sepadata->lastncutsfound = 0;
817 
818  /* include separator */
820  SEPA_USESSUBSCIP, SEPA_DELAY, sepaExeclpDisjunctive, NULL, sepadata) );
821 
822  assert( sepa != NULL );
823 
824  /* set non fundamental callbacks via setter functions */
825  SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyDisjunctive) );
826  SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeDisjunctive) );
827  SCIP_CALL( SCIPsetSepaInitsol(scip, sepa, sepaInitsolDisjunctive) );
828 
829  /* add separator parameters */
830  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxdepth",
831  "node depth of separating bipartite disjunctive cuts (-1: no limit)",
832  &sepadata->maxdepth, TRUE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
833 
834  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrounds",
835  "maximal number of separation rounds per iteration in a branching node (-1: no limit)",
836  &sepadata->maxrounds, TRUE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
837 
838  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxroundsroot",
839  "maximal number of separation rounds in the root node (-1: no limit)",
840  &sepadata->maxroundsroot, TRUE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
841 
842  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcuts",
843  "maximal number of cuts investigated per iteration in a branching node",
844  &sepadata->maxinvcuts, TRUE, DEFAULT_MAXINVCUTS, 0, INT_MAX, NULL, NULL) );
845 
846  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcutsroot",
847  "maximal number of cuts investigated per iteration in the root node",
848  &sepadata->maxinvcutsroot, TRUE, DEFAULT_MAXINVCUTSROOT, 0, INT_MAX, NULL, NULL) );
849 
850  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxconfsdelay",
851  "delay separation if number of conflict graph edges is larger than predefined value (-1: no limit)",
852  &sepadata->maxconfsdelay, TRUE, DEFAULT_MAXCONFSDELAY, -1, INT_MAX, NULL, NULL) );
853 
854  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrank",
855  "maximal rank of a disj. cut that could not be scaled to integral coefficients (-1: unlimited)",
856  &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
857 
858  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrankintegral",
859  "maximal rank of a disj. cut that could be scaled to integral coefficients (-1: unlimited)",
860  &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
861 
862  SCIP_CALL( SCIPaddRealParam(scip, "separating/" SEPA_NAME "/maxweightrange",
863  "maximal valid range max(|weights|)/min(|weights|) of row weights",
864  &sepadata->maxweightrange, TRUE, DEFAULT_MAXWEIGHTRANGE, 1.0, SCIP_REAL_MAX, NULL, NULL) );
865 
866  return SCIP_OKAY;
867 }
SCIP_RETCODE SCIPgetLPBInvRow(SCIP *scip, int r, SCIP_Real *coefs, int *inds, int *ninds)
Definition: scip.c:26881
#define DEFAULT_MAXINVCUTS
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5847
static SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
static SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41256
#define DEFAULT_MAXINVCUTSROOT
#define SCIP_MAXSTRLEN
Definition: def.h:198
SCIP_RETCODE SCIPincludeSepaDisjunctive(SCIP *scip)
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4292
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:5960
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18914
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18860
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:30469
#define SEPA_PRIORITY
#define FALSE
Definition: def.h:53
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
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:18962
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41580
#define DEFAULT_MAXWEIGHTRANGE
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26426
disjunctive cut separator
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34593
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18880
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:30577
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip.c:6687
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:544
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:633
SCIP_RETCODE SCIPsetSepaInitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINITSOL((*sepainitsol)))
Definition: scip.c:6735
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition: scip.c:26659
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
#define SEPA_MAXBOUNDDIST
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18725
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18673
int SCIPgetNCutsFound(SCIP *scip)
Definition: scip.c:37607
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41592
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41317
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20355
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18924
SCIP_VAR * SCIPnodeGetVarSOS1(SCIP_DIGRAPH *conflictgraph, int node)
Definition: cons_sos1.c:9898
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18638
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:19003
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:40692
int SCIPgetMaxDepth(SCIP *scip)
Definition: scip.c:37800
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19125
static SCIP_DECL_SEPAFREE(sepaFreeDisjunctive)
SCIP_RETCODE SCIPgetLPBInvARow(SCIP *scip, int r, SCIP_Real *binvrow, SCIP_Real *coefs, int *inds, int *ninds)
Definition: scip.c:26952
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16669
#define REALABS(x)
Definition: def.h:148
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26737
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41245
#define DEFAULT_MAXCONFSDELAY
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_RETCODE SCIPmakeRowIntegral(SCIP *scip, SCIP_ROW *row, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Bool *success)
Definition: scip.c:27990
#define SEPA_DESC
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37045
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41554
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:27616
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41219
static SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:5945
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:554
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:19136
#define SCIP_Bool
Definition: def.h:50
SCIP_Bool SCIPsepaWasLPDelayed(SCIP_SEPA *sepa)
Definition: sepa.c:870
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
Definition: scip.c:6671
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20427
#define SEPA_FREQ
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27798
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE generateDisjCutSOS1(SCIP *scip, SCIP_SEPA *sepa, SCIP_ROW **rows, int nrows, SCIP_COL **cols, int ncols, int ndisjcuts, SCIP_Bool scale, SCIP_Real cutlhs1, SCIP_Real cutlhs2, SCIP_Real *simplexcoefs1, SCIP_Real *simplexcoefs2, SCIP_Real *cutcoefs, SCIP_ROW **row, SCIP_Bool *madeintegral)
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:5927
static int getVarRank(SCIP *scip, SCIP_Real *binvrow, SCIP_Real *rowsmaxval, SCIP_Real maxweightrange, SCIP_ROW **rows, int nrows)
#define DEFAULT_MAXROUNDS
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18605
static SCIP_RETCODE getSimplexCoefficients(SCIP *scip, SCIP_ROW **rows, int nrows, SCIP_COL **cols, int ncols, SCIP_Real *coef, SCIP_Real *binvrow, SCIP_Real *simplexcoefs, int *nonbasicnumber)
#define SEPA_NAME
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:37750
#define SCIP_REAL_MAX
Definition: def.h:125
SCIP_RETCODE SCIPgetLPBasisInd(SCIP *scip, int *basisind)
Definition: scip.c:26853
SCIP_DIGRAPH * SCIPgetConflictgraphSOS1(SCIP_CONSHDLR *conshdlr)
Definition: cons_sos1.c:9799
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41378
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27821
#define DEFAULT_MAXROUNDSROOT
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18870
#define SCIP_Real
Definition: def.h:124
#define MIN(x, y)
Definition: memory.c:63
int SCIPgetNSOS1Vars(SCIP_CONSHDLR *conshdlr)
Definition: cons_sos1.c:9821
constraint handler for SOS type 1 constraints
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28321
#define DEFAULT_MAXRANKINTEGRAL
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27725
#define SCIP_Longint
Definition: def.h:109
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
Definition: sepa.c:760
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18615
SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28121
#define SEPA_DELAY
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18835
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16628
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:26834
#define DEFAULT_MAXRANK
SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
Definition: scip.c:6629
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18684
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_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:40706
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27851
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:38
#define DEFAULT_MAXDEPTH
#define SEPA_USESSUBSCIP