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-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file 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  * Cut coefficients belonging to integer variables can be strengthened by the 'monoidal cut strengthening' procedure, see@n
28  * "Strengthening cuts for mixed integer programs"@n
29  * Egon Balas, Robert G. Jeroslow, European Journal of Operational Research, Volume 4, Issue 4, 1980, Pages 224-234
30  */
31 
32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33 
34 #include <assert.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "scip/sepa_disjunctive.h"
38 #include "scip/cons_sos1.h"
39 
40 
41 #define SEPA_NAME "disjunctive"
42 #define SEPA_DESC "disjunctive cut separator"
43 #define SEPA_PRIORITY 10 /**< priority for separation */
44 #define SEPA_FREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
45 #define SEPA_MAXBOUNDDIST 0.0 /**< maximal relative distance from the current node's dual bound to primal bound
46  * compared to best node's dual bound for applying separation.*/
47 #define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
48 #define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
49 
50 #define DEFAULT_MAXRANK 20 /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
51 #define DEFAULT_MAXRANKINTEGRAL -1 /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
52 #define DEFAULT_MAXWEIGHTRANGE 1e+03 /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
53 #define DEFAULT_STRENGTHEN TRUE /**< strengthen cut if integer variables are present */
54 
55 #define DEFAULT_MAXDEPTH -1 /**< node depth of separating cuts (-1: no limit) */
56 #define DEFAULT_MAXROUNDS 25 /**< maximal number of separation rounds in a branching node (-1: no limit) */
57 #define DEFAULT_MAXROUNDSROOT 100 /**< maximal number of separation rounds in the root node (-1: no limit) */
58 #define DEFAULT_MAXINVCUTS 50 /**< maximal number of cuts investigated per iteration in a branching node */
59 #define DEFAULT_MAXINVCUTSROOT 250 /**< maximal number of cuts investigated per iteration in the root node */
60 #define DEFAULT_MAXCONFSDELAY 100000 /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
61 
62 
63 /** separator data */
64 struct SCIP_SepaData
65 {
66  SCIP_Bool strengthen; /**< strengthen cut if integer variables are present */
67  SCIP_CONSHDLR* conshdlr; /**< SOS1 constraint handler */
68  SCIP_Real maxweightrange; /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
69  int maxrank; /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
70  int maxrankintegral; /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
71  int maxdepth; /**< node depth of separating cuts (-1: no limit) */
72  int maxrounds; /**< maximal number of separation rounds in a branching node (-1: no limit) */
73  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: no limit) */
74  int maxinvcuts; /**< maximal number of cuts separated per iteration in a branching node */
75  int maxinvcutsroot; /**< maximal number of cuts separated per iteration in the root node */
76  int maxconfsdelay; /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
77  int lastncutsfound; /**< total number of cuts found after last call of separator */
78 };
79 
80 
81 /** gets rank of variable corresponding to row of \f$B^{-1}\f$ */
82 static
83 int getVarRank(
84  SCIP* scip, /**< SCIP pointer */
85  SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
86  SCIP_Real* rowsmaxval, /**< maximal row multiplicator from nonbasic matrix A_N */
87  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
88  SCIP_ROW** rows, /**< rows of LP relaxation of scip */
89  int nrows /**< number of rows */
90  )
91 {
92  SCIP_Real maxweight = 0.0;
93  int maxrank = 0;
94  int r;
95 
96  assert( scip != NULL );
97  assert( binvrow != NULL || nrows == 0 );
98  assert( rowsmaxval != NULL || nrows == 0 );
99  assert( rows != NULL || nrows == 0 );
100 
101  /* compute maximum row weights resulting from multiplication */
102  for (r = 0; r < nrows; ++r)
103  {
104  SCIP_Real val;
105 
106  val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
107  if ( SCIPisGT(scip, val, maxweight) )
108  maxweight = val;
109  }
110 
111  /* compute rank */
112  for (r = 0; r < nrows; ++r)
113  {
114  SCIP_Real val;
115  int rank;
116 
117  val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
118  rank = SCIProwGetRank(rows[r]);/*lint !e613*/
119  if ( rank > maxrank && SCIPisGT(scip, val * maxweightrange, maxweight) )
120  maxrank = rank;
121  }
122 
123  return maxrank;
124 }
125 
126 
127 /** gets the nonbasic coefficients of a simplex row */
128 static
130  SCIP* scip, /**< SCIP pointer */
131  SCIP_ROW** rows, /**< LP rows */
132  int nrows, /**< number LP rows */
133  SCIP_COL** cols, /**< LP columns */
134  int ncols, /**< number of LP columns */
135  SCIP_Real* coef, /**< row of \f$B^{-1} \cdot A\f$ */
136  SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
137  SCIP_Real* simplexcoefs, /**< pointer to store the nonbasic simplex-coefficients */
138  int* nonbasicnumber /**< pointer to store the number of nonbasic simplex-coefficients */
139  )
140 {
141  int r;
142  int c;
143 
144  assert( scip != NULL );
145  assert( rows != NULL );
146  assert( nonbasicnumber != NULL );
147  assert( simplexcoefs != NULL );
148  assert( cols != NULL );
149 
150  *nonbasicnumber = 0;
151 
152  /* note: the non-slack variables have to be added first (see the function generateDisjCutSOS1()) */
153 
154  /* get simplex-coefficients of the non-basic non-slack variables */
155  for (c = 0; c < ncols; ++c)
156  {
157  SCIP_COL* col;
158 
159  col = cols[c];
160  assert( col != NULL );
162  simplexcoefs[(*nonbasicnumber)++] = coef[c];
163  }
164 
165  /* get simplex-coefficients of the non-basic slack variables */
166  for (r = 0; r < nrows; ++r)
167  {
168  SCIP_ROW* row;
169  row = rows[r];
170  assert( row != NULL );
171 
173  {
174  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, row) - SCIProwGetRhs(row)) || SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, row) - SCIProwGetLhs(row)) );
175 
176  simplexcoefs[(*nonbasicnumber)++] = binvrow[r];
177  }
178  }
179 
180  return SCIP_OKAY;
181 }
182 
183 
184 /** computes a disjunctive cut inequality based on two simplex taubleau rows */
185 static
187  SCIP* scip, /**< SCIP pointer */
188  SCIP_SEPA* sepa, /**< separator */
189  SCIP_ROW** rows, /**< LP rows */
190  int nrows, /**< number of LP rows */
191  SCIP_COL** cols, /**< LP columns */
192  int ncols, /**< number of LP columns */
193  int ndisjcuts, /**< number of disjunctive cuts found so far */
194  SCIP_Bool scale, /**< should cut be scaled */
195  SCIP_Bool strengthen, /**< should cut be strengthened if integer variables are present */
196  SCIP_Real cutlhs1, /**< left hand side of the first simplex row */
197  SCIP_Real cutlhs2, /**< left hand side of the second simplex row */
198  SCIP_Real bound1, /**< bound of first simplex row */
199  SCIP_Real bound2, /**< bound of second simplex row */
200  SCIP_Real* simplexcoefs1, /**< simplex coefficients of first row */
201  SCIP_Real* simplexcoefs2, /**< simplex coefficients of second row */
202  SCIP_Real* cutcoefs, /**< pointer to store cut coefficients (length: nscipvars) */
203  SCIP_ROW** row, /**< pointer to store disjunctive cut inequality */
204  SCIP_Bool* madeintegral /**< pointer to store whether cut has been scaled to integral values */
205  )
206 {
207  char cutname[SCIP_MAXSTRLEN];
208  SCIP_COL** rowcols;
209  SCIP_COL* col;
210  SCIP_Real* rowvals;
211  SCIP_Real lhsrow;
212  SCIP_Real rhsrow;
213  SCIP_Real cutlhs;
214  SCIP_Real sgn;
215  SCIP_Real lb;
216  SCIP_Real ub;
217  int nonbasicnumber = 0;
218  int rownnonz;
219  int ind;
220  int r;
221  int c;
222 
223  assert( scip != NULL );
224  assert( row != NULL );
225  assert( rows != NULL );
226  assert( cols != NULL );
227  assert( simplexcoefs1 != NULL );
228  assert( simplexcoefs2 != NULL );
229  assert( cutcoefs != NULL );
230  assert( sepa != NULL );
231  assert( madeintegral != NULL );
232 
233  *madeintegral = FALSE;
234 
235  /* check signs */
236  if ( SCIPisFeasPositive(scip, cutlhs1) == SCIPisFeasPositive(scip, cutlhs2) )
237  sgn = 1.0;
238  else
239  sgn = -1.0;
240 
241  /* check bounds */
242  if ( SCIPisInfinity(scip, REALABS(bound1)) || SCIPisInfinity(scip, REALABS(bound2)) )
243  strengthen = FALSE;
244 
245  /* compute left hand side of row (a later update is possible, see below) */
246  cutlhs = sgn * cutlhs1 * cutlhs2;
247 
248  /* add cut-coefficients of the non-basic non-slack variables */
249  for (c = 0; c < ncols; ++c)
250  {
251  col = cols[c];
252  assert( col != NULL );
253  ind = SCIPcolGetLPPos(col);
254  assert( ind >= 0 );
255 
257  {
258  lb = SCIPcolGetLb(col);
259 
260  /* for integer variables we may obtain stronger coefficients */
261  if ( strengthen && SCIPcolIsIntegral(col) )
262  {
263  SCIP_Real mval;
264  SCIP_Real mvalfloor;
265  SCIP_Real mvalceil;
266 
267  mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
268  mvalfloor = SCIPfloor(scip, mval);
269  mvalceil = SCIPceil(scip, mval);
270 
271  cutcoefs[ind] = MIN(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] - mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] + mvalceil * bound2));
272  assert( SCIPisFeasLE(scip, cutcoefs[ind], MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
273  }
274  else
275  cutcoefs[ind] = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
276 
277  cutlhs += cutcoefs[ind] * lb;
278  ++nonbasicnumber;
279  }
280  else if ( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_UPPER )
281  {
282  ub = SCIPcolGetUb(col);
283 
284  /* for integer variables we may obtain stronger coefficients */
285  if ( strengthen && SCIPcolIsIntegral(col) )
286  {
287  SCIP_Real mval;
288  SCIP_Real mvalfloor;
289  SCIP_Real mvalceil;
290 
291  mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
292  mvalfloor = SCIPfloor(scip, -mval);
293  mvalceil = SCIPceil(scip, -mval);
294 
295  cutcoefs[ind] = MAX(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] + mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] - mvalceil * bound2));
296  assert( SCIPisFeasLE(scip, -cutcoefs[ind], -MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
297  }
298  else
299  cutcoefs[ind] = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
300 
301  cutlhs += cutcoefs[ind] * ub;
302  ++nonbasicnumber;
303  }
304  else
305  {
306  assert( SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_ZERO );
307  cutcoefs[ind] = 0.0;
308  }
309  }
310 
311  /* add cut-coefficients of the non-basic slack variables */
312  for (r = 0; r < nrows; ++r)
313  {
314  rhsrow = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]);
315  lhsrow = SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]);
316 
317  assert( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_ZERO );
318  assert( SCIPisFeasZero(scip, lhsrow - rhsrow) || SCIPisNegative(scip, lhsrow - rhsrow) );
319  assert( SCIProwIsInLP(rows[r]) );
320 
321  if ( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_BASIC )
322  {
323  SCIP_Real cutcoef;
324 
325  if ( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_UPPER )
326  {
327  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetRhs(rows[r])) );
328 
329  cutcoef = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
330  cutlhs -= cutcoef * rhsrow;
331  ++nonbasicnumber;
332  }
333  else /* SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER */
334  {
335  assert( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER );
336  assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetLhs(rows[r])) );
337 
338  cutcoef = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
339  cutlhs -= cutcoef * lhsrow;
340  ++nonbasicnumber;
341  }
342 
343  rownnonz = SCIProwGetNNonz(rows[r]);
344  rowvals = SCIProwGetVals(rows[r]);
345  rowcols = SCIProwGetCols(rows[r]);
346 
347  for (c = 0; c < rownnonz; ++c)
348  {
349  ind = SCIPcolGetLPPos(rowcols[c]);
350 
351  /* if column is not in LP, then return without generating cut */
352  if ( ind < 0 )
353  {
354  *row = NULL;
355  return SCIP_OKAY;
356  }
357 
358  cutcoefs[ind] -= cutcoef * rowvals[c];
359  }
360  }
361  }
362 
363  /* create cut */
364  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "%s_%d_%d", SCIPsepaGetName(sepa), SCIPgetNLPs(scip), ndisjcuts);
365  if ( SCIPgetDepth(scip) == 0 )
366  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
367  else
368  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), TRUE, FALSE, TRUE) );
369 
370  SCIP_CALL( SCIPcacheRowExtensions(scip, *row) );
371  for (c = 0; c < ncols; ++c)
372  {
373  ind = SCIPcolGetLPPos(cols[c]);
374  assert( ind >= 0 );
375  if ( ! SCIPisFeasZero(scip, cutcoefs[ind]) )
376  {
377  SCIP_CALL( SCIPaddVarToRow(scip, *row, SCIPcolGetVar(cols[c]), cutcoefs[ind] ) );
378  }
379  }
380  SCIP_CALL( SCIPflushRowExtensions(scip, *row) );
381 
382  /* try to scale the cut to integral values
383  * @todo find better but still stable disjunctive cut settings
384  */
385  if ( scale )
386  {
387  int maxdepth;
388  int depth;
389  SCIP_Longint maxdnom;
390  SCIP_Real maxscale;
391 
392  depth = SCIPgetDepth(scip);
393  assert( depth >= 0 );
394  maxdepth = SCIPgetMaxDepth(scip);
395  if ( depth == 0 )
396  {
397  maxdnom = 1000;
398  maxscale = 1000.0;
399  }
400  else if ( depth <= maxdepth/4 )
401  {
402  maxdnom = 1000;
403  maxscale = 1000.0;
404  }
405  else if ( depth <= maxdepth/2 )
406  {
407  maxdnom = 100;
408  maxscale = 100.0;
409  }
410  else
411  {
412  maxdnom = 10;
413  maxscale = 10.0;
414  }
415 
416  SCIP_CALL( SCIPmakeRowIntegral(scip, *row, -SCIPepsilon(scip), SCIPsumepsilon(scip), maxdnom, maxscale, TRUE, madeintegral) );
417  }
418 
419  return SCIP_OKAY;
420 }
421 
422 
423 /*
424  * Callback methods
425  */
426 
427 /** copy method for separator plugins (called when SCIP copies plugins) */
428 static
429 SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
430 {
431  assert( scip != NULL );
432  assert( sepa != NULL );
433  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
434 
435  /* call inclusion method of constraint handler */
437 
438  return SCIP_OKAY;
439 }
440 
441 
442 /** destructor of separator to free user data (called when SCIP is exiting) */
443 static
444 SCIP_DECL_SEPAFREE(sepaFreeDisjunctive)/*lint --e{715}*/
445 {
446  SCIP_SEPADATA* sepadata;
447 
448  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
449 
450  /* free separator data */
451  sepadata = SCIPsepaGetData(sepa);
452  assert( sepadata != NULL );
453 
454  SCIPfreeMemory(scip, &sepadata);
455 
456  SCIPsepaSetData(sepa, NULL);
457 
458  return SCIP_OKAY;
459 }
460 
461 
462 /** solving process initialization method of separator */
463 static
464 SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
465 { /*lint --e{715}*/
466  SCIP_SEPADATA* sepadata;
467 
468  sepadata = SCIPsepaGetData(sepa);
469  assert(sepadata != NULL);
470 
471  sepadata->conshdlr = SCIPfindConshdlr(scip, "SOS1");
472 
473  return SCIP_OKAY;
474 }
475 
476 
477 /** LP solution separation method for disjunctive cuts */
478 static
479 SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
480 {
481  SCIP_SEPADATA* sepadata;
482  SCIP_CONSHDLR* conshdlr;
483  SCIP_DIGRAPH* conflictgraph;
484  SCIP_ROW** rows;
485  SCIP_COL** cols;
486  SCIP_Real* cutcoefs = NULL;
487  SCIP_Real* simplexcoefs1 = NULL;
488  SCIP_Real* simplexcoefs2 = NULL;
489  SCIP_Real* coef = NULL;
490  SCIP_Real* binvrow = NULL;
491  SCIP_Real* rowsmaxval = NULL;
492  SCIP_Real* violationarray = NULL;
493  int* fixings1 = NULL;
494  int* fixings2 = NULL;
495  int* basisind = NULL;
496  int* basisrow = NULL;
497  int* varrank = NULL;
498  int* edgearray = NULL;
499  int nedges;
500  int ndisjcuts;
501  int nrelevantedges;
502  int nsos1vars;
503  int nconss;
504  int maxcuts;
505  int ncalls;
506  int depth;
507  int ncols;
508  int nrows;
509  int ind;
510  int j;
511  int i;
512 
513  assert( sepa != NULL );
514  assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
515  assert( scip != NULL );
516  assert( result != NULL );
517 
518  *result = SCIP_DIDNOTRUN;
519 
520  /* only generate disjunctive cuts if we are not close to terminating */
521  if ( SCIPisStopped(scip) )
522  return SCIP_OKAY;
523 
524  /* only generate disjunctive cuts if an optimal LP solution is at hand */
526  return SCIP_OKAY;
527 
528  /* only generate disjunctive cuts if the LP solution is basic */
529  if ( ! SCIPisLPSolBasic(scip) )
530  return SCIP_OKAY;
531 
532  /* get LP data */
533  SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
534  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
535 
536  /* return if LP has no columns or no rows */
537  if ( ncols == 0 || nrows == 0 )
538  return SCIP_OKAY;
539 
540  assert( cols != NULL );
541  assert( rows != NULL );
542 
543  /* get sepa data */
544  sepadata = SCIPsepaGetData(sepa);
545  assert( sepadata != NULL );
546 
547  /* get constraint handler */
548  conshdlr = sepadata->conshdlr;
549  if ( conshdlr == NULL )
550  return SCIP_OKAY;
551 
552  /* get number of constraints */
553  nconss = SCIPconshdlrGetNConss(conshdlr);
554  if ( nconss == 0 )
555  return SCIP_OKAY;
556 
557  /* check for maxdepth < depth, maxinvcutsroot = 0 and maxinvcuts = 0 */
558  depth = SCIPgetDepth(scip);
559  if ( ( sepadata->maxdepth >= 0 && sepadata->maxdepth < depth )
560  || ( depth == 0 && sepadata->maxinvcutsroot == 0 )
561  || ( depth > 0 && sepadata->maxinvcuts == 0 ) )
562  return SCIP_OKAY;
563 
564  /* only call the cut separator a given number of times at each node */
565  ncalls = SCIPsepaGetNCallsAtNode(sepa);
566  if ( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
567  || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
568  return SCIP_OKAY;
569 
570  /* get conflict graph and number of conflict graph edges (note that the digraph arcs were added in both directions) */
571  conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
572  nedges = (int)SCIPceil(scip, (SCIP_Real)SCIPdigraphGetNArcs(conflictgraph)/2);
573 
574  /* if too many conflict graph edges, the separator can be slow: delay it until no other cuts have been found */
575  if ( sepadata->maxconfsdelay >= 0 && nedges >= sepadata->maxconfsdelay )
576  {
577  int ncutsfound;
578 
579  ncutsfound = SCIPgetNCutsFound(scip);
580  if ( ncutsfound > sepadata->lastncutsfound || ! SCIPsepaWasLPDelayed(sepa) )
581  {
582  sepadata->lastncutsfound = ncutsfound;
583  *result = SCIP_DELAYED;
584  return SCIP_OKAY;
585  }
586  }
587 
588  /* check basis status */
589  for (j = 0; j < ncols; ++j)
590  {
591  if ( SCIPcolGetBasisStatus(cols[j]) == SCIP_BASESTAT_ZERO )
592  return SCIP_OKAY;
593  }
594 
595  /* get number of SOS1 variables */
596  nsos1vars = SCIPgetNSOS1Vars(conshdlr);
597 
598  /* allocate buffer arrays */
599  SCIP_CALL( SCIPallocBufferArray(scip, &edgearray, nedges) );
600  SCIP_CALL( SCIPallocBufferArray(scip, &fixings1, nedges) );
601  SCIP_CALL( SCIPallocBufferArray(scip, &fixings2, nedges) );
602  SCIP_CALL( SCIPallocBufferArray(scip, &violationarray, nedges) );
603 
604  /* get all violated conflicts {i, j} in the conflict graph and sort them based on the degree of a violation value */
605  nrelevantedges = 0;
606  for (j = 0; j < nsos1vars; ++j)
607  {
608  SCIP_VAR* var;
609 
610  var = SCIPnodeGetVarSOS1(conflictgraph, j);
611 
613  {
614  int* succ;
615  int nsucc;
616 
617  /* get successors and number of successors */
618  nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
619  succ = SCIPdigraphGetSuccessors(conflictgraph, j);
620 
621  for (i = 0; i < nsucc; ++i)
622  {
623  SCIP_VAR* varsucc;
624  int succind;
625 
626  succind = succ[i];
627  varsucc = SCIPnodeGetVarSOS1(conflictgraph, succind);
628  if ( SCIPvarIsActive(varsucc) && succind < j && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, varsucc) ) &&
630  {
631  fixings1[nrelevantedges] = j;
632  fixings2[nrelevantedges] = succind;
633  edgearray[nrelevantedges] = nrelevantedges;
634  violationarray[nrelevantedges++] = SCIPgetSolVal(scip, NULL, var) * SCIPgetSolVal(scip, NULL, varsucc);
635  }
636  }
637  }
638  }
639 
640  /* sort violation score values */
641  if ( nrelevantedges > 0)
642  SCIPsortDownRealInt(violationarray, edgearray, nrelevantedges);
643  else
644  {
645  SCIPfreeBufferArrayNull(scip, &violationarray);
646  SCIPfreeBufferArrayNull(scip, &fixings2);
647  SCIPfreeBufferArrayNull(scip, &fixings1);
648  SCIPfreeBufferArrayNull(scip, &edgearray);
649 
650  return SCIP_OKAY;
651  }
652  SCIPfreeBufferArrayNull(scip, &violationarray);
653 
654  /* compute maximal number of cuts */
655  if ( SCIPgetDepth(scip) == 0 )
656  maxcuts = MIN(sepadata->maxinvcutsroot, nrelevantedges);
657  else
658  maxcuts = MIN(sepadata->maxinvcuts, nrelevantedges);
659  assert( maxcuts > 0 );
660 
661  /* allocate buffer arrays */
662  SCIP_CALL( SCIPallocBufferArray(scip, &varrank, ncols) );
663  SCIP_CALL( SCIPallocBufferArray(scip, &rowsmaxval, nrows) );
664  SCIP_CALL( SCIPallocBufferArray(scip, &basisrow, ncols) );
665  SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
666  SCIP_CALL( SCIPallocBufferArray(scip, &coef, ncols) );
667  SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs1, ncols) );
668  SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs2, ncols) );
669  SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
670  SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
671 
672  /* get basis indices */
673  SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
674 
675  /* create vector "basisrow" with basisrow[column of non-slack basis variable] = corresponding row of B^-1;
676  * compute maximum absolute value of nonbasic row coefficients */
677  for (j = 0; j < nrows; ++j)
678  {
679  SCIP_COL** rowcols;
680  SCIP_Real* rowvals;
681  SCIP_ROW* row;
682  SCIP_Real val;
683  SCIP_Real max = 0.0;
684  int nnonz;
685 
686  /* fill basisrow vector */
687  ind = basisind[j];
688  if ( ind >= 0 )
689  basisrow[ind] = j;
690 
691  /* compute maximum absolute value of nonbasic row coefficients */
692  row = rows[j];
693  assert( row != NULL );
694  rowvals = SCIProwGetVals(row);
695  nnonz = SCIProwGetNNonz(row);
696  rowcols = SCIProwGetCols(row);
697 
698  for (i = 0; i < nnonz; ++i)
699  {
701  {
702  val = REALABS(rowvals[i]);
703  if ( SCIPisFeasGT(scip, val, max) )
704  max = REALABS(val);
705  }
706  }
707 
708  /* handle slack variable coefficient and save maximum value */
709  rowsmaxval[j] = MAX(max, 1.0);
710  }
711 
712  /* initialize variable ranks with -1 */
713  for (j = 0; j < ncols; ++j)
714  varrank[j] = -1;
715 
716  /* free buffer array */
717  SCIPfreeBufferArrayNull(scip, &basisind);
718 
719  /* for the most promising disjunctions: try to generate disjunctive cuts */
720  ndisjcuts = 0;
721  for (i = 0; i < maxcuts; ++i)
722  {
723  SCIP_Bool madeintegral;
724  SCIP_Real cutlhs1;
725  SCIP_Real cutlhs2;
726  SCIP_Real bound1;
727  SCIP_Real bound2;
728  SCIP_ROW* row = NULL;
729  SCIP_VAR* var;
730  SCIP_COL* col;
731 
732  int nonbasicnumber;
733  int cutrank = 0;
734  int edgenumber;
735  int rownnonz;
736 
737  edgenumber = edgearray[i];
738 
739  /* determine first simplex row */
740  var = SCIPnodeGetVarSOS1(conflictgraph, fixings1[edgenumber]);
741  col = SCIPvarGetCol(var);
742  ind = SCIPcolGetLPPos(col);
743  assert( ind >= 0 );
744  assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );
745 
746  /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
747  SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
748  SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
749 
750  /* get the simplex-coefficients of the non-basic variables */
751  SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs1, &nonbasicnumber) );
752 
753  /* get rank of variable if not known already */
754  if ( varrank[ind] < 0 )
755  varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
756  cutrank = MAX(cutrank, varrank[ind]);
757 
758  /* get right hand side and bound of simplex talbeau row */
759  cutlhs1 = SCIPcolGetPrimsol(col);
760  if ( SCIPisFeasPositive(scip, cutlhs1) )
761  bound1 = SCIPcolGetUb(col);
762  else
763  bound1 = SCIPcolGetLb(col);
764 
765 
766  /* determine second simplex row */
767  var = SCIPnodeGetVarSOS1(conflictgraph, fixings2[edgenumber]);
768  col = SCIPvarGetCol(var);
769  ind = SCIPcolGetLPPos(col);
770  assert( ind >= 0 );
771  assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );
772 
773  /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
774  SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
775  SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
776 
777  /* get the simplex-coefficients of the non-basic variables */
778  SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs2, &nonbasicnumber) );
779 
780  /* get rank of variable if not known already */
781  if ( varrank[ind] < 0 )
782  varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
783  cutrank = MAX(cutrank, varrank[ind]);
784 
785  /* get right hand side and bound of simplex talbeau row */
786  cutlhs2 = SCIPcolGetPrimsol(col);
787  if ( SCIPisFeasPositive(scip, cutlhs2) )
788  bound2 = SCIPcolGetUb(col);
789  else
790  bound2 = SCIPcolGetLb(col);
791 
792  /* add coefficients to cut */
793  SCIP_CALL( generateDisjCutSOS1(scip, sepa, rows, nrows, cols, ncols, ndisjcuts, TRUE, sepadata->strengthen, cutlhs1, cutlhs2, bound1, bound2, simplexcoefs1, simplexcoefs2, cutcoefs, &row, &madeintegral) );
794  if ( row == NULL )
795  continue;
796 
797  /* raise cutrank for present cut */
798  ++cutrank;
799 
800  /* check if there are numerical evidences */
801  if ( ( madeintegral && ( sepadata->maxrankintegral == -1 || cutrank <= sepadata->maxrankintegral ) )
802  || ( ! madeintegral && ( sepadata->maxrank == -1 || cutrank <= sepadata->maxrank ) ) )
803  {
804  /* 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 */
805  rownnonz = SCIProwGetNNonz(row);
806  if ( rownnonz > 0 && ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
807  {
808  SCIP_Bool infeasible;
809 
810  /* set cut rank */
811  SCIProwChgRank(row, cutrank);
812 
813  /* add cut */
814  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
815  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
816  if ( infeasible )
817  {
818  *result = SCIP_CUTOFF;
819  break;
820  }
821  ++ndisjcuts;
822  }
823  }
824 
825  /* release row */
826  SCIP_CALL( SCIPreleaseRow(scip, &row) );
827  }
828 
829  /* save total number of cuts found so far */
830  sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
831 
832  /* evaluate the result of the separation */
833  if ( *result != SCIP_CUTOFF )
834  {
835  if ( ndisjcuts > 0 )
836  *result = SCIP_SEPARATED;
837  else
838  *result = SCIP_DIDNOTFIND;
839  }
840 
841  SCIPdebugMessage("Number of found disjunctive cuts: %d.\n", ndisjcuts);
842 
843  /* free buffer arrays */
844  SCIPfreeBufferArrayNull(scip, &cutcoefs);
845  SCIPfreeBufferArrayNull(scip, &simplexcoefs2);
846  SCIPfreeBufferArrayNull(scip, &simplexcoefs1);
847  SCIPfreeBufferArrayNull(scip, &coef);
848  SCIPfreeBufferArrayNull(scip, &binvrow);
849  SCIPfreeBufferArrayNull(scip, &basisrow);
850  SCIPfreeBufferArrayNull(scip, &fixings2);
851  SCIPfreeBufferArrayNull(scip, &fixings1);
852  SCIPfreeBufferArrayNull(scip, &edgearray);
853  SCIPfreeBufferArrayNull(scip, &rowsmaxval);
854  SCIPfreeBufferArrayNull(scip, &varrank);
855 
856  return SCIP_OKAY;
857 }
858 
859 
860 /** creates the disjunctive cut separator and includes it in SCIP */
862  SCIP* scip /**< SCIP data structure */
863  )
864 {
865  SCIP_SEPADATA* sepadata = NULL;
866  SCIP_SEPA* sepa = NULL;
867 
868  /* create separator data */
869  SCIP_CALL( SCIPallocMemory(scip, &sepadata) );
870  sepadata->conshdlr = NULL;
871  sepadata->lastncutsfound = 0;
872 
873  /* include separator */
875  SEPA_USESSUBSCIP, SEPA_DELAY, sepaExeclpDisjunctive, NULL, sepadata) );
876 
877  assert( sepa != NULL );
878 
879  /* set non fundamental callbacks via setter functions */
880  SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyDisjunctive) );
881  SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeDisjunctive) );
882  SCIP_CALL( SCIPsetSepaInitsol(scip, sepa, sepaInitsolDisjunctive) );
883 
884  /* add separator parameters */
885  SCIP_CALL( SCIPaddBoolParam(scip, "separating/"SEPA_NAME"/strengthen",
886  "strengthen cut if integer variables are present.",
887  &sepadata->strengthen, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
888 
889  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxdepth",
890  "node depth of separating bipartite disjunctive cuts (-1: no limit)",
891  &sepadata->maxdepth, TRUE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
892 
893  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrounds",
894  "maximal number of separation rounds per iteration in a branching node (-1: no limit)",
895  &sepadata->maxrounds, TRUE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
896 
897  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxroundsroot",
898  "maximal number of separation rounds in the root node (-1: no limit)",
899  &sepadata->maxroundsroot, TRUE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
900 
901  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcuts",
902  "maximal number of cuts investigated per iteration in a branching node",
903  &sepadata->maxinvcuts, TRUE, DEFAULT_MAXINVCUTS, 0, INT_MAX, NULL, NULL) );
904 
905  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcutsroot",
906  "maximal number of cuts investigated per iteration in the root node",
907  &sepadata->maxinvcutsroot, TRUE, DEFAULT_MAXINVCUTSROOT, 0, INT_MAX, NULL, NULL) );
908 
909  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxconfsdelay",
910  "delay separation if number of conflict graph edges is larger than predefined value (-1: no limit)",
911  &sepadata->maxconfsdelay, TRUE, DEFAULT_MAXCONFSDELAY, -1, INT_MAX, NULL, NULL) );
912 
913  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrank",
914  "maximal rank of a disj. cut that could not be scaled to integral coefficients (-1: unlimited)",
915  &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
916 
917  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrankintegral",
918  "maximal rank of a disj. cut that could be scaled to integral coefficients (-1: unlimited)",
919  &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
920 
921  SCIP_CALL( SCIPaddRealParam(scip, "separating/" SEPA_NAME "/maxweightrange",
922  "maximal valid range max(|weights|)/min(|weights|) of row weights",
923  &sepadata->maxweightrange, TRUE, DEFAULT_MAXWEIGHTRANGE, 1.0, SCIP_REAL_MAX, NULL, NULL) );
924 
925  return SCIP_OKAY;
926 }
SCIP_RETCODE SCIPgetLPBInvRow(SCIP *scip, int r, SCIP_Real *coefs, int *inds, int *ninds)
Definition: scip.c:26894
#define DEFAULT_MAXINVCUTS
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
static SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
static SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
#define DEFAULT_MAXINVCUTSROOT
#define SCIP_MAXSTRLEN
Definition: def.h:201
SCIP_RETCODE SCIPincludeSepaDisjunctive(SCIP *scip)
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4288
#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:5965
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:30859
#define SEPA_PRIORITY
#define FALSE
Definition: def.h:56
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:18963
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
#define DEFAULT_MAXWEIGHTRANGE
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
disjunctive cut separator
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:30967
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip.c:6718
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:6766
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition: scip.c:26672
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
#define SEPA_MAXBOUNDDIST
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18726
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18674
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
int SCIPgetNCutsFound(SCIP *scip)
Definition: scip.c:37997
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41984
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:18705
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
SCIP_VAR * SCIPnodeGetVarSOS1(SCIP_DIGRAPH *conflictgraph, int node)
Definition: cons_sos1.c:10647
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18639
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:19004
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:41118
int SCIPgetMaxDepth(SCIP *scip)
Definition: scip.c:38214
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41758
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:26965
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26750
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define DEFAULT_MAXCONFSDELAY
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:28003
#define SEPA_DESC
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37435
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
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:27629
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20598
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
static SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:5950
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:554
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:19137
#define SCIP_Bool
Definition: def.h:53
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:6702
#define SEPA_FREQ
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27811
#define MAX(x, y)
Definition: tclique_def.h:75
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:5932
static int getVarRank(SCIP *scip, SCIP_Real *binvrow, SCIP_Real *rowsmaxval, SCIP_Real maxweightrange, SCIP_ROW **rows, int nrows)
#define DEFAULT_MAXROUNDS
#define DEFAULT_STRENGTHEN
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18606
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:38140
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_RETCODE SCIPgetLPBasisInd(SCIP *scip, int *basisind)
Definition: scip.c:26866
SCIP_DIGRAPH * SCIPgetConflictgraphSOS1(SCIP_CONSHDLR *conshdlr)
Definition: cons_sos1.c:10548
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41770
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:27834
#define DEFAULT_MAXROUNDSROOT
#define REALABS(x)
Definition: def.h:151
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
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_Bool strengthen, SCIP_Real cutlhs1, SCIP_Real cutlhs2, SCIP_Real bound1, SCIP_Real bound2, SCIP_Real *simplexcoefs1, SCIP_Real *simplexcoefs2, SCIP_Real *cutcoefs, SCIP_ROW **row, SCIP_Bool *madeintegral)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41933
#define SCIP_Real
Definition: def.h:127
#define MIN(x, y)
Definition: memory.c:67
int SCIPgetNSOS1Vars(SCIP_CONSHDLR *conshdlr)
Definition: cons_sos1.c:10570
constraint handler for SOS type 1 constraints
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28334
#define DEFAULT_MAXRANKINTEGRAL
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
#define SCIP_Longint
Definition: def.h:112
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
Definition: sepa.c:760
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18616
SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28134
#define SEPA_DELAY
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:26847
#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:6660
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3629
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:41132
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27864
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:38
#define DEFAULT_MAXDEPTH
#define SEPA_USESSUBSCIP