Scippy

SCIP

Solving Constraint Integer Programs

sepa_zerohalf.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 /**
17  * @file sepa_zerohalf.c
18  * @brief {0,1/2}-cuts separator
19  * @author Manuel Kutschka
20  * @author Kati Wolter
21  *
22  * {0,1/2}-Chv'atal-Gomory cuts separator. It solves the following separation problem:
23  *
24  *
25  * Given an integer program
26  *
27  * - min { c^T x : Ax <= b, x >= 0, x integer }
28  *
29  * and a fractional solution x* of its LP relaxation.
30  *
31  * Find a weightvector u whose entries u_i are either 0 or 1/2 such that the following inequality is valid for all integral solutions and violated by x*
32  *
33  * - floor(u^T A) x <= floor(u^T b)
34  *
35  * or (if exact methods are used) give a proof that no such inequality exists
36  *
37  *
38  *
39  * References:
40  * - Alberto Caprara, Matteo Fischetti. {0,1/2}-Chvatal-Gomory cuts. Math. Programming, Volume 74, p221--235, 1996.
41  * - Arie M. C. A. Koster, Adrian Zymolka and Manuel Kutschka. \n
42  * Algorithms to separate {0,1/2}-Chvatal-Gomory cuts.
43  * Algorithms - ESA 2007: 15th Annual European Symposium, Eilat, Israel, October 8-10, 2007, \n
44  * Proceedings. Lecture Notes in Computer Science, Volume 4698, p. 693--704, 2007.
45  * - Arie M. C. A. Koster, Adrian Zymolka and Manuel Kutschka. \n
46  * Algorithms to separate {0,1/2}-Chvatal-Gomory cuts (Extended Version). \n
47  * ZIB Report 07-10, Zuse Institute Berlin, 2007. http://www.zib.de/Publications/Reports/ZR-07-10.pdf
48  * - Manuel Kutschka. Algorithmen zur Separierung von {0,1/2}-Schnitten. Diplomarbeit. Technische Universitaet Berlin, 2007.
49  */
50 
51 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
52 
53 #include "string.h"
54 #include "scip/sepa_zerohalf.h"
55 #include "scip/cons_linear.h"
56 #include "scip/scipdefplugins.h"
57 
58 /* prints short statistics (callback, preprocessing, adding cuts) */
59 /* #define ZEROHALF__PRINT_STATISTICS */ /**< print statistics */
60 
61 #define SEPA_NAME "zerohalf"
62 #define SEPA_DESC "{0,1/2}-cuts separator"
63 #define SEPA_PRIORITY -6000
64 #define SEPA_FREQ -1
65 #define SEPA_MAXBOUNDDIST 0.0
66 #define SEPA_USESSUBSCIP TRUE
67 #define SEPA_DELAY FALSE
68 
69 #define DEFAULT_MAXROUNDS 5 /**< maximal number of zerohalf separation rounds per node (-1: unlimited) */
70 #define DEFAULT_MAXROUNDSROOT 10 /**< maximal number of zerohalf separation rounds in the root node (-1: unlimited) */
71 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of {0,1/2}-cuts separated per separation round */
72 #define DEFAULT_MAXSEPACUTSROOT 500 /**< maximal number of {0,1/2}-cuts separated per separation round in root node */
73 #define DEFAULT_DYNAMICCUTS TRUE /**< should generated cuts be removed from the LP if they are no longer tight? */
74 #define DEFAULT_DECOMPOSEPROBLEM FALSE /**< should problem be decomposed into subproblems (if possible)? */
75 #define DEFAULT_MAXDEPTH -1 /**< separating cuts only if depth <= maxdepth (-1: unlimited) */
76 #define DEFAULT_MINVIOLATION 0.30 /**< minimal violation of a {0,1/2}-cut to be separated */
77 #define DEFAULT_FORCECUTSTOLP FALSE /**< should the cuts be forced to enter the LP? (bypassing SCIPefficacy criteria) */
78 #define DEFAULT_FORCECUTSTOSEPASTORE FALSE /**< should the cuts be forced to enter SCIP's sepastore?
79  * (bypassing SCIPefficicacy criteria, if no other cut is found) */
80 #define DEFAULT_MAXCUTS 100 /**< maximal number of {0,1/2}-cuts determined per separation round
81  * (this includes separated but inefficacious cuts) */
82 #define DEFAULT_MAXCUTSROOT 1000 /**< maximal number of {0,1/2}-cuts determined per separation round
83  * in the root node (this includes separated but inefficacious cuts) */
84 #define DEFAULT_SUBSCIPOBJECTIVE 'v' /**< auxiliary IP objective function type */
85 #define DEFAULT_RELAXCONTVARS FALSE /**< should continuous variables be relaxed by adding variable bounds? */
86 #define DEFAULT_SCALEFRACCOEFFS TRUE /**< should rows be scaled to make fractional coefficients integer? */
87 #define DEFAULT_SUBSCIPSETTINGS "-" /**< optional settings file of the auxiliary IP (-: none) */
88 #define DEFAULT_SUBSCIPSOLLIMIT -1 /**< limits/solutions setting of the auxiliary IP */
89 #define DEFAULT_SUBSCIPUSEALLSOLS TRUE /**< should all (proper) solutions of the auxiliary IP be used to generate
90  * cuts instead of using only the best? */
91 #define DEFAULT_PPDELTA 0.500 /**< value of delta parameter used in preprocessing method 'd' */
92 #define DEFAULT_SUBSCIPOBJPEN 0.001 /**< penalty factor used with objective function 'p' of auxiliary IP */
93 
94 #define DEFAULT_PPMETHODS "CXGXIM" /**< preprocessing methods and ordering */
95 #define DEFAULT_SEPAMETHODS "2g" /**< preprocessing methods and ordering */
96 #define DEFAULT_MAXNCALLS -1LL /**< maximal number of calls (-1: unlimited) */
97 #define DEFAULT_IGNOREPREVIOUSZHCUTS FALSE /**< should zerohalf cuts found in previous callbacks be ignored? */
98 #define DEFAULT_ONLYORIGROWS FALSE /**< should only original LP rows be considered (i.e. ignore previously added LP rows)? */
99 #define DEFAULT_USEZHCUTPOOL TRUE /**< should zerohalf cuts be filtered using a cutpool */
100 #define DEFAULT_DELAYEDCUTS TRUE /**< should cuts be added to the delayed cut pool? */
101 #define DEFAULT_MAXTESTDELTA 10 /**< maximal number of different deltas to try for cmir (-1: unlimited, 0: delta=1) */
102 #define DEFAULT_TRYNEGSCALING TRUE /**< should negative values also be tested in scaling for cmir? */
104 /* cut pool management */
105 #define ORTHOFUNC 'e'
106 #define MINORTHO 0.5
107 
108 /* SCIPcalcMIR parameters */
109 #define NNONZOFFSET 500
110 #define BOUNDSWITCH 0.50
111 #define USEVBDS TRUE
112 #define ALLOWLOCAL TRUE
113 #define FIXINTEGRALRHS TRUE
114 #define BOUNDSFORTRANS NULL
115 #define BOUNDTYPESFORTRANS NULL
116 #define MAXWEIGHTRANGE 10000.00
117 #define MINFRAC 0.05
118 #define MAXFRAC 1.00
120 /* SCIPcalcRowIntegralScalar parameters */
121 #define MAXDNOM 1000
122 #define MAXSCALE 1000.0
123 
124 /* should variable bounds be used for substituting continuous variables */
125 #define USEVARBOUNDS TRUE
127 
128 /* --------------------------------------------------------------------------------------------------------------------
129  * definitions of enums and some related strings
130  * -------------------------------------------------------------------------------------------------------------------- */
131 
132 /** preprocessing methods, usable within the ppmethods parameter */
134  {
136  DELETEZEROROWS = 'Z',
138  DELETECOLSINGLETONS = 's',
145  PPCOLUMNS = 'C',
146  PPROWS = 'R'
147  };
148 #if 0 /* currently not used */
149 typedef enum preprocessingmethods PREPROCESSINGMETHODS;
150 #endif
151 
152 /** separation methods, usable within the sepamethods parameter */
153 enum sepamethods
154  {
155  STOPIFCUTWASFOUND = '!',
156  SOLVEAUXSCIP = 's',
158  ENUMHEURNMAX1 = 'e',
160  GAUSSHEUR = 'g',
162  };
163 #if 0 /* currently not used */
164 typedef enum sepamethods SEPAMETHODS;
165 #endif
166 
167 /** statistics: "origin" of separated cut */
168 enum cutseparatedby
169  {
171  };
173 
175 
176 /* --------------------------------------------------------------------------------------------------------------------
177  * auxiliary (inline) functions
178  * -------------------------------------------------------------------------------------------------------------------- */
179 
180 #define ISEVEN(scip, value) (SCIPisEQ((scip) , SCIPfloor(scip , (value) / 2) , (value) / 2)) /**< is value even? */
181 #define ISODD(scip, value) (!(ISEVEN((scip), (value)))) /**< is value odd? */
182 #define XOR(bool1, bool2) ((bool1) ^ (bool2))
183 #define DIV(value1, powerof2value) (((unsigned int)(value1)) / ((unsigned int)(powerof2value))) /**< integer division using a power of 2 as divisor */
184 #define MOD(value1, powerof2value) (((unsigned int)(value1)) % ((unsigned int)(powerof2value))) /**< remainder of integer division using a power of 2
185  as divisor */
186 #ifndef BMSmoveMemoryArray
187 /** moves array at source with size num to ptr */
188 #define BMSmoveMemoryArray(ptr, source, num) \
189  { \
190  size_t size__ = (num) * sizeof(*(ptr)); \
191  if( size__ > 0 ) \
192  { \
193  assert((void*)(ptr) != NULL); \
194  assert((void*)(source) != NULL); \
195  memmove((void*)(ptr), (void*)(source), size__); \
196  } \
197  }
198 #endif
199 
200 #ifdef ZEROHALF__PRINT_STATISTICS
201 
202 #define ZEROHALFstatistics(x) x /**< execute if ZEROHALF__PRINT_STATISTICS is defined */
203 #define ZEROHALFstatisticsMessage printf("#### ") ; printf /**< print statistics message */
204 #define ZEROHALFcreateNewTimer(timervar) SCIP_CALL(SCIPcreateClock(scip, &timervar)) /**< create new timer */
205 #define ZEROHALFcreateTimer(timervar) SCIP_CALL(SCIPcreateClock(scip, &timervar)) /**< recreate existing timer */
206 #define ZEROHALFfreeTimer(timervar) SCIP_CALL(SCIPfreeClock(scip, &timervar)) /**< free timer */
207 #define ZEROHALFresetTimer(timervar) SCIP_CALL(SCIPresetClock(scip, timervar)) /**< reset timer */
208 #define ZEROHALFstartTimer(timervar) SCIP_CALL(SCIPstartClock(scip, timervar)) /**< start timer */
209 #define ZEROHALFstopTimer(timervar) SCIP_CALL(SCIPstopClock(scip, timervar)) /**< stop timer */
210 #define ZEROHALFevalTimer(timervar) (SCIPgetClockTime(scip, timervar)) /**< evaluate timer (get time) */
211 
212 #else
213 
214 #if 0 /* currently not used */
215 #define ZEROHALFstatistics(x) /**/ /**< nothing */
216 #define ZEROHALFstatisticsMessage while( FALSE ) printf /**< nothing */
217 #define ZEROHALFcreateNewTimer(timervar) /**/ /**< nothing */
218 #define ZEROHALFcreateTimer(timervar) /**/ /**< nothing */
219 #define ZEROHALFfreeTimer(timervar) /**/ /**< nothing */
220 #define ZEROHALFresetTimer(timervar) /**/ /**< nothing */
221 #define ZEROHALFstartTimer(timervar) /**/ /**< nothing */
222 #define ZEROHALFstopTimer(timervar) /**/ /**< nothing */
223 #define ZEROHALFevalTimer(timervar) (0.0) /**< nothing */
224 #endif
225 
226 #endif
227 
228 
229 /* --------------------------------------------------------------------------------------------------------------------
230  * symbolic constants for statistical analysis
231  * -------------------------------------------------------------------------------------------------------------------- */
232 
233 /* row / columns */
234 #define IRRELEVANT -1 /**< row or column is irrelevant */
235 
236 /* row */
237 #define ZERO_ROW -100 /**< row has no nonzero entries */
238 #define IDENT_TO_ROW_WITH_SMALLER_SLACK -101 /**< row is identical to another row but has a larger slack value */
239 #define SLACK_GREATER_THAN_MAXSLACK -102 /**< row has a slack value > maxslack */
240 #define DEFINES_VIOLATED_ZEROHALF_CUT -103 /**< row defines a violated zerohalf cut */
241 #ifdef WITHDECOMPOSE
242 #define ROW_IN_SUBPROB_WITHOUT_ODD_RHS -104 /**< row is part of a subproblem without rows with odd rhs */
243 #endif
244 #define NONEXISTENT_ROW -105 /**< row does not exist (lhs is -infinity or rhs is infinity) */
245 #define NO_RELEVANT_COLUMNS -106 /**< row does not contain relevant columns */
246 #define SLACK_GREATER_THAN_MSL_MINUS_SODD -107 /**< row has even rhs and the sum of its slack value and the minimum
247  slack value of a odd-rhs-row exceeds maxslack */
248 #define LARGE_COL_EXISTS -108 /**< row contains a column which rounding penalty exceeds maxslack
249  and the sum of this row's slack and the minimum slack of another
250  row with the proper columns exceeds maxslack as well */
252 /* column */
253 #define ZERO_COLUMN -200 /**< column has no nonzero entries */
254 #define IDENT_TO_ANOTHER_COLUMN -201 /**< column is identical to another column */
255 #define ZERO_LP_SOL -202 /**< column corresponds to a variable whose LP solution is zero */
256 #define LP_SOL_EQUALS_EVEN_LB -203 /**< column corresponds to a variable whose LP solution equals its even lb */
257 #define LP_SOL_EQUALS_ODD_LB -204 /**< column corresponds to a variable whose LP solution equals its odd lb */
258 #define LP_SOL_EQUALS_EVEN_UB -205 /**< column corresponds to a variable whose LP solution equals its even ub */
259 #define LP_SOL_EQUALS_ODD_UB -206 /**< column corresponds to a variable whose LP solution equals its odd ub */
260 #define SINGLETON_COLUMN -207 /**< column has only one nonzero entry */
261 #define CONTINUOUS_VARIABLE -208 /**< column corresponds to a non-integer variable */
262 #define SMALL_FRACSOL_HEUR -209 /**< column has been omitted (see preprocessColumnsWithSmallFracsol) */
263 #define ALL_MATRIX_ROWS_DELETED -210 /**< all rows (of the current subproblem) have been deleted */
264 #ifdef WITHDECOMPOSE
265 #define COLUMN_IN_SUBPROB_WITHOUT_ODD_RHS -211 /**< column is part of a subproblem without a row with odd rhs value */
266 #endif
269 /* --------------------------------------------------------------------------------------------------------------------
270  * bit array data structures and functions
271  * -------------------------------------------------------------------------------------------------------------------- */
273 
274 #define BITARRAYBASETYPE unsigned int /**< base type used for the bitarray data structures */
275 #define BITARRAYBITMASKTYPE BITARRAYBASETYPE
276 
277 /** size of BITARRAYBASETYPE */
278 static const unsigned int Zerohalf_bitarraybasetypesize = sizeof(BITARRAYBASETYPE);
279 
280 /** number of bits per BITARRAYBASETYPE */
281 static const unsigned int Zerohalf_bitarraybasetypesize_nbits = sizeof(BITARRAYBASETYPE) << 3;
282 
284 #define BITARRAY BITARRAYBASETYPE*
285 
286 /** get the bit mask where the pos-th bit is set */
287 #define BITMASK(pos) ((unsigned int)(1 << (pos)))
288 
289 /** set the pos-th bit of var */
290 #define BITSET(var, pos) (var) |= BITMASK(pos)
291 
292 /** is the pos-th bit of var set? */
293 #define BITISSET(var, pos) (var & BITMASK(pos))
294 
295 /** set the pos-th bit of bitarray barray */
296 #define BITARRAYBITSET(barray, pos) BITSET(barray[DIV((pos),Zerohalf_bitarraybasetypesize_nbits)], \
297  MOD(pos,Zerohalf_bitarraybasetypesize_nbits))
298 
299 /** is the pos-th bit of bitarray barray set? */
300 #define BITARRAYBITISSET(barray, pos) BITISSET(barray[DIV(pos,Zerohalf_bitarraybasetypesize_nbits)], \
301  MOD(pos,Zerohalf_bitarraybasetypesize_nbits))
303 /** clear bitarray */
304 #define BITARRAYCLEAR(barray, barraysize) BMSclearMemoryArray(barray,barraysize)
306 /** calculates the number of array elements (w.r.t. the bitarray base type) required to create the bitarray */
307 #define GETREQUIREDBITARRAYSIZE(nvalstostore) \
308  ((((unsigned int)(nvalstostore)) % (Zerohalf_bitarraybasetypesize_nbits) == 0) \
309  ? (((unsigned int)(nvalstostore)) / (Zerohalf_bitarraybasetypesize_nbits)) \
310  : ((((unsigned int)(nvalstostore)) / (Zerohalf_bitarraybasetypesize_nbits)) + 1))
311 
312 /** get the corresponding array element of a bitarray position */
313 #define GETBITARRAYINDEX(pos) DIV((pos),Zerohalf_bitarraybasetypesize_nbits)
314 
315 /** get the bitmask to mask all bits except the pos-th bit of an array element */
316 #define GETBITARRAYMASK(pos) BITMASK(MOD((pos),Zerohalf_bitarraybasetypesize_nbits))
317 
318 /** apply operation op for all array elements of bitarray barray1 and barray2 */
319 #define BITARRAYSFOREACH(barray1, barray2, size, op) \
320  { \
321  int idx__; \
322  for( idx__ = 0 ; idx__ < (size) ; ++idx__) \
323  { \
324  barray2[idx__] op barray1[idx__]; \
325  } \
326  }
327 
328 /** barray2 = barray1 XOR barray2 */
329 #define BITARRAYSXOR(barray1, barray2, size) BITARRAYSFOREACH(barray1,barray2,size,^=)
330 
331 /** are barray1 and barray2 equal? */
332 #define BITARRAYSAREEQUAL(barray1, barray2, size) \
333  (memcmp((void*)(barray1), (void*)(barray2), (size_t)((size) * (Zerohalf_bitarraybasetypesize))) == 0)
334 
335 #if 0 /* currently not used */
336 /** clear the pos-th bit of var */
337 #define BITCLEAR(var, pos) (var) &= ~BITMASK(pos)
339 /** flip the pos-th bit of var */
340 #define BITFLIP(var, pos) (var) ^= BITMASK(pos)
342 /** clear the pos-th bit of bitarray barray */
343 #define BITARRAYBITCLEAR(barray, pos) BITCLEAR(barray[DIV((pos),Zerohalf_bitarraybasetypesize_nbits)], \
344  MOD(pos,Zerohalf_bitarraybasetypesize_nbits))
345 
346 /** flip the pos-th bit of bitarray barray */
347 #define BITARRAYBITFLIP(barray, pos) BITFLIP(barray[DIV((pos),Zerohalf_bitarraybasetypesize_nbits)], \
348  MOD(pos,Zerohalf_bitarraybasetypesize_nbits))
349 
350 /** barray2 = barray1 AND barray2 */
351 #define BITARRAYSAND(barray1, barray2, size) BITARRAYSFOREACH(barray1,barray2,size,&=)
352 
353 /** barray2 = barray1 OR barray2 */
354 #define BITARRAYSOR(barray1, barray2, size) BITARRAYSFOREACH(barray1,barray2,size,|=)
355 
356 /** barray2 = NOT barray1 */
357 #define BITARRAYSNOT(barray1, barray2, size) BITARRAYSFOREACH(barray1,barray2,size,= ~)
358 #endif
359 
360 
361 /* --------------------------------------------------------------------------------------------------------------------
362  * data structures
363  * -------------------------------------------------------------------------------------------------------------------- */
364 
365 
366 /** parameters */
367 struct SCIP_SepaData
368 {
369 
370  int maxrounds; /**< maximal number of {0,1/2} separation rounds per node (-1: unlimited) */
371  int maxroundsroot; /**< maximal number of {0,1/2} separation rounds in the root node (-1: unlimited) */
372  int maxsepacuts; /**< maximal number of {0,1/2} cuts separated per separation round */
373  int maxsepacutsroot; /**< maximal number of {0,1/2} cuts separated per separation round in root node */
374  int maxdepth; /**< separating cuts only if depth <= maxdepth (-1: unlimited) */
375  SCIP_Bool dynamiccuts; /**< should generated cuts be removed from the LP if they are no longer tight? */
376  SCIP_Bool decomposeproblem; /**< should problem be decomposed into subproblems (if possible)? */
377 
378  SCIP_Real minviolation; /**< minimal violation of a {0,1/2}-cut to be separated */
379  SCIP_Bool forcecutstolp; /**< should the cuts be forced to enter the LP? */
380  SCIP_Bool forcecutstosepastore; /**< should the cuts be forced to enter SCIP's sepastore? */
381  int maxcuts; /**< maximal number of {0,1/2}-cuts determined per separation round
382  (this includes separated but inefficacious cuts) */
383  int maxcutsroot; /**< maximal number of {0,1/2}-cuts determined per separation round
384  in the root node (this includes separated but inefficacious cuts) */
385 
386  char* ppmethods; /**< preprocessing methods */
387  char* sepamethods; /**< separation methods */
388  int nppmethods; /**< length of ppmethods string */
389  int nsepamethods; /**< length of sepamethods string */
390 
391  int subscipsollimit; /**< value of auxiliary IP / subscip "limits/sol" */
392  SCIP_Bool subscipuseallsols; /**< should all known feasible solution of the auxiliary IP be considered? */
393  SCIP_Bool relaxcontvars; /**< should continuous vars be relaxed by adding varbounds? */
394  SCIP_Bool scalefraccoeffs; /**< should fractional coeffs be scaled to become integer? */
395  char* subscipsettings; /**< optional settings file for the auxiliary IP / subscip */
396  char subscipobjective; /**< type of objective function of the auxiliary IP / subscip */
397  SCIP_Real ppdelta; /**< value of delta parameter used in preprocessing method 'd' */
398  SCIP_Real subscipobjpen; /**< penalty factor used with objective function 'p' of auxiliary IP */
399  SCIP_Longint maxncalls; /**< maximal number of callbacks */
400  SCIP_Bool ignoreprevzhcuts; /**< should zerohalf cuts found within previous callbacks considered as well? */
401  SCIP_Bool onlyorigrows; /**< should only original LP rows be considered (i.e. ignore previously added LP rows)? */
402  SCIP_Bool usezhcutpool; /**< should zerohalf cuts be filtered using a cutpool? */
403  SCIP_Bool delayedcuts; /**< should cuts be added to the delayed cut pool? */
404 
405  SCIP_Real maxslack; /**< initial: 1.0 - 2.0 * minviolation */
406  int norigrows; /**< number of original LP rows */
407  int* origrows; /**< set of SCIP_ROW->index of all original LP rows */
408 
409  int maxnnonz; /**< maximal number of nonzeros allowed in a zerohalf cut */
410  int maxtestdelta; /**< maximal number of different deltas to try for cmir (-1: unlimited, 0: delta=1) */
411  SCIP_Bool trynegscaling; /**< should negative values also be tested in scaling for cmir? */
412 
413  /* statistics */
414  int totalncutsfound; /**< total number of separated zerohalf cuts, including inefficious ones */
415  int totalnsepacuts; /**< total number of separated zerohalf cuts */
416  SCIP_CLOCK** pptimers; /**< timers of preprocessing methods */
417  SCIP_CLOCK** sepatimers; /**< timers of separation algorithms */
418  SCIP_CLOCK* dtimer; /**< timer of decomposition method */
419  int* nsepacutsalgo; /**< number zerohalf cuts separated by a specific separation algorithm,
420  * including inefficious cuts */
421  int* nzerohalfcutsalgo; /**< number zerohalf cuts separated by a specific separation algorithm */
422 };
423 
424 
425 /** sub data of the LP or a sub-LP obtained by problem decomposition */
426 struct Zerohalf_SubLPData
427 {
428  int* rrows; /**< relevant rows (indices of elements in rows array of ZEROHALF_LPDATA) */
429  int nrrows; /**< number of relevant rows */
430  SCIP_Real* rrowsrhs; /**< rhs value of relevant rows; could also be lhs value of the orig row */
431  SCIP_Real* rrowsslack; /**< slack value of relevant rows */
432  int* rcols; /**< relevant columns (indices of elements in cols array of ZEROHALF_LPDATA) */
433  int nrcols; /**< number of relevant columns */
434  SCIP_Real* rcolslbslack; /**< slack value of lower bound constraint: x*_j - lb_j */
435  SCIP_Real* rcolsubslack; /**< slack value of upper bound constraint: ub_j - x*_j */
436 };
437 typedef struct Zerohalf_SubLPData ZEROHALF_SUBLPDATA;
438 
439 
440 /** LP data */
441 struct Zerohalf_LPData
442 {
443  SCIP_VAR** vars; /**< LP variables */
444  SCIP_ROW** rows; /**< LP rows */
445  SCIP_COL** cols; /**< LP columns */
446  int nvars; /**< number of LP variables */
447  int nrows; /**< number of LP rows */
448  int ncols; /**< number of LP columns */
449  int nvarbounds; /**< number of variable bounds (-x_j <= -lb_j, x_j <= ub_j) */
450 
451  ZEROHALF_SUBLPDATA** subproblems; /**< decomposed subproblems (subset of the variables, rows and columns above) */
452  int nsubproblems; /**< number of subproblems */
453 
454  SCIP_Real* intscalarsleftrow; /**< array of scalars that would make left half-rows (-a^Tx <= -lhs) rows integral (0.0 if scalar has not been calculated) */
455  SCIP_Real* intscalarsrightrow; /**< array of scalars that would make right half-rows (a^Tx <= rhs) rows integral (0.0 if scalar has not been calculated) */
456 
457  /* row related index sets */
458  int* subproblemsindexofrow; /**< is rows index relevant? value <0: not relevant,
459  value >=0: index of subproblem containing the row */
460  int* rrowsindexofleftrow; /**< maps rows index of lhs <= a^Tx <= rhs to rrows index of -a^Tx <= -lhs */
461  int* rrowsindexofrightrow; /**< maps rows index of lhs <= a^Tx <= rhs to rrows index of a^Tx <= rhs */
462 
463  /* col related index sets */
464  int* subproblemsindexofcol; /**< is cols index relevant? value <0: not relevant
465  * value >=0: index of subproblem containing the column */
466  int* rcolsindexofcol; /**< maps cols index to rcols index */
467 
468  int* bestlbidxofcol; /**< maps cols index of a continuous variable to the index of its
469  * best lower bound (-2: undetermined, -1: lb, >=0: index of vlb)*/
470  int* bestubidxofcol; /**< maps cols index of a continuous variable to the index of its
471  * best upper bound (-2: undetermined, -1: ub, >=0: index of vub)*/
472 
473  /* statistics */
474  int ndelvarbounds; /**< number of deleted variable bounds by basic preprocessing */
475 
476 };
477 typedef struct Zerohalf_LPData ZEROHALF_LPDATA;
478 
479 
480 /** data structure to store data of the auxiliary IP:
481  * (1) minimize violation:
482  * min z := s^T v + x^T y
483  * s.t. (b (mod 2))^T v - 2q = 1 "odd rhs"
484  * (A (mod 2))^T v - y - -2r = 0 "column sum"
485  *
486  * v \\in {0,1}^m
487  * y \\in {0,1}^n
488  * r \\in Z^n_+
489  * q \\in Z_+
490  * (2) minimize (weighted) number of aggregated rows
491  * min z := w^T v
492  * s.t. s^T v + x^T y < 1 "feasibility"
493  * (b (mod 2))^T v - 2q = 1 "odd rhs"
494  * (A (mod 2))^T v - y - -2r = 0 "column sum"
495  *
496  * v \\in {0,1}^m
497  * y \\in {0,1}^n
498  * r \\in Z^n_+
499  * q \\in Z_+
500  *
501  * with w \\in \\Rset^m
502  */
503 struct Zerohalf_AuxIPData
504 {
505  SCIP* subscip; /**< pointer to (sub)SCIP data structure containing the auxiliary IP */
506  int m; /**< number of rows */
507  int n; /**< number of cols */
508 
509  SCIP_VAR** v; /**< decision variable: 1 iff row is selected for generating a violated zerohalf cut */
510  SCIP_VAR** y; /**< auxiliary variable used for calculating the rounding down penalties in the objective */
511  SCIP_VAR** r; /**< auxiliary variable used for modelling mod 2 calculus */
512  SCIP_VAR* q; /**< auxiliary variable used for modelling mod 2 calculus */
513 
514  SCIP_CONS* feasipcons; /**< feasibility constraint */
515  SCIP_CONS* oddrhscons; /**< odd rhs constraint */
516  SCIP_CONS** columnsumcons; /**< column sum constraints */
517 
518  SCIP_Real timelimit; /**< value of "limits/time" of subscip */
519  SCIP_Real memorylimit; /**< value of "limits/memory" of subscip */
520  SCIP_Real objectivelimit; /**< value of objective limit of subscip */
521  int nodelimit; /**< value of "limits/nodes" of subscip */
522 };
523 typedef struct Zerohalf_AuxIPData ZEROHALF_AUXIPDATA;
524 
525 
526 /** data structure to store data (mod 2) densely*/
527 struct Zerohalf_Mod2Data
528 {
529  ZEROHALF_SUBLPDATA* relatedsubproblem; /**< pointer to corresponding subproblem data structure */
530 
531  BITARRAY* rows; /**< dense mod 2 rows */
532  BITARRAY* rowaggregations; /**< Zerohalf_Mod2Data->rows index set, storing the actual row aggregations */
533  SCIP_Bool* rhs; /**< TRUE iff corresponding relatedsubproblem->rrowsrhs is odd */
534 
535  SCIP_Real* slacks; /**< slack value (equal to corresponding relatedsubproblem->rrowsslack value) */
536  SCIP_Real* fracsol; /**< LP solution value of variable of SCIP_COL* */
537 
538  int nrows; /**< number of Zerohalf_Mod2Data->rows */
539  int rowsbitarraysize; /**< size (w.r.t. bitarray base type) of Zerohalf_Mod2Data->rows array */
540  int rowaggregationsbitarraysize; /** size (w.r.t. bitarray base type) of Zerohalf_Mod2Data->rowaggregations array */
541  int nvarbounds; /**< number of variable bounds that are part of Zerohalf_Mod2Data->rows */
542 
543  int* rowsind; /**< index set of subset of Zerohalf_Mod2Data->rows */
544  int* colsind; /**< index set of subset of relatedsubproblem->rcols */
545 
546  int nrowsind; /**< number of rowsind elements */
547  int ncolsind; /**< number of colsind elements */
548 
549  /* statistics */
550  int* rowstatistics; /**< stores if and why a row was removed in preprocessing */
551  int* colstatistics; /**< stores if and why a column was removed in preprocessing */
552 };
553 typedef struct Zerohalf_Mod2Data ZEROHALF_MOD2DATA;
554 
555 
556 /** data structure to store a violated zerohalf cut and related data */
557 struct Zerohalf_CutData
558 {
559  ZEROHALF_SUBLPDATA* relatedsubproblem; /**< pointer to corresponding subproblem data structure */
560  ZEROHALF_MOD2DATA* relatedmod2data; /**< pointer to corresponding mod 2 data structure */
561 
562  SCIP_ROW* cut; /**< pointer to SCIP_ROW storing the cut */
563 
564  SCIP_Bool success; /**< was SCIPcalcMIR successful? */
565  SCIP_Bool isfeasviolated; /**< is zerohalf cut violated w.r.t. the feasibility tolerance? */
566  SCIP_Bool islocal; /**< is zerohalf cut only locally valid? */
567 
568  SCIP_Real activity; /**< activity of the zerohalf cut */
569  SCIP_Real rhs; /**< rhs of the zerohalf cut */
570  SCIP_Real norm; /**< norm of the nonzero elements of the zerohalf cut */
571  SCIP_Real efficacy; /**< efficacy of the zerohalf cut */
572  SCIP_Real violation; /**< violation of the zerohalf cut */
573  int cutrank; /**< rank of cut */
574  int nnonz; /**< number of nonzero coefficients of the zerohalf cut */
575 
576  /* statistics */
577  int nrowsincut; /**< number of LP rows combined into the zerohalf cut */
578  int nrrowsincut; /**< number of preprocessed/aggregated LP rows combined into the zerohalf cut */
579  CUTSEPARATEDBY separatedby; /**< flag to store the method that has separated the zerohalf cut */
580  int addedtolp; /**< was the cut added to SCIP? */
581 
582 };
583 typedef struct Zerohalf_CutData ZEROHALF_CUTDATA;
584 
585 
586 
587 /** auxiliary graph node data structure */
588 struct Zerohalf_AuxGraph_Node;
589 typedef struct Zerohalf_AuxGraph_Node ZEROHALF_AUXGRAPH_NODE;
590 
591 struct Zerohalf_AuxGraph_Node
592 {
593  ZEROHALF_AUXGRAPH_NODE** neighbors; /**< node adjacency list */
594  SCIP_Real* edgeweights; /**< weights of outgoing edges */
595  int* relatedrows; /**< label mapping outgoing edges to mod 2 rows */
596  int nneighbors; /**< number of adjacent nodes */
597  SCIP_Real distance; /**< actual distant from start node (used by Dijkstra)*/
598  ZEROHALF_AUXGRAPH_NODE* previous; /**< previous node in shortest-path-tree (used by Dijkstra) */
599 };
600 
601 
602 /** auxiliary graph data structure */
603 struct Zerohalf_AuxGraph
604 {
605  ZEROHALF_AUXGRAPH_NODE** nodes; /**< list of all original nodes */
606  ZEROHALF_AUXGRAPH_NODE** nodecopies; /**< list of all copies of original nodes */
607  int nnodes; /**< number of original nodes (equals number of copies) */
608 };
609 typedef struct Zerohalf_AuxGraph ZEROHALF_AUXGRAPH;
610 
611 
612 /* --------------------------------------------------------------------------------------------------------------------
613  * local methods: create / free data structure
614  * -------------------------------------------------------------------------------------------------------------------- */
615 
616 
617 /** creates and initializes sub LP data structures */
618 static
620  SCIP* scip, /**< SCIP data structure */
621  ZEROHALF_SUBLPDATA** subproblem /**< pointer to store pointer to created data structure */
622  )
623 {
624  assert(scip != NULL);
625  assert(subproblem != NULL);
626 
627  SCIP_CALL(SCIPallocMemory(scip, subproblem));
628  (*subproblem)->rrows = NULL;
629  (*subproblem)->rrowsrhs = NULL;
630  (*subproblem)->rrowsslack = NULL;
631  (*subproblem)->nrrows = 0;
632 
633  (*subproblem)->rcols = NULL;
634  (*subproblem)->rcolslbslack = NULL;
635  (*subproblem)->rcolsubslack = NULL;
636  (*subproblem)->nrcols = 0;
637 
638  return SCIP_OKAY;
639 }
640 
641 
642 /** frees sub LP data structures */
643 static
645  SCIP* scip, /**< SCIP data structure */
646  ZEROHALF_SUBLPDATA** subproblem /**< pointer to pointer of data structure */
647  )
648 {
649  assert(scip != NULL);
650  assert(subproblem != NULL);
651  assert(*subproblem != NULL);
652 
653  if( (*subproblem)->rrows != NULL )
654  {
655  SCIPfreeMemoryArray(scip, &((*subproblem)->rrows));
656  }
657  if( (*subproblem)->rrowsrhs != NULL )
658  {
659  SCIPfreeMemoryArray(scip, &((*subproblem)->rrowsrhs));
660  }
661  if( (*subproblem)->rrowsslack != NULL )
662  {
663  SCIPfreeMemoryArray(scip, &((*subproblem)->rrowsslack));
664  }
665  if( (*subproblem)->rcols != NULL )
666  {
667  SCIPfreeMemoryArray(scip, &((*subproblem)->rcols));
668  }
669  if( (*subproblem)->rcolslbslack != NULL )
670  {
671  SCIPfreeMemoryArray(scip, &((*subproblem)->rcolslbslack));
672  }
673  if( (*subproblem)->rcolsubslack != NULL )
674  {
675  SCIPfreeMemoryArray(scip, &((*subproblem)->rcolsubslack));
676  }
677  SCIPfreeMemory(scip, subproblem);
678  (*subproblem) = NULL;
679 }
680 
681 
682 /** creates and initializes LP data structures */
683 static
685  SCIP* scip, /**< SCIP data structure */
686  ZEROHALF_LPDATA** lpdata /**< pointer to store pointer to created data structure */
687  )
688 {
689  assert(scip != NULL);
690  assert(lpdata != NULL);
691 
692  SCIP_CALL(SCIPallocMemory(scip, lpdata));
693  (*lpdata)->vars = NULL;
694  (*lpdata)->rows = NULL;
695  (*lpdata)->cols = NULL;
696 
697  (*lpdata)->subproblems = NULL;
698  (*lpdata)->nsubproblems = 0;
699 
700  (*lpdata)->intscalarsleftrow = NULL;
701  (*lpdata)->intscalarsrightrow = NULL;
702 
703  (*lpdata)->subproblemsindexofrow = NULL;
704  (*lpdata)->rrowsindexofleftrow = NULL;
705  (*lpdata)->rrowsindexofrightrow = NULL;
706 
707  (*lpdata)->subproblemsindexofcol = NULL;
708  (*lpdata)->rcolsindexofcol = NULL;
709 
710  (*lpdata)->bestlbidxofcol = NULL;
711  (*lpdata)->bestubidxofcol = NULL;
712 
713  return SCIP_OKAY;
714 }
715 
716 
717 /** frees LP data structures */
718 static
720  SCIP* scip, /**< SCIP data structure */
721  ZEROHALF_LPDATA** lpdata /**< pointer to pointer of data structure */
722  )
723 {
724  int sp;
725 
726  assert(scip != NULL);
727  assert(lpdata != NULL);
728  assert(*lpdata != NULL);
729 
730  /* ! Do not free (*lpdata)->vars, (*lpdata)->rows and (*lpdata)->cols ! */
731  assert(((*lpdata)->nsubproblems == 0 && (*lpdata)->subproblems == NULL)
732  || ((*lpdata)->nsubproblems > 0 && (*lpdata)->subproblems != NULL));
733 
734  if( (*lpdata)->subproblems != NULL )
735  {
736  for( sp = 0 ; sp < (*lpdata)->nsubproblems ; ++sp )
737  if( (*lpdata)->subproblems[sp] != NULL )
738  ZerohalfSubLPDataFree(scip, &((*lpdata)->subproblems[sp]));
739  SCIPfreeMemoryArray(scip, &((*lpdata)->subproblems));
740  }
741 
742  if( (*lpdata)->intscalarsleftrow != NULL )
743  {
744  SCIPfreeMemoryArray(scip, &((*lpdata)->intscalarsleftrow));
745  }
746  if( (*lpdata)->intscalarsrightrow != NULL )
747  {
748  SCIPfreeMemoryArray(scip, &((*lpdata)->intscalarsrightrow));
749  }
750  if( (*lpdata)->subproblemsindexofrow != NULL )
751  {
752  SCIPfreeMemoryArray(scip, &((*lpdata)->subproblemsindexofrow));
753  }
754  if( (*lpdata)->rrowsindexofleftrow != NULL )
755  {
756  SCIPfreeMemoryArray(scip, &((*lpdata)->rrowsindexofleftrow));
757  }
758  if( (*lpdata)->rrowsindexofrightrow != NULL )
759  {
760  SCIPfreeMemoryArray(scip, &((*lpdata)->rrowsindexofrightrow));
761  }
762  if( (*lpdata)->subproblemsindexofcol != NULL )
763  {
764  SCIPfreeMemoryArray(scip, &((*lpdata)->subproblemsindexofcol));
765  }
766  if( (*lpdata)->rcolsindexofcol != NULL )
767  {
768  SCIPfreeMemoryArray(scip, &((*lpdata)->rcolsindexofcol));
769  }
770  if( (*lpdata)->bestlbidxofcol != NULL )
771  {
772  SCIPfreeMemoryArray(scip, &((*lpdata)->bestlbidxofcol));
773  }
774  if( (*lpdata)->bestubidxofcol != NULL )
775  {
776  SCIPfreeMemoryArray(scip, &((*lpdata)->bestubidxofcol));
777  }
778  SCIPfreeMemory(scip, lpdata);
779  (*lpdata) = NULL;
780 
781  return SCIP_OKAY;
782 }
783 
784 
785 /** creates and initializes mod 2 data structures */
786 static
788  SCIP* scip, /**< SCIP data structure */
789  ZEROHALF_MOD2DATA** mod2data /**< pointer to store pointer to created data structure */
790  )
791 {
792  assert(scip != NULL);
793  assert(mod2data != NULL);
794 
795  SCIP_CALL(SCIPallocMemory(scip, mod2data));
797  (*mod2data)->relatedsubproblem = NULL;
798 
799  (*mod2data)->rows = NULL;
800  (*mod2data)->rowaggregations = NULL;
801  (*mod2data)->rhs = NULL;
802 
803  (*mod2data)->slacks = NULL;
804  (*mod2data)->fracsol = NULL;
805 
806  (*mod2data)->rowstatistics = NULL;
807  (*mod2data)->colstatistics = NULL;
808 
809  (*mod2data)->rowsind = NULL;
810  (*mod2data)->colsind = NULL;
811 
812  return SCIP_OKAY;
813 }
814 
815 
816 /** frees data structures */
817 static
819  SCIP* scip, /**< SCIP data structure */
820  ZEROHALF_MOD2DATA** mod2data /**< pointer to pointer of data structure */
821  )
822 {
823  int i;
824 
825  assert(scip != NULL);
826  assert(mod2data != NULL);
827  assert(*mod2data != NULL);
828 
829  if( (*mod2data)->rows != NULL )
830  {
831  for( i = 0 ; i < (*mod2data)->nrows ; ++i)
832  if( (*mod2data)->rows[i] != NULL )
833  {
834  SCIPfreeMemoryArray(scip, &((*mod2data)->rows[i]));
835  }
836  SCIPfreeMemoryArray(scip, &((*mod2data)->rows));
837  }
838 
839  if( (*mod2data)->rowaggregations != NULL )
840  {
841  for( i = 0 ; i < (*mod2data)->nrows ; ++i)
842  if( (*mod2data)->rowaggregations[i] != NULL )
843  {
844  SCIPfreeMemoryArray(scip, &((*mod2data)->rowaggregations[i]));
845  }
846  SCIPfreeMemoryArray(scip, &((*mod2data)->rowaggregations));
847  }
848 
849  if( (*mod2data)->rhs != NULL )
850  {
851  SCIPfreeMemoryArray(scip, &((*mod2data)->rhs));
852  }
853  if( (*mod2data)->slacks != NULL )
854  {
855  SCIPfreeMemoryArray(scip, &((*mod2data)->slacks));
856  }
857  if( (*mod2data)->fracsol != NULL )
858  {
859  SCIPfreeMemoryArray(scip, &((*mod2data)->fracsol));
860  }
861  if( (*mod2data)->rowstatistics != NULL )
862  {
863  SCIPfreeMemoryArray(scip, &((*mod2data)->rowstatistics));
864  }
865  if( (*mod2data)->colstatistics != NULL )
866  {
867  SCIPfreeMemoryArray(scip, &((*mod2data)->colstatistics));
868  }
869  if( (*mod2data)->rowsind != NULL )
870  {
871  SCIPfreeMemoryArray(scip, &((*mod2data)->rowsind));
872  }
873  if( (*mod2data)->colsind != NULL )
874  {
875  SCIPfreeMemoryArray(scip, &((*mod2data)->colsind));
876  }
877  SCIPfreeMemory(scip, mod2data);
878  (*mod2data) = NULL;
879 
880  return SCIP_OKAY;
881 }
882 
883 
884 /** creates and initializes auxiliary IP data structures */
885 static
887  SCIP* scip, /**< SCIP data structure */
888  ZEROHALF_AUXIPDATA** auxipdata /**< pointer to store pointer to created data structure */
889  )
890 {
891  assert(scip != NULL);
892  assert(auxipdata != NULL);
893 
894  SCIP_CALL(SCIPallocMemory(scip, auxipdata));
896  (*auxipdata)->subscip = NULL;
897 
898  (*auxipdata)->v = NULL;
899  (*auxipdata)->y = NULL;
900  (*auxipdata)->r = NULL;
901  (*auxipdata)->q = NULL;
902 
903  (*auxipdata)->feasipcons = NULL;
904  (*auxipdata)->oddrhscons = NULL;
905  (*auxipdata)->columnsumcons = NULL;
906 
907  return SCIP_OKAY;
908 }
909 
910 
911 /** frees auxiliary IP data structures */
912 static
914  SCIP* scip, /**< SCIP data structure */
915  ZEROHALF_AUXIPDATA** auxipdata /**< pointer to pointer of data structure */
916  )
917 {
918  assert(scip != NULL);
919  assert(auxipdata != NULL);
920  assert(*auxipdata != NULL);
921 
922  if( (*auxipdata)->subscip != NULL )
923  {
924  SCIP_CALL( SCIPfree(&((*auxipdata)->subscip)) );
925  }
926 
927  if( (*auxipdata)->v != NULL )
928  {
929  SCIPfreeMemoryArray(scip, &((*auxipdata)->v));
930  }
931  if( (*auxipdata)->y != NULL )
932  {
933  SCIPfreeMemoryArray(scip, &((*auxipdata)->y));
934  }
935  if( (*auxipdata)->r != NULL )
936  {
937  SCIPfreeMemoryArray(scip, &((*auxipdata)->r));
938  }
939  if( (*auxipdata)->columnsumcons != NULL )
940  {
941  SCIPfreeMemoryArray(scip, &((*auxipdata)->columnsumcons));
942  }
943  SCIPfreeMemory(scip, auxipdata);
944  (*auxipdata) = NULL;
945 
946  return SCIP_OKAY;
947 }
948 
949 
950 /** creates and initializes cut data structures */
951 static
953  SCIP* scip, /**< SCIP data structure */
954  ZEROHALF_CUTDATA** cutdata, /**< pointer to pointer of data structure */
955  ZEROHALF_SUBLPDATA* relatedsubproblem, /**< pointer to corresponding subproblem */
956  ZEROHALF_MOD2DATA* relatedmod2data, /**< pointer to corresponding mod 2 data */
957  int nrrowsincut, /**< number of preprocessed / mod 2 rows in cut */
958  int nrowsincut, /**< number of original / LP rows in cut */
959  CUTSEPARATEDBY separatedby /**< flag storing the method that separated this cut */
960  )
961 {
962  assert(scip != NULL);
963  assert(cutdata != NULL);
964  assert(nrrowsincut >= 0);
965  assert(nrowsincut >= 0);
966 
967  SCIP_CALL(SCIPallocMemory(scip, cutdata));
968 
969  (*cutdata)->relatedsubproblem = relatedsubproblem;
970  (*cutdata)->relatedmod2data = relatedmod2data;
971 
972  (*cutdata)->cut = NULL;
973 
974  (*cutdata)->success = FALSE;
975  (*cutdata)->isfeasviolated = FALSE;
976  (*cutdata)->islocal = TRUE;
977 
978  (*cutdata)->activity = 0.0;
979  (*cutdata)->rhs = 0.0;
980  (*cutdata)->norm = 0.0;
981  (*cutdata)->efficacy = 0.0;
982  (*cutdata)->violation = 0.0;
983  (*cutdata)->cutrank = 0;
984  (*cutdata)->nnonz = 0;
985 
986  (*cutdata)->nrrowsincut = nrrowsincut;
987  (*cutdata)->nrowsincut = nrowsincut;
988  (*cutdata)->separatedby = separatedby;
989  (*cutdata)->addedtolp = FALSE;
990 
991  return SCIP_OKAY;
992 }
993 
994 
995 /** frees cut data structures */
996 static
998  SCIP* scip, /**< SCIP data structure */
999  ZEROHALF_CUTDATA** cutdata /**< pointer to pointer of data structure */
1000  )
1001 {
1002  assert(scip != NULL);
1003  assert(cutdata != NULL);
1004  assert(*cutdata != NULL);
1005 
1006  if( (*cutdata)->cut != NULL )
1007  {
1008  SCIP_CALL(SCIPreleaseRow(scip, &((*cutdata)->cut)));
1009  }
1010  SCIPfreeMemory(scip, cutdata);
1011  (*cutdata) = NULL;
1012 
1013  return SCIP_OKAY;
1014 }
1015 
1016 
1017 /** creates and initializes auxiliary graph node data structures */
1018 static
1020  SCIP* scip, /**< SCIP data structure */
1021  ZEROHALF_AUXGRAPH_NODE** node /**< pointer to store pointer to created data structure */
1022  )
1023 {
1024  assert(scip != NULL);
1025  assert(node != NULL);
1026 
1027  SCIP_CALL(SCIPallocMemory(scip, node));
1029  (*node)->neighbors = NULL;
1030  (*node)->edgeweights = NULL;
1031  (*node)->relatedrows = NULL;
1032  (*node)->nneighbors = 0;
1033 
1034  (*node)->distance = -1.0;
1035  (*node)->previous = NULL;
1036 
1037  return SCIP_OKAY;
1038 }
1039 
1040 
1041 /** frees auxiliary graph node data structures */
1042 static
1044  SCIP* scip, /**< SCIP data structure */
1045  ZEROHALF_AUXGRAPH_NODE** node /**< pointer to pointer of data structure */
1046  )
1047 {
1048  assert(scip != NULL);
1049  assert(node != NULL);
1050 
1051  if( (*node)->neighbors != NULL )
1052  {
1053  SCIPfreeMemoryArray(scip, &((*node)->neighbors));
1054  }
1055  if( (*node)->edgeweights != NULL )
1056  {
1057  SCIPfreeMemoryArray(scip, &((*node)->edgeweights));
1058  }
1059  if( (*node)->relatedrows != NULL )
1060  {
1061  SCIPfreeMemoryArray(scip, &((*node)->relatedrows));
1062  }
1063  SCIPfreeMemory(scip, node);
1064  (*node) = NULL;
1065 
1066  return SCIP_OKAY;
1067 }
1068 
1069 
1070 /** creates and initializes auxiliary graph data structures */
1071 static
1073  SCIP* scip, /**< SCIP data structure */
1074  ZEROHALF_AUXGRAPH** auxgraph /**< pointer to store pointer to created data structure */
1075  )
1076 {
1077  assert(scip != NULL);
1078  assert(auxgraph != NULL);
1079 
1080  SCIP_CALL(SCIPallocMemory(scip, auxgraph));
1082  (*auxgraph)->nodes = NULL;
1083  (*auxgraph)->nodecopies = NULL;
1084 
1085  (*auxgraph)->nnodes = 0;
1086 
1087  return SCIP_OKAY;
1088 }
1089 
1090 
1091 /** frees auxiliary graph data structures */
1092 static
1094  SCIP* scip, /**< SCIP data structure */
1095  ZEROHALF_AUXGRAPH** auxgraph /**< pointer to pointer of data structure */
1096  )
1097 {
1098  int n;
1099 
1100  assert(scip != NULL);
1101  assert(auxgraph != NULL);
1103  if( (*auxgraph)->nodes != NULL )
1104  {
1105  assert((*auxgraph)->nnodes > 0);
1106  for( n = 0; n < (*auxgraph)->nnodes ; ++n )
1107  if( (*auxgraph)->nodes[n] != NULL )
1108  {
1109  SCIP_CALL(ZerohalfAuxGraphNodeFree(scip, &((*auxgraph)->nodes[n])));
1110  }
1111  SCIPfreeMemoryArray(scip, (&(*auxgraph)->nodes));
1112  }
1113 
1114  if( (*auxgraph)->nodecopies != NULL )
1115  {
1116  assert((*auxgraph)->nnodes > 0);
1117  for( n = 0; n < (*auxgraph)->nnodes ; ++n )
1118  if( (*auxgraph)->nodecopies[n] != NULL )
1119  {
1120  SCIP_CALL(ZerohalfAuxGraphNodeFree(scip, &((*auxgraph)->nodecopies[n])));
1121  }
1122  SCIPfreeMemoryArray(scip, (&(*auxgraph)->nodecopies));
1123  }
1124 
1125  SCIPfreeMemory(scip, auxgraph);
1126  (*auxgraph) = NULL;
1127 
1128  return SCIP_OKAY;
1129 }
1130 
1131 
1132 /* --------------------------------------------------------------------------------------------------------------------
1133  * local methods: debug
1134  * -------------------------------------------------------------------------------------------------------------------- */
1135 
1136 #ifdef SCIP_DEBUG
1137 /** returns a string containing the name of the symbolic constant (given as int value) */
1138 static
1139 char* getconstantname(
1140  char* buffer, /**< string containing the name */
1141  int value /**< symbolic constant given as int value */
1142  )
1143 {
1144  switch( value )
1145  {
1146  case IRRELEVANT:
1147  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "IRRELEVANT"); break;
1148  case ZERO_ROW:
1149  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "ZEROROW"); break;
1151  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "IDENTROW"); break;
1153  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "SLACK>MAXSLACK"); break;
1155  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "ISZHCUT"); break;
1156 #ifdef WITHDECOMPOSE
1157  case ROW_IN_SUBPROB_WITHOUT_ODD_RHS:
1158  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "NOODDRHSROW"); break;
1159 #endif
1160  case NONEXISTENT_ROW:
1161  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "DOESNOTEXIST"); break;
1162  case NO_RELEVANT_COLUMNS:
1163  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "HASNORELEVANTCOLS"); break;
1165  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "SLACK+SODD>MAXSLACK"); break;
1166  case LARGE_COL_EXISTS:
1167  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "SCOL+SODD>MAXSLACK"); break;
1168  case ZERO_COLUMN:
1169  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "ZEROCOLUMN"); break;
1171  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "IDENTCOLUMN"); break;
1172  case ZERO_LP_SOL:
1173  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "PRIMSOL=0"); break;
1174  case LP_SOL_EQUALS_EVEN_LB:
1175  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "PRIMSOL=EVENLB"); break;
1176  case LP_SOL_EQUALS_ODD_LB:
1177  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "PRIMSOL=ODDLB"); break;
1178  case LP_SOL_EQUALS_EVEN_UB:
1179  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "PRIMSOL=EVENUB"); break;
1180  case LP_SOL_EQUALS_ODD_UB:
1181  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "PRIMSOL=ODDUB"); break;
1182  case SINGLETON_COLUMN:
1183  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "SINGLETONCOLUMN"); break;
1184  case CONTINUOUS_VARIABLE:
1185  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "CONTCOLUMN"); break;
1186  case SMALL_FRACSOL_HEUR:
1187  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "SUMFRACSOL<DELTA"); break;
1189  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "NOROWSLEFT"); break;
1190 #ifdef WITHDECOMPOSE
1191  case COLUMN_IN_SUBPROB_WITHOUT_ODD_RHS:
1192  (void) SCIPsnprintf(buffer, SCIP_MAXSTRLEN, "NOODDRHSCOL"); break;
1193 #endif
1194  default:
1195  SCIPerrorMessage("parameter <%s> unknown\n", value);
1196  SCIPABORT();
1197  }
1198 
1199  return buffer;
1200 }
1201 #endif
1202 
1203 
1204 #ifdef ZEROHALF__PRINT_STATISTICS
1205 /** prints the preprocessing statistics of the basic preprocessing applied while
1206  reading the LP data and building basic data structures */
1207 static
1208 SCIP_RETCODE printPreprocessingStatistics(
1209  SCIP* scip, /**< SCIP data structure */
1210  ZEROHALF_LPDATA* lpdata /**< data of current LP relaxation */
1211  )
1212 {
1213  int i;
1214  int nrelevantrows;
1215  int nirrelevantrows;
1216  int nerrors;
1217  int nrelevantcols;
1218  int nirrelevantcols;
1219  int nrows;
1220  int ncols;
1221  int nnonexistingrows;
1222 
1223  assert(lpdata != NULL);
1224 
1225  nrelevantrows = 0;
1226  nirrelevantrows = 0;
1227  nnonexistingrows = 0;
1228  nrelevantcols = 0;
1229  nirrelevantcols = 0;
1230  nerrors = 0;
1231 
1232  for( i = 0 ; i < lpdata->nrows ; ++i)
1233  {
1234  if( lpdata->rrowsindexofleftrow[i] >= 0 )
1235  nrelevantrows++;
1236  else
1237  if( lpdata->rrowsindexofleftrow[i] < -199 )
1238  nerrors++;
1239  else
1240  if( lpdata->rrowsindexofleftrow[i] == NONEXISTENT_ROW )
1241  nnonexistingrows++;
1242  else
1243  nirrelevantrows++;
1244  if( lpdata->rrowsindexofrightrow[i] >= 0 )
1245  nrelevantrows++;
1246  else
1247  if( lpdata->rrowsindexofrightrow[i] < -199 )
1248  nerrors++;
1249  else
1250  if( lpdata->rrowsindexofrightrow[i] == NONEXISTENT_ROW )
1251  nnonexistingrows++;
1252  else
1253  nirrelevantrows++;
1254  }
1255 
1256  for( i = 0 ; i < lpdata->ncols ; ++i)
1257  {
1258  if( lpdata->rcolsindexofcol[i] >= 0 )
1259  nrelevantcols++;
1260  else
1261  if( lpdata->rcolsindexofcol[i] == -1 )
1262  nirrelevantcols++;
1263  else
1264  if( lpdata->rcolsindexofcol[i] > -200 || lpdata->rcolsindexofcol[i] < -299 )
1265  nerrors++;
1266  else
1267  nirrelevantcols++;
1268  }
1269 
1270  nrows = nrelevantrows + nirrelevantrows - nnonexistingrows;
1271  ncols = nrelevantcols + nirrelevantcols;
1272 
1273  ZEROHALFstatisticsMessage("\n");
1274  ZEROHALFstatisticsMessage(" | ----- lp data ----- | --- (reductions) -- | --- problem data -- | -lpdata- | -(red.)- | -probd.- | --------\n");
1275  ZEROHALFstatisticsMessage(" | nrows | ncols | ndelrows | ndelcols | nrrows | nrcols | nvarbnds | ndlvbnds | nvarbnds | \n");
1276  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8d | %8d | %8d | %8d | %8d |\n",
1277  "READING LPDATA", nrows, ncols, nirrelevantrows - nnonexistingrows, nirrelevantcols, nrelevantrows, nrelevantcols,
1278  lpdata->nvarbounds, lpdata->ndelvarbounds, lpdata->nvarbounds - lpdata->ndelvarbounds);
1279 
1280  return SCIP_OKAY;
1281 }
1282 #endif
1283 
1284 
1285 #ifdef SCIP_DEBUG
1286 /** prints the considered subproblem */
1287 static
1288 void debugPrintSubLpData(
1289  SCIP* scip, /**< SCIP data structure */
1290  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
1291  ZEROHALF_SUBLPDATA* sublpdata /**< considered subproblem */
1292  )
1293 {
1294  int i;
1295  int j;
1296 
1297  assert(scip != NULL);
1298  assert(lpdata != NULL);
1299  assert(sublpdata != NULL);
1300 
1301 
1302  SCIPdebugMessage("\n debugPrintSubLpData:\n\n");
1303 
1304  SCIPdebugMessage(" rrows: (nrrows=%d)\n", sublpdata->nrrows);
1305  for( i = 0 ; i < sublpdata->nrrows ; ++i)
1306  {
1307  SCIPdebugMessage(" %6d: rrows: %6d rhs: %6g slack: %6g name: %s\n",
1308  i, sublpdata->rrows[i], sublpdata->rrowsrhs[i], sublpdata->rrowsslack[i],
1309  SCIProwGetName(lpdata->rows[sublpdata->rrows[i]]));
1310  }
1311  SCIPdebugMessage("\n rcols: (nrcols=%d)\n", sublpdata->nrcols);
1312  for( j = 0 ; j < sublpdata->nrcols ; ++j)
1313  {
1314  SCIPdebugMessage(" %6d: rcols: %6d lbslack: %6g ubslack: %6g\n",
1315  i, sublpdata->rcols[i], sublpdata->rcolslbslack[i], sublpdata->rcolsubslack[i]);
1316  }
1317 }
1318 #endif
1319 
1320 
1321 #ifdef SCIP_DEBUG
1322 /** prints mod 2 data structures */
1323 static
1324 void debugPrintMod2Data(
1325  SCIP* scip, /**< SCIP data structure */
1326  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
1327  ZEROHALF_MOD2DATA* mod2data, /**< considered mod 2 data structure */
1328  SCIP_Bool printaggregations /**< should row aggregation bitarrays be printed? */
1329  )
1330 {
1331  int i;
1332  int j;
1333  int k;
1334 
1335  assert(scip != NULL);
1336  assert(lpdata != NULL);
1337  assert(mod2data != NULL);
1338 
1339 
1340  SCIPdebugMessage("\n debugPrintMod2Data:\n\n");
1341 
1342  SCIPdebugMessage(" nrows = %d, nvarbounds = %d, nrcols = %d, nrowsind = %d, ncolsind = %d\n",
1343  mod2data->nrows, mod2data->nvarbounds, mod2data->relatedsubproblem->nrcols,
1344  mod2data->nrowsind, mod2data->ncolsind);
1345  SCIPdebugMessage(" rowsbitarraysize = %d, rowaggregationsbitarraysize = %d\n",
1346  mod2data->rowsbitarraysize, mod2data->rowaggregationsbitarraysize);
1347 
1348 
1349  SCIPdebugMessage("\n fracsol:\n");
1350  for( j = 0 ; j < mod2data->relatedsubproblem->nrcols ; ++j )
1351  {
1352  for( k = 0 ; k < mod2data->ncolsind ; ++k )
1353  if( mod2data->colsind[k] == j )
1354  break;
1355  SCIPdebugMessage(" rcols[%6d]: fracsol: %6g colsind: %6d name: %s\n", j, mod2data->fracsol[j],
1356  k < mod2data->ncolsind ? k : -1,
1357  SCIPvarGetName(SCIPcolGetVar(lpdata->cols[mod2data->relatedsubproblem->rcols[j]])));
1358  }
1359 
1360  SCIPdebugMessage("\n (A mod 2, b mod 2, [#nonz] (slacks), R, name(rrows), left(-)/right(+):\n");
1361  if( mod2data->nrowsind == 0 )
1362  {
1363  SCIPdebugMessage(" empty\n");
1364  }
1365  for( i = 0 ; i < mod2data->nrowsind ; ++i )
1366  {
1367  int nnonz = 0;
1368  SCIPdebugMessage(" ");
1369  for( j = 0 ; j < mod2data->ncolsind; ++j )
1370  if( BITARRAYBITISSET(mod2data->rows[mod2data->rowsind[i]], mod2data->colsind[j]) ) /*lint !e701*/
1371  {
1372  nnonz++;
1373  SCIPdebugPrintf("1");
1374  }
1375  else
1376  {
1377  SCIPdebugPrintf(".");
1378  }
1379  if( mod2data->rhs[mod2data->rowsind[i]] )
1380  {
1381  SCIPdebugPrintf(" 1");
1382  }
1383  else
1384  {
1385  SCIPdebugPrintf(" 0");
1386  }
1387  SCIPdebugPrintf(" [%4d] ", nnonz);
1388  SCIPdebugPrintf("(%6g) ", mod2data->slacks[mod2data->rowsind[i]]);
1389 
1390  if( printaggregations )
1391  {
1392  for( j = 0 ; j < mod2data->relatedsubproblem->nrrows; ++j )
1393  if( BITARRAYBITISSET(mod2data->rowaggregations[mod2data->rowsind[i]], j) ) /*lint !e701*/
1394  {
1395  SCIPdebugPrintf("1");
1396  }
1397  else
1398  {
1399  SCIPdebugPrintf(".");
1400  }
1401  }
1402 
1403  if( mod2data->rowsind[i] < mod2data->nrows - mod2data->nvarbounds )
1404  {
1405  SCIPdebugPrintf(" %s ", SCIProwGetName(lpdata->rows[mod2data->relatedsubproblem->rrows[mod2data->rowsind[i]]]));
1406  if( lpdata->rrowsindexofleftrow[mod2data->relatedsubproblem->rrows[mod2data->rowsind[i]]] == mod2data->rowsind[i] )
1407  {
1408  SCIPdebugPrintf(" -\n");
1409  }
1410  else
1411  {
1412  SCIPdebugPrintf(" +\n");
1413  }
1414  }
1415  else
1416  {
1417  SCIPdebugPrintf(" varbound(rows[%d])\n", mod2data->rowsind[i]);
1418  }
1419  }
1420  SCIPdebugPrintf("\n");
1421 }
1422 #endif
1423 
1424 
1425 #ifdef SCIP_DEBUG
1426 /** prints LP data */
1427 static
1428 SCIP_RETCODE debugPrintLPRowsAndCols(
1429  SCIP* scip, /**< SCIP data structure */
1430  ZEROHALF_LPDATA* lpdata /**< data of current LP relaxation */
1431  )
1432 {
1433  int i;
1434  int j;
1435  char temp[SCIP_MAXSTRLEN];
1436 
1437  assert(scip != NULL);
1438  assert(lpdata != NULL);
1439 
1440  SCIPdebugMessage("\n\nLP rows:\n");
1441  for( i = 0 ; i < lpdata->nrows ; ++i)
1442  {
1443  SCIPdebugMessage("\nrow %d (left): %s[%d,%d] %s:\n", i,
1444  (lpdata->subproblemsindexofrow[i] == IRRELEVANT)
1445  || (lpdata->rrowsindexofleftrow[i] < 0) ? "IRRELEVANT" : "RELEVANT",
1446  lpdata->subproblemsindexofrow[i], lpdata->rrowsindexofleftrow[i],
1447  lpdata->rrowsindexofleftrow[i] < 0 ? getconstantname(temp, lpdata->rrowsindexofleftrow[i]) : "");
1448  SCIPdebugMessage("row %d (right): %s[%d,%d] %s:\n", i,
1449  (lpdata->subproblemsindexofrow[i] == IRRELEVANT)
1450  || (lpdata->rrowsindexofrightrow[i] < 0) ? "IRRELEVANT" : "RELEVANT",
1451  lpdata->subproblemsindexofrow[i], lpdata->rrowsindexofrightrow[i],
1452  lpdata->rrowsindexofrightrow[i] < 0 ? getconstantname(temp, lpdata->rrowsindexofrightrow[i]) : "");
1453  SCIP_CALL( SCIPprintRow(scip, lpdata->rows[i], NULL) );
1454  }
1455 
1456  SCIPdebugMessage("\n\nLP cols:\n");
1457  for( j = 0 ; j < lpdata->ncols ; ++j)
1458  {
1459  SCIPdebugMessage("\ncol %d: %s[%d,%d] %s:\n", j,
1460  (lpdata->subproblemsindexofcol[j] == IRRELEVANT)
1461  || (lpdata->rcolsindexofcol[j] < 0) ? "IRRELEVANT" : "RELEVANT",
1462  lpdata->subproblemsindexofcol[j], lpdata->rcolsindexofcol[j],
1463  lpdata->rcolsindexofcol[j] < 0 ? getconstantname(temp, lpdata->rcolsindexofcol[j]) : "");
1464  SCIPdebugMessage("%s = %f\n",
1465  SCIPvarGetName(SCIPcolGetVar(lpdata->cols[j])),
1466  SCIPcolGetPrimsol(lpdata->cols[j]));
1467  }
1468 
1469  return SCIP_OKAY;
1470 }
1471 #endif
1472 
1473 
1474 /* --------------------------------------------------------------------------------------------------------------------
1475  * local methods: SCIPsortInd comparators
1476  * -------------------------------------------------------------------------------------------------------------------- */
1477 
1478 
1479 /** comparator function for sorting an index array non-decreasingly according to a real array */
1480 static
1481 SCIP_DECL_SORTINDCOMP(compRealNonDecreasing)
1482 {
1483  SCIP_Real* scores;
1484 
1485  scores = (SCIP_Real*) dataptr;
1486 
1487  if( scores[ind1] < scores[ind2] )
1488  return -1;
1489  else if( scores[ind1] > scores[ind2] )
1490  return +1;
1491  else
1492  return 0;
1493 }
1494 
1495 
1496 /** comparator function for sorting an index array non-increasingly according to a real array */
1497 static
1498 SCIP_DECL_SORTINDCOMP(compRealNonIncreasing)
1499 {
1500  SCIP_Real* scores;
1501 
1502  scores = (SCIP_Real*) dataptr;
1503 
1504  if( scores[ind1] < scores[ind2] )
1505  return +1;
1506  else if( scores[ind1] > scores[ind2] )
1507  return -1;
1508  else
1509  return 0;
1510 }
1511 
1512 
1513 /* --------------------------------------------------------------------------------------------------------------------
1514  * local methods: LP data
1515  * -------------------------------------------------------------------------------------------------------------------- */
1516 
1517 
1518 /** searches for relevant columns, i.e., columns that cannot be deleted because of basic preprocessing methods */
1519 static
1521  SCIP* scip, /**< SCIP data structure */
1522  ZEROHALF_LPDATA* lpdata /**< data of current LP relaxation */
1523  )
1524 {
1525  SCIP_VAR* var;
1526  SCIP_COL* col;
1527  SCIP_Real primsol;
1528  SCIP_Real lb;
1530  SCIP_Real lbslack;
1531  SCIP_Real ubslack;
1532  ZEROHALF_SUBLPDATA* problem;
1533  int j;
1534 #ifdef ZEROHALF__PRINT_STATISTICS
1535  int tempnvarbnds;
1536 #endif
1537  int nsubproblems;
1538 
1539  assert(scip != NULL);
1540  assert(lpdata != NULL);
1541  assert(lpdata->cols != NULL);
1542  assert(lpdata->ncols > 0);
1543  assert(lpdata->nrows > 0);
1544  assert(lpdata->subproblems == NULL);
1545  assert(lpdata->nsubproblems == 0);
1546  assert(lpdata->subproblemsindexofrow == NULL);
1547  assert(lpdata->rrowsindexofleftrow == NULL);
1548  assert(lpdata->rrowsindexofrightrow == NULL);
1549  assert(lpdata->subproblemsindexofcol == NULL);
1550  assert(lpdata->rcolsindexofcol == NULL);
1551  assert(lpdata->bestlbidxofcol == NULL);
1552  assert(lpdata->bestubidxofcol == NULL);
1553 
1554  nsubproblems = 1;
1555 
1556  /* allocate temporary memory for column data structures */
1557  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->subproblems), nsubproblems)); /* create one "sub"problem */
1558  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->subproblemsindexofcol), lpdata->ncols));
1559  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->rcolsindexofcol), lpdata->ncols));
1560  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->bestlbidxofcol), lpdata->ncols));
1561  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->bestubidxofcol), lpdata->ncols));
1562 
1563  SCIP_CALL(ZerohalfSubLPDataCreate(scip, &problem));
1564  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rcols), lpdata->ncols));
1565  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rcolslbslack), lpdata->ncols));
1566  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rcolsubslack), lpdata->ncols));
1567 
1568  /* initialize data */
1569  BMSclearMemoryArray(lpdata->subproblemsindexofcol, lpdata->ncols);
1570  BMSclearMemoryArray(lpdata->rcolsindexofcol, lpdata->ncols);
1571 
1572  lpdata->nsubproblems = 1;
1573  lpdata->subproblems[0] = problem;
1574  lpdata->nvarbounds = 0;
1575  lpdata->ndelvarbounds = 0;
1576 
1577  /* check all cols */
1578  for( j = 0 ; j < lpdata->ncols ; ++j)
1579  {
1580  /* initialize best lb and best ub (-2: undetermined)*/
1581  lpdata->bestlbidxofcol[j] = -2;
1582  lpdata->bestubidxofcol[j] = -2;
1583 
1584  col = lpdata->cols[j];
1585  var = SCIPcolGetVar(col);
1586 
1587  /* check if vartype is continuous */
1589  {
1590  primsol = SCIPcolGetPrimsol(col);
1591  if( SCIPisFeasZero(scip, primsol) )
1592  primsol = 0.0;
1593 
1594  assert(SCIPisFeasEQ(scip, SCIPgetVarSol(scip, var), primsol));
1595 
1596  lb = SCIPcolGetLb(col);
1597  ub = SCIPcolGetUb(col);
1598  lbslack = primsol - lb;
1599  ubslack = ub - primsol;
1600  if( SCIPisFeasZero(scip, lbslack) )
1601  lbslack = 0.0;
1602  if( SCIPisFeasZero(scip, ubslack) )
1603  ubslack = 0.0;
1604  assert(SCIPisLE(scip, lb, ub));
1605  assert(!SCIPisNegative(scip, lbslack));
1606  assert(!SCIPisNegative(scip, ubslack));
1607 
1608 #ifdef ZEROHALF__PRINT_STATISTICS
1609  tempnvarbnds = 0;
1610  if( !SCIPisInfinity(scip, (-1) * lb) )
1611  tempnvarbnds++;
1612  if( !SCIPisInfinity(scip, ub) )
1613  tempnvarbnds++;
1614  lpdata->nvarbounds += tempnvarbnds;
1615 #endif
1616 
1617  if( SCIPisNegative(scip, lb) )
1618  {
1619  /* column is declared to be irrelevant because its lower bound is negative,
1620  * variable would have to be shifted, complemented or decomposed.
1621  */
1622  /**@todo consider general integers with negative lower bounds and transform to positive representation
1623  * and propagate through corresponding rows. In the current version, redundant inequalities might be
1624  * considered as cut candidates and valid cuts might be missed, but no wrong cuts should be produced
1625  * (due to SCIPcalcMIR) this leads to performance deterioration in the (rare) case of general integers
1626  * with negative bounds.
1627  */
1628  lpdata->subproblemsindexofcol[j] = IRRELEVANT;
1629  lpdata->rcolsindexofcol[j] = IRRELEVANT;
1630  }
1631  else if( !SCIPisZero(scip, primsol) )
1632  {
1633  if( SCIPisZero(scip, lbslack) )
1634  {
1635 #ifdef ZEROHALF__PRINT_STATISTICS
1636  lpdata->ndelvarbounds += tempnvarbnds;
1637 #endif
1638  lpdata->subproblemsindexofcol[j] = IRRELEVANT;
1639  if( ISODD(scip, lb) )
1640  lpdata->rcolsindexofcol[j] = LP_SOL_EQUALS_ODD_LB;
1641  else
1642  lpdata->rcolsindexofcol[j] = LP_SOL_EQUALS_EVEN_LB;
1643  }
1644  else
1645  {
1646  if( SCIPisZero(scip, ubslack) )
1647  {
1648 #ifdef ZEROHALF__PRINT_STATISTICS
1649  lpdata->ndelvarbounds += tempnvarbnds;
1650 #endif
1651  lpdata->subproblemsindexofcol[j] = IRRELEVANT;
1652  if( ISODD(scip, ub) )
1653  lpdata->rcolsindexofcol[j] = LP_SOL_EQUALS_ODD_UB;
1654  else
1655  lpdata->rcolsindexofcol[j] = LP_SOL_EQUALS_EVEN_UB;
1656  }
1657  else
1658  {
1659  /* relevant col was found */
1660  problem->rcols[problem->nrcols] = j;
1661  problem->rcolslbslack[problem->nrcols] = lbslack;
1662  problem->rcolsubslack[problem->nrcols] = ubslack;
1663  lpdata->subproblemsindexofcol[j] = 0;
1664  lpdata->rcolsindexofcol[j] = problem->nrcols;
1665  problem->nrcols++;
1666  }
1667  }
1668  }
1669  else
1670  {
1671 #ifdef ZEROHALF__PRINT_STATISTICS
1672  lpdata->ndelvarbounds += tempnvarbnds;
1673 #endif
1674  lpdata->subproblemsindexofcol[j] = IRRELEVANT;
1675  lpdata->rcolsindexofcol[j] = ZERO_LP_SOL;
1676  }
1677  }
1678  else
1679  {
1680  /* column is irrelevant because vartype is continuous (is handled in getRelevantRows())*/
1681  lpdata->subproblemsindexofcol[j] = IRRELEVANT;
1682  lpdata->rcolsindexofcol[j] = CONTINUOUS_VARIABLE;
1683  }
1684  }
1685 
1686  return SCIP_OKAY;
1687 }
1688 
1689 
1690 /** finds closest lower bound of col and stores it within lpdata;
1691  * the bound can be the lower bound or the best variable lower bound with nonnegative column variable
1692  */
1693 static
1694 void findClosestLb(
1695  SCIP* scip, /**< SCIP data structure */
1696  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
1697  SCIP_COL* col, /**< column to get closest lower bound */
1698  SCIP_Real* bestlbsol, /**< pointer to store value of closest lower bound */
1699  int* bestlbtype, /**< pointer to store type of closest lower bound */
1700  SCIP_VAR** bestzvlb, /**< pointer to store variable z in closest variable lower bound b*z + d */
1701  SCIP_Real* bestbvlb, /**< pointer to store coefficient b in closest variable lower bound b*z + d */
1702  SCIP_Real* bestdvlb /**< pointer to store constant d in closest variable lower bound b*z + d */
1704  )
1705 {
1706  SCIP_VAR* var;
1707  SCIP_VAR** zvlb;
1708  SCIP_Real* bvlb;
1709  SCIP_Real* dvlb;
1710  int collppos;
1711  int nvlb;
1712  int j;
1713 
1714  assert(lpdata != NULL);
1715  assert(bestlbsol != NULL);
1716  assert(bestlbtype != NULL);
1717  assert(bestzvlb != NULL);
1718  assert(bestbvlb != NULL);
1719  assert(bestdvlb != NULL);
1720 
1721 
1722  collppos = SCIPcolGetLPPos(col);
1723  var = SCIPcolGetVar(col);
1724  *bestlbsol = SCIPcolGetLb(col);
1725  *bestlbtype = lpdata->bestlbidxofcol[collppos];
1726  *bestzvlb = NULL;
1727  *bestbvlb = 0.0;
1728  *bestdvlb = 0.0;
1729 
1730  if( *bestlbtype == -1 )
1731  return;
1732 
1733  if( USEVARBOUNDS ) /*lint !e774 !e506*/
1734  {
1735  nvlb = SCIPvarGetNVlbs(var);
1736  zvlb = SCIPvarGetVlbVars(var);
1737  bvlb = SCIPvarGetVlbCoefs(var);
1738  dvlb = SCIPvarGetVlbConstants(var);
1739 
1740  assert(zvlb != NULL || nvlb == 0);
1741  assert(bvlb != NULL || nvlb == 0);
1742  assert(dvlb != NULL || nvlb == 0);
1743  }
1744 
1745  if( *bestlbtype == -2 )
1746  {
1747  if( USEVARBOUNDS ) /*lint !e774 !e506*/
1748  {
1749 
1750  /* search for lb or vlb with maximal bound value */
1751  for( j = 0; j < nvlb; j++ )
1752  {
1753  assert(zvlb != NULL);
1754  assert(bvlb != NULL);
1755  assert(dvlb != NULL);
1756  assert(SCIPvarGetType(zvlb[j]) != SCIP_VARTYPE_CONTINUOUS);
1757 
1758  /* use only vlb with nonnegative variable z that are column variables and present in the current LP */
1759  if( SCIPvarGetStatus(zvlb[j]) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(SCIPvarGetCol(zvlb[j])) &&
1760  !SCIPisNegative(scip, SCIPcolGetLb(SCIPvarGetCol(zvlb[j]))) )
1761  {
1762  SCIP_Real vlbsol;
1763 
1764  vlbsol = bvlb[j] * SCIPcolGetPrimsol(SCIPvarGetCol(zvlb[j])) + dvlb[j];
1765  if( vlbsol > *bestlbsol )
1766  {
1767  *bestlbsol = vlbsol;
1768  *bestlbtype = j;
1769  }
1770  }
1771  }
1772  }
1773 
1774  /* if no better var bound could be found, set type to the fixed bound (-1) */
1775  if( *bestlbtype == -2 )
1776  *bestlbtype = -1;
1777 
1778  /* store best bound for substitution */
1779  lpdata->bestlbidxofcol[collppos] = *bestlbtype;
1780  }
1781  assert(lpdata->bestlbidxofcol[collppos] > -2);
1782 
1783  if( *bestlbtype >= 0 )
1784  {
1785  assert(USEVARBOUNDS); /*lint !e774 !e506*/
1786  assert(*bestlbtype < nvlb);
1787  assert(zvlb != NULL);
1788  assert(bvlb != NULL);
1789  assert(dvlb != NULL);
1790  *bestzvlb = zvlb[*bestlbtype];
1791  *bestbvlb = bvlb[*bestlbtype];
1792  *bestdvlb = dvlb[*bestlbtype];
1793  }
1794 }
1795 
1796 
1797 /** finds closest upper bound of col and stores it within lpdata;
1798  * the bound can be the upper bound or the best variable upper bound with nonnegative column variable
1799  */
1800 static
1801 void findClosestUb(
1802  SCIP* scip, /**< SCIP data structure */
1803  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
1804  SCIP_COL* col, /**< column to get closest upper bound */
1805  SCIP_Real* bestubsol, /**< pointer to store value of closest upper bound */
1806  int* bestubtype, /**< pointer to store type of closest upper bound */
1807  SCIP_VAR** bestzvub, /**< pointer to store variable z in closest variable upper bound b*z + d */
1808  SCIP_Real* bestbvub, /**< pointer to store coefficient b in closest variable upper bound b*z + d */
1809  SCIP_Real* bestdvub /**< pointer to store constant d in closest variable upper bound b*z + d */
1811  )
1812 {
1813  SCIP_VAR* var;
1814  SCIP_VAR** zvub;
1815  SCIP_Real* bvub;
1816  SCIP_Real* dvub;
1817  int collppos;
1818  int nvub;
1819  int j;
1820 
1821  assert(lpdata != NULL);
1822  assert(bestubsol != NULL);
1823  assert(bestubtype != NULL);
1824  assert(bestzvub != NULL);
1825  assert(bestbvub != NULL);
1826  assert(bestdvub != NULL);
1827 
1828  collppos = SCIPcolGetLPPos(col);
1829  var = SCIPcolGetVar(col);
1830  *bestubsol = SCIPcolGetUb(col);
1831  *bestubtype = lpdata->bestubidxofcol[collppos];
1832  *bestzvub = NULL;
1833  *bestbvub = 0.0;
1834  *bestdvub = 0.0;
1835 
1836  if( *bestubtype == -1 )
1837  return;
1838 
1839  if( USEVARBOUNDS ) /*lint !e774 !e506*/
1840  {
1841  nvub = SCIPvarGetNVubs(var);
1842  zvub = SCIPvarGetVubVars(var);
1843  bvub = SCIPvarGetVubCoefs(var);
1844  dvub = SCIPvarGetVubConstants(var);
1845 
1846  assert(zvub != NULL || nvub == 0);
1847  assert(bvub != NULL || nvub == 0);
1848  assert(dvub != NULL || nvub == 0);
1849  }
1850 
1851  if( *bestubtype == -2 )
1852  {
1853  if( USEVARBOUNDS ) /*lint !e774 !e506*/
1854  {
1855  /* search for ub or vub with maximal bound value */
1856  for( j = 0; j < nvub; j++ )
1857  {
1858  assert(zvub != NULL);
1859  assert(bvub != NULL);
1860  assert(dvub != NULL);
1861  assert(SCIPvarGetType(zvub[j]) != SCIP_VARTYPE_CONTINUOUS);
1862 
1863  /* use only vub with nonnegative variable z that are column variables and present in the current LP */
1864  if( SCIPvarGetStatus(zvub[j]) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(SCIPvarGetCol(zvub[j])) &&
1865  !SCIPisNegative(scip, SCIPcolGetUb(SCIPvarGetCol(zvub[j]))) )
1866  {
1867  SCIP_Real vubsol;
1868 
1869  vubsol = bvub[j] * SCIPcolGetPrimsol(SCIPvarGetCol(zvub[j])) + dvub[j];
1870  if( vubsol < *bestubsol )
1871  {
1872  *bestubsol = vubsol;
1873  *bestubtype = j;
1874  }
1875  }
1876  }
1877  }
1878  /* if no better var bound could be found, set type to the fixed bound (-1) */
1879  if( *bestubtype == -2 )
1880  *bestubtype = -1;
1881 
1882  /* store best bound for substitution */
1883  lpdata->bestubidxofcol[collppos] = *bestubtype;
1884  }
1885  assert(lpdata->bestubidxofcol[collppos] > -2);
1886 
1887  if( *bestubtype >= 0 )
1888  {
1889  assert(USEVARBOUNDS); /*lint !e774 !e506*/
1890  assert(*bestubtype < nvub);
1891  assert(zvub != NULL);
1892  assert(bvub != NULL);
1893  assert(dvub != NULL);
1894  *bestzvub = zvub[*bestubtype];
1895  *bestbvub = bvub[*bestubtype];
1896  *bestdvub = dvub[*bestubtype];
1897  }
1898 }
1899 
1900 
1901 /** searches for relevant rows, i.e., rows containing relevant columns that cannot be deleted because of basic
1902  * preprocessing methods
1903  */
1904 static
1906  SCIP* scip, /**< SCIP data structure */
1907  SCIP_SEPADATA* sepadata, /**< separator data */
1908  ZEROHALF_LPDATA* lpdata /**< data of current LP relaxation */
1909  )
1910 {
1911  SCIP_COL** colscurrentrow;
1912  SCIP_Real* valscurrentrow;
1913  SCIP_Real* densecoeffscurrentleftrow;
1914  SCIP_Real* densecoeffscurrentrightrow;
1915  SCIP_ROW* row;
1916  SCIP_VAR* var;
1917  SCIP_VAR* bestzvbnd;
1918  SCIP_Real bestbndsol;
1919  SCIP_Real bestbvbnd;
1920  SCIP_Real bestdvbnd;
1921  SCIP_Real intscalarleftrow;
1922  SCIP_Real intscalarrightrow;
1923  SCIP_Real act;
1924  SCIP_Real cst;
1925  SCIP_Real lhs;
1926  SCIP_Real lhsslack;
1927  SCIP_Real maxslack;
1928  SCIP_Real rhs;
1929  SCIP_Real rhsslack;
1930  int bestbndtype;
1931  int nnonzcurrentrow;
1932  int c;
1933  int r;
1934  int k;
1935  SCIP_Bool lhsslackislessequalmaxslack;
1936  SCIP_Bool rhsslackislessequalmaxslack;
1937  SCIP_Bool lhsisinfinity;
1938  SCIP_Bool rhsisinfinity;
1939  SCIP_Bool lhsiseven;
1940  SCIP_Bool rhsiseven;
1941  SCIP_Bool success;
1942  ZEROHALF_SUBLPDATA* problem;
1943 
1944  int collppos;
1945  SCIP_Bool rowisrelevant;
1946 
1947  assert(scip != NULL);
1948  assert(sepadata != NULL);
1949  assert(lpdata != NULL);
1950  assert(lpdata->rows != NULL);
1951  assert(lpdata->nrows > 0);
1952  assert(lpdata->subproblemsindexofcol != NULL);
1953  assert(lpdata->rcolsindexofcol != NULL);
1954  assert(lpdata->subproblems != NULL);
1955  assert(lpdata->nsubproblems > 0);
1956 
1957  assert(lpdata->subproblemsindexofrow == NULL);
1958  assert(lpdata->rrowsindexofleftrow == NULL);
1959  assert(lpdata->rrowsindexofrightrow == NULL);
1960 
1961  k = 0;
1962  problem = lpdata->subproblems[k];
1963 
1964  assert(k >= 0);
1965  assert(k <= lpdata->nsubproblems);
1966  assert(problem != NULL);
1967  assert(problem->rcols != NULL);
1968  assert(problem->nrcols > 0);
1969  assert(problem->rcolslbslack != NULL);
1970  assert(problem->rcolsubslack != NULL);
1971 
1972  assert(problem->rrows == NULL);
1973  assert(problem->rrowsrhs == NULL);
1974  assert(problem->rrowsslack == NULL);
1975 
1976  /* allocate temporary memory for row data structures */
1977  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->subproblemsindexofrow), lpdata->nrows));
1978  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->rrowsindexofleftrow), lpdata->nrows));
1979  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->rrowsindexofrightrow), lpdata->nrows));
1980  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rrows), 2 * lpdata->nrows));
1981  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rrowsrhs), 2 * lpdata->nrows));
1982  SCIP_CALL(SCIPallocMemoryArray(scip, &(problem->rrowsslack), 2 * lpdata->nrows));
1983 
1984  /* allocate temporary memory */
1985  SCIP_CALL(SCIPallocBufferArray(scip, &densecoeffscurrentleftrow, lpdata->ncols));
1986  SCIP_CALL(SCIPallocBufferArray(scip, &densecoeffscurrentrightrow, lpdata->ncols));
1987 
1988  /* initialize arrays */
1989  BMSclearMemoryArray(lpdata->subproblemsindexofrow, lpdata->nrows);
1990  BMSclearMemoryArray(lpdata->rrowsindexofleftrow, lpdata->nrows);
1991  BMSclearMemoryArray(lpdata->rrowsindexofrightrow, lpdata->nrows);
1992  BMSclearMemoryArray(densecoeffscurrentleftrow, lpdata->ncols);
1993  BMSclearMemoryArray(densecoeffscurrentrightrow, lpdata->ncols);
1994 
1995  maxslack = sepadata->maxslack;
1996  problem->nrrows = 0;
1997  for( r = 0 ; r < lpdata->nrows ; ++r)
1998  {
1999  row = lpdata->rows[r];
2000 
2001  if( sepadata->ignoreprevzhcuts )
2002  {
2003  /* ignore rows whose names start with "zerohalf" */
2004  const char* rowname = SCIProwGetName(row);
2005 
2006  if( strlen(rowname) > 8 )
2007  if(rowname[0] == 'z'
2008  && rowname[1] == 'e'
2009  && rowname[2] == 'r'
2010  && rowname[3] == 'o'
2011  && rowname[4] == 'h'
2012  && rowname[5] == 'a'
2013  && rowname[6] == 'l'
2014  && rowname[7] == 'f' )
2015  {
2016  lpdata->subproblemsindexofrow[r] = IRRELEVANT;
2017  lpdata->rrowsindexofleftrow[r] = NONEXISTENT_ROW;
2018  lpdata->rrowsindexofrightrow[r] = NONEXISTENT_ROW;
2019  continue;
2020  }
2021  }
2022 
2023  /* check if current row is an original LP row (i.e., was not added) if necessary */
2024  if( sepadata->onlyorigrows )
2025  {
2026  int left;
2027  int center;
2028  int right;
2029  int rowindex;
2030 
2031  assert(sepadata->origrows != NULL);
2032  assert(sepadata->norigrows > 0);
2033 
2034  left = 0;
2035  center = 1;
2036  right = sepadata->norigrows - 1;
2037  rowindex = SCIProwGetIndex(row);
2038  while( left <= right && center > -1 )
2039  {
2040  center = left + ((right - left) / 2);
2041  if( sepadata->origrows[center] == rowindex )
2042  center = -1;
2043  if( sepadata->origrows[center] > rowindex )
2044  right = center - 1;
2045  else
2046  left = center + 1;
2047  }
2048  if( center > -1 )
2049  {
2050  lpdata->subproblemsindexofrow[r] = IRRELEVANT;
2051  lpdata->rrowsindexofleftrow[r] = NONEXISTENT_ROW;
2052  lpdata->rrowsindexofrightrow[r] = NONEXISTENT_ROW;
2053  continue;
2054  }
2055  }
2056 
2057  /* get row data */
2058  colscurrentrow = SCIProwGetCols(row);
2059  nnonzcurrentrow = SCIProwGetNLPNonz(row);
2060  valscurrentrow = SCIProwGetVals(row);
2061 
2062  /* clear dense coeffs arrays */
2063  BMSclearMemoryArray(densecoeffscurrentleftrow, lpdata->ncols);
2064  BMSclearMemoryArray(densecoeffscurrentrightrow, lpdata->ncols);
2065 
2066  /* calculate dense coeffs arrays */
2067  for( c = 0; c < nnonzcurrentrow; ++c)
2068  {
2069  collppos = SCIPcolGetLPPos(colscurrentrow[c]);
2070  assert(0 <= collppos && collppos < lpdata->ncols);
2071 
2072  var = SCIPcolGetVar(colscurrentrow[c]);
2073 
2074  /* check if row contains a continuous variable */
2076  {
2077  bestzvbnd = NULL;
2078  bestbndsol = 0.0;
2079  bestbvbnd = 0.0;
2080  bestdvbnd = 0.0;
2081  bestbndtype = -2;
2082 
2083  /* Consider rhs of row and relax continuous variables by substituting for:
2084  * - a_j > 0: x_j = lb or x_j = b*z + d with variable lower bound b*z + d with column var z >= 0
2085  * - a_j < 0: x_j = ub or x_j = b*z + d with variable upper bound b*z + d with column var z >= 0
2086  * and
2087  * consider lhs of row and relax continuous variables by substituting for:
2088  * - a_j < 0: x_j = lb or x_j = b*z + d with variable lower bound b*z + d with column var z >= 0
2089  * - a_j > 0: x_j = ub or x_j = b*z + d with variable upper bound b*z + d with column var z >= 0
2090  */
2091 
2092  findClosestLb(scip, lpdata, colscurrentrow[c],
2093  &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2094  assert( bestbndtype > -2 && lpdata->bestlbidxofcol[collppos] == bestbndtype);
2095 
2096  if( bestbndtype > -1 )
2097  {
2098  int zlppos;
2099 
2100  zlppos = SCIPcolGetLPPos(SCIPvarGetCol(bestzvbnd));
2101  assert(0 <= zlppos && zlppos < lpdata->ncols);
2102 
2103  if( valscurrentrow[c] > 0 )
2104  densecoeffscurrentrightrow[zlppos] += valscurrentrow[c] * bestbvbnd;
2105  else
2106  densecoeffscurrentleftrow[zlppos] -= valscurrentrow[c] * bestbvbnd;
2107  }
2108 
2109  findClosestUb(scip, lpdata, colscurrentrow[c],
2110  &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2111  assert(bestbndtype > -2 && lpdata->bestubidxofcol[collppos] == bestbndtype);
2112 
2113  if( bestbndtype > -1 )
2114  {
2115  int zlppos;
2116 
2117  zlppos = SCIPcolGetLPPos(SCIPvarGetCol(bestzvbnd));
2118  assert(0 <= zlppos && zlppos < lpdata->ncols);
2119 
2120  if( valscurrentrow[c] > 0 )
2121  densecoeffscurrentleftrow[zlppos] -= valscurrentrow[c] * bestbvbnd;
2122  else
2123  densecoeffscurrentrightrow[zlppos] += valscurrentrow[c] * bestbvbnd;
2124  }
2125  }
2126  else
2127  {
2128  densecoeffscurrentleftrow[collppos] -= valscurrentrow[c];
2129  densecoeffscurrentrightrow[collppos] += valscurrentrow[c];
2130  }
2131  }
2132 
2133  /* calculate scalar that would make (left|right) row coefficients integral;
2134  * try to avoid unnecessary or expensive scaling calls
2135  */
2136  intscalarleftrow = 1.0;
2137  intscalarrightrow = 1.0;
2138 
2139  if( sepadata->scalefraccoeffs && (!SCIPisIntegral(scip, SCIPgetRowMinCoef(scip, row))
2140  || !SCIPisIntegral(scip, SCIPgetRowMaxCoef(scip, row)) || !SCIPisIntegral(scip, SCIProwGetSumNorm(row))) )
2141  {
2142  SCIP_CALL( SCIPcalcIntegralScalar(densecoeffscurrentleftrow, lpdata->ncols,
2143  -SCIPepsilon(scip), SCIPepsilon(scip), (SCIP_Longint) MAXDNOM, MAXSCALE, &intscalarleftrow, &success) );
2144  if( !success )
2145  {
2146  lpdata->rrowsindexofleftrow[r] = NONEXISTENT_ROW;
2147  }
2148 
2149  SCIP_CALL( SCIPcalcIntegralScalar(densecoeffscurrentrightrow, lpdata->ncols,
2150  -SCIPepsilon(scip), SCIPepsilon(scip), (SCIP_Longint) MAXDNOM, MAXSCALE, &intscalarrightrow, &success) );
2151  if( !success )
2152  {
2153  lpdata->rrowsindexofrightrow[r] = NONEXISTENT_ROW;
2154  }
2155 
2156  if ( lpdata->rrowsindexofleftrow[r] == NONEXISTENT_ROW
2157  && lpdata->rrowsindexofrightrow[r] == NONEXISTENT_ROW )
2158  {
2159  lpdata->subproblemsindexofrow[r] = IRRELEVANT;
2160  continue;
2161  }
2162  }
2163 
2164  lpdata->intscalarsleftrow[r] = intscalarleftrow;
2165  lpdata->intscalarsrightrow[r] = intscalarrightrow;
2166 
2167  /* calculate lhs/rhs & slacks */
2168  act = SCIPgetRowLPActivity(scip, row);
2169  lhs = SCIProwGetLhs(row);
2170  rhs = SCIProwGetRhs(row);
2171  cst = SCIProwGetConstant(row);
2172 
2173  lhsisinfinity = SCIPisInfinity(scip, -lhs);
2174  rhsisinfinity = SCIPisInfinity(scip, rhs);
2175 
2176  lhsslack = SCIPisFeasZero(scip, act - lhs) ? 0.0 : act - lhs;
2177  rhsslack = SCIPisFeasZero(scip, rhs - act) ? 0.0 : rhs - act;
2178 
2179  lhs = (lhs - cst) * intscalarleftrow;
2180  rhs = (rhs - cst) * intscalarrightrow;
2181 
2182  lhsisinfinity = lhsisinfinity || SCIPisInfinity(scip, -lhs);
2183  rhsisinfinity = rhsisinfinity || SCIPisInfinity(scip, rhs);
2184 
2185  lhsslack = lhsslack * intscalarleftrow;
2186  rhsslack = rhsslack * intscalarrightrow;
2187 
2188  /* check if the slack value of the row is small enough */
2189  if( (!lhsisinfinity && SCIPisLE(scip, lhsslack, maxslack))
2190  || (!rhsisinfinity && SCIPisLE(scip, rhsslack, maxslack)) )
2191  {
2192  colscurrentrow = SCIProwGetCols(row);
2193  nnonzcurrentrow = SCIProwGetNLPNonz(row);
2194  valscurrentrow = SCIProwGetVals(row);
2195 
2196  lhsiseven = ISEVEN(scip, lhs);
2197  rhsiseven = ISEVEN(scip, rhs);
2198 
2199  rowisrelevant = FALSE;
2200  for( c = 0 ; c < nnonzcurrentrow ; ++c )
2201  {
2202  collppos = SCIPcolGetLPPos(colscurrentrow[c]);
2203  var = SCIPcolGetVar(colscurrentrow[c]);
2204 
2205  /* check if row contains a column with primsol = odd bound and update lhs/rhs parity */
2206  if( lpdata->rcolsindexofcol[collppos] == LP_SOL_EQUALS_ODD_LB
2207  || lpdata->rcolsindexofcol[collppos] == LP_SOL_EQUALS_ODD_UB )
2208  {
2209  assert(SCIPvarGetType(SCIPcolGetVar(colscurrentrow[c])) != SCIP_VARTYPE_CONTINUOUS);
2210  lhsiseven = !lhsiseven;
2211  rhsiseven = !rhsiseven;
2212  }
2213 
2214  /* check if row contains a continuous variable */
2216  {
2217  if( !rhsisinfinity )
2218  {
2219  if( valscurrentrow[c] * intscalarrightrow > 0 )
2220  {
2221  findClosestLb(scip, lpdata, colscurrentrow[c], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2222  assert(bestbndtype > -2 && lpdata->bestlbidxofcol[collppos] == bestbndtype);
2223  }
2224  else
2225  {
2226  assert(valscurrentrow[c] * intscalarrightrow < 0);
2227  findClosestUb(scip, lpdata, colscurrentrow[c], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2228  assert(bestbndtype > -2 && lpdata->bestubidxofcol[collppos] == bestbndtype);
2229  }
2230  assert(bestbndtype == -1 || bestzvbnd != NULL);
2231 
2232  if( SCIPisInfinity(scip, -bestbndsol) || SCIPisInfinity(scip, bestbndsol) )
2233  rhsisinfinity = TRUE;
2234  else
2235  {
2236  /**@todo check whether REALABS is really correct */
2237  if ( bestbndtype == -1 )
2238  rhs -= intscalarrightrow * REALABS(valscurrentrow[c]) * bestbndsol;
2239  else
2240  rhs -= intscalarrightrow * REALABS(valscurrentrow[c]) * bestdvbnd;
2241  rhsslack += intscalarrightrow * REALABS(valscurrentrow[c])
2242  * REALABS(SCIPcolGetPrimsol(colscurrentrow[c]) - bestbndsol);
2243  assert(SCIPisGE(scip, rhsslack, 0.0));
2244  rhsisinfinity = rhsisinfinity || SCIPisInfinity(scip, rhs);
2245  }
2246  }
2247 
2248  if( !lhsisinfinity )
2249  {
2250  if( valscurrentrow[c] * intscalarleftrow < 0 )
2251  {
2252  findClosestLb(scip, lpdata, colscurrentrow[c], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2253  assert(bestbndtype > -2 && lpdata->bestlbidxofcol[collppos] == bestbndtype);
2254  }
2255  else
2256  {
2257  assert(valscurrentrow[c] * intscalarleftrow > 0);
2258  findClosestUb(scip, lpdata, colscurrentrow[c], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2259  assert(bestbndtype > -2 && lpdata->bestubidxofcol[collppos] == bestbndtype);
2260  }
2261  assert(bestbndtype == -1 || bestzvbnd != NULL);
2262 
2263  if( SCIPisInfinity(scip, -bestbndsol) || SCIPisInfinity(scip, bestbndsol) )
2264  lhsisinfinity = TRUE;
2265  else
2266  {
2267  /**@todo check whether REALABS is really correct */
2268  if( bestbndtype == -1 )
2269  lhs -= intscalarleftrow * REALABS(valscurrentrow[c]) * bestbndsol;
2270  else
2271  lhs -= intscalarleftrow * REALABS(valscurrentrow[c]) * bestdvbnd;
2272  lhsslack += intscalarleftrow * REALABS(valscurrentrow[c])
2273  * REALABS(SCIPcolGetPrimsol(colscurrentrow[c]) - bestbndsol);
2274  assert(SCIPisGE(scip, lhsslack, 0.0));
2275  lhsisinfinity = lhsisinfinity || SCIPisInfinity(scip, lhs);
2276  }
2277  }
2278 
2279  /* if both lhs and rhs became infinity, then the (relaxed) row is not relevant */
2280  if( lhsisinfinity && rhsisinfinity )
2281  {
2282  rowisrelevant = FALSE;
2283  break;
2284  }
2285 
2286  rowisrelevant = TRUE;
2287  }
2288 
2289  /* check if row contains at least one relevant column (because k == 0 by initialization) */
2290  if( lpdata->subproblemsindexofcol[collppos] == k )
2291  rowisrelevant = TRUE;
2292 
2293  /* check if row contains no relevant columns but an odd lhs or rhs value */
2294  if( c == nnonzcurrentrow - 1 && (!lhsiseven || !rhsiseven) )
2295  rowisrelevant = TRUE;
2296 
2297  }
2298  assert(SCIPisGE(scip, lhsslack, 0.0));
2299  assert(SCIPisGE(scip, rhsslack, 0.0));
2300 
2301 
2302  /* process row if it is relevant */
2303  if( rowisrelevant )
2304  {
2305  /* row is relevant because it contains a relevant column */
2306  problem->rrows[problem->nrrows] = r;
2307 
2308  lhsslackislessequalmaxslack = SCIPisLE(scip, lhsslack, maxslack);
2309  rhsslackislessequalmaxslack = SCIPisLE(scip, rhsslack, maxslack);
2310 
2311  /* note: due to the relaxation of continuous variables with their bounds the coeffs of nonzero variables
2312  * in left row and right row may be different. hence the row with smaller slack cannot be removed without
2313  * checking the coeffs first.
2314  */
2315  if( !lhsisinfinity && lhsslackislessequalmaxslack )
2316  {
2317  /* "-a^T x <= -lhs" */
2318  lpdata->subproblemsindexofrow[r] = k;
2319  lpdata->rrowsindexofleftrow[r] = problem->nrrows;
2320 
2321  problem->rrows[problem->nrrows] = r;
2322  /**@todo check whether lhs is correct, or whether this must be -lhs. do we store the
2323  * -ax <= -lhs constraint or the ax >= lhs constraint? Is this handled correctly above while updating lhs?
2324  */
2325  problem->rrowsrhs[problem->nrrows] = lhs;
2326  problem->rrowsslack[problem->nrrows] = lhsslack;
2327  }
2328  else
2329  {
2330  lpdata->rrowsindexofleftrow[r] = lhsisinfinity ? NONEXISTENT_ROW : SLACK_GREATER_THAN_MAXSLACK;
2331  }
2332  /**@todo check the following: if !lhsinfinity AND !rhsinfinity: then only one of them is stored currently,
2333  * because problem->nrrows++ is only called once. if this is intended, why do we allocate 2 * lpdata->nrows
2334  * entries for rrows?
2335  */
2336  if( !rhsisinfinity && rhsslackislessequalmaxslack )
2337  {
2338  /* "a^T x <= rhs" */
2339  lpdata->subproblemsindexofrow[r] = k;
2340  lpdata->rrowsindexofrightrow[r] = problem->nrrows;
2341 
2342  problem->rrows[problem->nrrows] = r;
2343  problem->rrowsrhs[problem->nrrows] = rhs;
2344  problem->rrowsslack[problem->nrrows] = rhsslack;
2345  }
2346  else
2347  {
2348  lpdata->rrowsindexofrightrow[r] = rhsisinfinity ? NONEXISTENT_ROW : SLACK_GREATER_THAN_MAXSLACK;
2349  }
2350 
2351  /* increase counter only if at least one half row had a sufficiently small slack */
2352  if( lpdata->rrowsindexofleftrow[r] > -1 || lpdata->rrowsindexofrightrow[r] > -1 )
2353  problem->nrrows++;
2354  }
2355  else /* case: !rowisrelevant */
2356  {
2357  /* row does not contain relevant columns */
2358  lpdata->subproblemsindexofrow[r] = IRRELEVANT;
2359  lpdata->rrowsindexofleftrow[r] = lhsisinfinity ? NONEXISTENT_ROW : NO_RELEVANT_COLUMNS;
2360  lpdata->rrowsindexofrightrow[r] = rhsisinfinity ? NONEXISTENT_ROW : NO_RELEVANT_COLUMNS;
2361  }
2362  }
2363  else /* case: lhsslack > maxslack && rhsslack > maxslack */
2364  {
2365  lpdata->subproblemsindexofrow[r] = IRRELEVANT;
2366  lpdata->rrowsindexofleftrow[r] = lhsisinfinity ? NONEXISTENT_ROW : SLACK_GREATER_THAN_MAXSLACK;
2367  lpdata->rrowsindexofrightrow[r] = rhsisinfinity ? NONEXISTENT_ROW : SLACK_GREATER_THAN_MAXSLACK;
2368  }
2369  }
2370 
2371  /* free temporary memory */
2372  SCIPfreeBufferArray(scip, &densecoeffscurrentleftrow);
2373  SCIPfreeBufferArray(scip, &densecoeffscurrentrightrow);
2374 
2375  return SCIP_OKAY;
2376 }
2377 
2378 
2379 
2380 /* check if mod 2 data structure contains at most two nonzero entries per row */
2381 static
2383  ZEROHALF_MOD2DATA* mod2data /**< considered mod 2 data */
2384  )
2385 {
2386  int r;
2387  int c;
2388  int nentries;
2389 
2390  assert(mod2data != NULL);
2392  if( mod2data->nrowsind == 0 )
2393  return TRUE; /*FALSE;*/
2394 
2395  if( mod2data->ncolsind <= 2 )
2396  return TRUE;
2397 
2398  for( r = 0; r < mod2data->nrowsind ; ++r )
2399  {
2400  nentries = 0;
2401  for( c = 0; c < mod2data->ncolsind ; ++c )
2402  {
2403  if( BITARRAYBITISSET(mod2data->rows[mod2data->rowsind[r]], mod2data->colsind[c]) ) /*lint !e701*/
2404  {
2405  nentries++;
2406  if( nentries > 2 )
2407  return FALSE;
2408  }
2409  }
2410  }
2411 
2412  return TRUE;
2413 }
2414 
2415 
2416 
2417 #ifdef ZEROHALF__PRINT_STATISTICS
2418 /* check if mod 2 data structure contains at most two nonzero entries per column */
2419 static
2420 SCIP_Bool hasMatrixMax2EntriesPerColumn(
2421  ZEROHALF_MOD2DATA* mod2data /**< considered mod 2 data */
2422  )
2423 {
2424  int r;
2425  int c;
2426  int nentries;
2427 
2428  assert(mod2data != NULL);
2429 
2430  if( mod2data->ncolsind == 0 )
2431  return TRUE; /*FALSE;*/
2432 
2433  if( mod2data->nrowsind <= 2 )
2434  return TRUE;
2435 
2436  for( c = 0; c < mod2data->ncolsind ; ++c )
2437  {
2438  nentries = 0;
2439  for( r = 0; r < mod2data->nrowsind ; ++r )
2440  {
2441  if( BITARRAYBITISSET(mod2data->rows[mod2data->rowsind[r]], mod2data->colsind[c]) ) /*lint !e701*/
2442  {
2443  nentries++;
2444  if( nentries > 2 )
2445  return FALSE;
2446  }
2447  }
2448  }
2449 
2450  return TRUE;
2451 }
2452 #endif
2453 
2454 
2455 
2456 /* stores relevant data into bit arrays (mod 2 data structure) */
2457 static
2459  SCIP* scip, /**< SCIP data structure */
2460  SCIP_SEPADATA* sepadata, /**< separator data */
2461  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
2462  int subproblemindex, /**< index of considered subproblem */
2463  ZEROHALF_MOD2DATA* mod2data /**< data (mod 2) */
2464  )
2465 {
2466  ZEROHALF_SUBLPDATA* problem;
2467  SCIP_COL** colscurrentrow;
2468  SCIP_ROW* row;
2469  SCIP_Real* nonzvalscurrentrow;
2470  SCIP_Real maxslack;
2471  SCIP_Real intscalar;
2472  BITARRAY tempcurrentrow;
2473  int* varboundstoadd;
2474  int nnonzcurrentrow;
2475  int rcolsindex;
2476  int c;
2477  int i;
2478  int j;
2479 #ifdef ZEROHALF__PRINT_STATISTICS
2480  int nirrelevantvarbounds;
2481 #endif
2482  SCIP_Bool tempmod2rhs;
2483  SCIP_Bool ignorerow;
2484  SCIP_Bool fliplhsrhs;
2485  SCIP_Bool isrhsrow;
2486  SCIP_Real* densecoeffscurrentrow;
2487 
2488  assert(scip != NULL);
2489  assert(sepadata != NULL);
2490  assert(lpdata != NULL);
2491  assert(lpdata->rows != NULL);
2492  assert(lpdata->nrows > 0);
2493  assert(lpdata->cols != NULL);
2494  assert(lpdata->ncols > 0);
2495  assert(lpdata->subproblems != NULL);
2496  assert(lpdata->nsubproblems > 0);
2497  assert(lpdata->subproblemsindexofrow != NULL);
2498  assert(lpdata->rrowsindexofleftrow != NULL);
2499  assert(lpdata->rrowsindexofrightrow != NULL);
2500  assert(lpdata->subproblemsindexofcol != NULL);
2501  assert(lpdata->rcolsindexofcol != NULL);
2502  assert(0 <= subproblemindex);
2503  assert(subproblemindex <= lpdata->nsubproblems);
2504  problem = lpdata->subproblems[subproblemindex];
2505  assert(problem != NULL);
2506  assert(problem->rrows != NULL);
2507  assert(problem->nrrows > 0);
2508  assert(problem->rrowsrhs != NULL);
2509  assert(problem->rrowsslack != NULL);
2510  assert(problem->rcols != NULL);
2511  assert(problem->nrcols > 0);
2512  assert(problem->rcolslbslack != NULL);
2513  assert(problem->rcolsubslack != NULL);
2514  assert(mod2data != NULL);
2515 
2516  /* identify varbounds to be added to the matrix */
2517  SCIP_CALL(SCIPallocBufferArray(scip, &varboundstoadd, 2 * problem->nrcols)); /* <0: lb, >0: ub */
2518 
2519  maxslack = sepadata->maxslack;
2520 
2521 #ifdef ZEROHALF__PRINT_STATISTICS
2522  nirrelevantvarbounds = 0;
2523 #endif
2524  mod2data->nvarbounds = 0;
2525  for( c = 0 ; c < problem->nrcols ; c++ )
2526  {
2527  SCIP_Bool lbslackisok;
2528  SCIP_Bool ubslackisok;
2529 
2530  lbslackisok = SCIPisLE(scip, problem->rcolslbslack[c], maxslack);
2531  ubslackisok = SCIPisLE(scip, problem->rcolsubslack[c], maxslack);
2532 
2533  if( lbslackisok && ubslackisok )
2534  {
2535  SCIP_Real lb;
2536  SCIP_Real ub;
2537 
2538  lb = SCIPcolGetLb(lpdata->cols[problem->rcols[c]]);
2539  ub = SCIPcolGetUb(lpdata->cols[problem->rcols[c]]);
2540 
2541  if( ISEVEN(scip, lb) != ISEVEN(scip, ub) )
2542  {
2543  varboundstoadd[mod2data->nvarbounds] = (-1) * (c + 1);
2544  mod2data->nvarbounds++;
2545  varboundstoadd[mod2data->nvarbounds] = c + 1;
2546  mod2data->nvarbounds++;
2547  }
2548  else
2549  {
2550  if( SCIPisLE(scip, problem->rcolslbslack[c], problem->rcolsubslack[c]) )
2551  varboundstoadd[mod2data->nvarbounds] = (-1) * (c + 1);
2552  else
2553  varboundstoadd[mod2data->nvarbounds] = c + 1;
2554  mod2data->nvarbounds++;
2555 #ifdef ZEROHALF__PRINT_STATISTICS
2556  nirrelevantvarbounds++;
2557 #endif
2558  }
2559  }
2560  else
2561  {
2562  if( lbslackisok )
2563  {
2564  varboundstoadd[mod2data->nvarbounds] = (-1) * (c + 1);
2565  mod2data->nvarbounds++;
2566  }
2567 #ifdef ZEROHALF__PRINT_STATISTICS
2568  else
2569  nirrelevantvarbounds++;
2570 #endif
2571  if( ubslackisok )
2572  {
2573  varboundstoadd[mod2data->nvarbounds] = c + 1;
2574  mod2data->nvarbounds++;
2575  }
2576 #ifdef ZEROHALF__PRINT_STATISTICS
2577  else
2578  nirrelevantvarbounds++;
2579 #endif
2580  }
2581  }
2582  mod2data->nrows = problem->nrrows + mod2data->nvarbounds;
2583 
2584  /* allocate temporary memory */
2585  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rows), mod2data->nrows) );
2586  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rowaggregations), mod2data->nrows) );
2587  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rhs), mod2data->nrows) );
2588  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->slacks), mod2data->nrows) );
2589  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->fracsol), problem->nrcols) );
2590  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rowstatistics), mod2data->nrows) );
2591  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->colstatistics), problem->nrcols) );
2592  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rowsind), mod2data->nrows) );
2593  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->colsind), problem->nrcols) );
2594  SCIP_CALL( SCIPallocBufferArray(scip, &densecoeffscurrentrow, lpdata->ncols) );
2595 
2596  /* initialize temporary memory */
2597  mod2data->relatedsubproblem = problem;
2598  BMSclearMemoryArray(mod2data->rows, mod2data->nrows); /* NULL = 0x0 */
2599  BMSclearMemoryArray(mod2data->rowaggregations, mod2data->nrows); /* NULL = 0x0 */
2600  BMScopyMemoryArray(mod2data->slacks, problem->rrowsslack, problem->nrrows);
2601  for( c = 0 ; c < problem->nrcols ; ++c)
2602  mod2data->fracsol[c] = SCIPcolGetPrimsol(lpdata->cols[problem->rcols[c]]);
2603  for( c = 0 ; c < problem->nrcols ; c++)
2604  mod2data->colsind[c] = c;
2605  mod2data->nrowsind = 0;
2606  mod2data->ncolsind = problem->nrcols;
2607  mod2data->rowsbitarraysize = (int) GETREQUIREDBITARRAYSIZE(problem->nrcols);
2608  mod2data->rowaggregationsbitarraysize = (int) GETREQUIREDBITARRAYSIZE(problem->nrrows);
2609  tempcurrentrow = NULL;
2610 
2611  /* (i) for all relevant rows */
2612  for( i = 0 ; i < problem->nrrows ; ++i )
2613  {
2614  row = lpdata->rows[problem->rrows[i]];
2615  colscurrentrow = SCIProwGetCols(row);
2616  nonzvalscurrentrow = SCIProwGetVals(row);
2617  nnonzcurrentrow = SCIProwGetNLPNonz(row);
2618  assert(nnonzcurrentrow > 0);
2619  tempcurrentrow = NULL;
2620  fliplhsrhs = FALSE;
2621  ignorerow = FALSE;
2622 
2623  /* check if rrows corresponds to a lhs or rhs row in the LP */
2624  if( lpdata->rrowsindexofleftrow[problem->rrows[i]] == i )
2625  isrhsrow = FALSE;
2626  else
2627  {
2628  assert(lpdata->rrowsindexofrightrow[problem->rrows[i]] == i);
2629  isrhsrow = TRUE;
2630  }
2631  intscalar = isrhsrow ? lpdata->intscalarsrightrow[problem->rrows[i]]
2632  : lpdata->intscalarsleftrow[problem->rrows[i]];
2633 
2634  /* clear dense coeffs array */
2635  BMSclearMemoryArray(densecoeffscurrentrow, lpdata->ncols);
2636 
2637  /* compute dense coeffs array of current row (including intscaling and bound substitutions) */
2638  for( j = 0 ; j < nnonzcurrentrow; ++j )
2639  {
2640  if( SCIPvarGetType(SCIPcolGetVar(colscurrentrow[j])) == SCIP_VARTYPE_CONTINUOUS )
2641  {
2642  SCIP_Bool ispositivecoeff;
2643  SCIP_VAR* bestzvbnd;
2644  SCIP_Real bestbndsol;
2645  SCIP_Real bestbvbnd;
2646  SCIP_Real bestdvbnd;
2647  int bestbndtype;
2648 
2649  /* check sign of coefficient */
2650  if( nonzvalscurrentrow[j] * intscalar > 0.0 )
2651  ispositivecoeff = TRUE;
2652  else
2653  ispositivecoeff = FALSE;
2654 
2655  /* get appropriate bound */
2656  if( isrhsrow == ispositivecoeff )
2657  findClosestLb(scip, lpdata, colscurrentrow[j], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2658  else
2659  findClosestUb(scip, lpdata, colscurrentrow[j], &bestbndsol, &bestbndtype, &bestzvbnd, &bestbvbnd, &bestdvbnd );
2660 
2661  /* check bound type */
2662  assert(bestbndtype > -2);
2663  if( !USEVARBOUNDS ) /*lint !e774 !e506*/
2664  assert(bestbndtype == -1);
2665 
2666  /* normal lb or ub is used; only rhs would have to be adjusted but this has already been done in getRelevantRows */
2667  if( bestbndtype == -1 )
2668  continue;
2669  assert(USEVARBOUNDS && bestbndtype > -1); /*lint !e774 !e506*/
2670 
2671  /* variable bound is used: update coefficient of non-continuous variable z that is used in substitution */
2672  densecoeffscurrentrow[SCIPcolGetLPPos(SCIPvarGetCol(bestzvbnd))] += (nonzvalscurrentrow[j] * intscalar * bestbvbnd);
2673  }
2674  else
2675  {
2676  densecoeffscurrentrow[SCIPcolGetLPPos(colscurrentrow[j])] += (nonzvalscurrentrow[j] * intscalar);
2677  }
2678  }
2679 
2680  for( j = 0 ; j < lpdata->ncols; ++j )
2681  {
2682  assert(SCIPcolGetLPPos(lpdata->cols[j]) == j);
2683 
2684  if( SCIPisZero(scip, densecoeffscurrentrow[j]) )
2685  continue;
2686 
2687  if( intscalar == 1.0 && !SCIPisIntegral(scip, densecoeffscurrentrow[j]) )
2688  {
2689  ignorerow = TRUE;
2690  break;
2691  }
2692  else
2693  assert(sepadata->scalefraccoeffs);
2694 
2695  /* integral coefficient */
2696  /* coefficient is only integral with respect to tolerances; use really integral values */
2697  if( isrhsrow )
2698  densecoeffscurrentrow[j] = SCIPfloor(scip, densecoeffscurrentrow[j]);
2699  else
2700  densecoeffscurrentrow[j] = SCIPceil(scip, densecoeffscurrentrow[j]);
2701 
2702  if( ISODD(scip, densecoeffscurrentrow[j]) )
2703  {
2704  rcolsindex = lpdata->rcolsindexofcol[j];
2705  fliplhsrhs = XOR((int) fliplhsrhs,
2706  (int) (rcolsindex == LP_SOL_EQUALS_ODD_LB || rcolsindex == LP_SOL_EQUALS_ODD_UB));
2707  if( rcolsindex >= 0 ) /* relevant column? */
2708  {
2709  if( tempcurrentrow == NULL )
2710  {
2711  SCIP_CALL( SCIPallocMemoryArray(scip, &tempcurrentrow, mod2data->rowsbitarraysize) );
2712  BITARRAYCLEAR(tempcurrentrow, mod2data->rowsbitarraysize);
2713  }
2714  assert(rcolsindex < problem->nrcols);
2715  BITARRAYBITSET(tempcurrentrow, rcolsindex); /*lint !e701*/
2716  assert(BITARRAYBITISSET(tempcurrentrow, rcolsindex)); /*lint !e701*/
2717  }
2718  }
2719  }
2720 
2721  /* check if current row should be ignored, continuing with the next one */
2722  if( ignorerow )
2723  {
2724  if( tempcurrentrow != NULL )
2725  {
2726  SCIPfreeMemoryArray(scip, &tempcurrentrow);
2727  tempcurrentrow = NULL;
2728  }
2729  continue;
2730  }
2731 
2732  /* consider rhs */
2733  if( XOR((int) ISODD(scip, problem->rrowsrhs[i]), (int) fliplhsrhs) )
2734  tempmod2rhs = TRUE;
2735  else
2736  tempmod2rhs = FALSE;
2737 
2738  if( tempcurrentrow == NULL && tempmod2rhs )
2739  {
2740  SCIP_CALL( SCIPallocMemoryArray(scip, &tempcurrentrow, mod2data->rowsbitarraysize) );
2741  BITARRAYCLEAR(tempcurrentrow, mod2data->rowsbitarraysize);
2742  }
2743  assert(tempcurrentrow != NULL || !tempmod2rhs);
2744 
2745  /* store temporary data in appropriate (mod 2) data structures */
2746  if( tempcurrentrow != NULL )
2747  {
2748  mod2data->rows[i] = tempcurrentrow;
2749  mod2data->rhs[i] = tempmod2rhs;
2750 
2751  assert(mod2data->rowaggregationsbitarraysize > 0);
2752  SCIP_CALL( SCIPallocMemoryArray(scip, &(mod2data->rowaggregations[i]),
2753  mod2data->rowaggregationsbitarraysize) ); /*lint !e866*/
2754  BITARRAYCLEAR(mod2data->rowaggregations[i], mod2data->rowaggregationsbitarraysize); /*lint !e866*/
2755  BITARRAYBITSET(mod2data->rowaggregations[i], i); /*lint !e701*/
2756 
2757  mod2data->rowsind[mod2data->nrowsind] = i;
2758  mod2data->nrowsind++;
2759 
2760  tempcurrentrow = NULL;
2761  }
2762  else
2763  {
2764  /* zero row */
2765  lpdata->subproblemsindexofrow[problem->rrows[i]] = IRRELEVANT;
2766  if( lpdata->rrowsindexofleftrow[problem->rrows[i]] >= 0 )
2767  lpdata->rrowsindexofleftrow[problem->rrows[i]] = ZERO_ROW;
2768  if( lpdata->rrowsindexofrightrow[problem->rrows[i]] >= 0 )
2769  lpdata->rrowsindexofrightrow[problem->rrows[i]] = ZERO_ROW;
2770  }
2771  }
2772 
2773 
2774  /* (ii) for all relevant varbounds */
2775  i = problem->nrrows;
2776  for( j = 0 ; j < mod2data->nvarbounds ; ++j)
2777  {
2778  SCIP_Real bound;
2779 
2780  if( varboundstoadd[j] < 0 )
2781  c = (-1) * varboundstoadd[j] - 1;
2782  else
2783  c = varboundstoadd[j] - 1;
2784 
2785  assert(mod2data->rowsbitarraysize > 0);
2786  SCIP_CALL(SCIPallocMemoryArray(scip, &(mod2data->rows[i]), mod2data->rowsbitarraysize)); /*lint !e866*/
2787  BITARRAYCLEAR(mod2data->rows[i], mod2data->rowsbitarraysize); /*lint !e866*/
2788  BITARRAYBITSET(mod2data->rows[i], c); /*lint !e701*/
2789  assert(BITARRAYBITISSET(mod2data->rows[i], c)); /*lint !e701*/
2790 
2791  SCIP_CALL(SCIPallocMemoryArray(scip, &(mod2data->rowaggregations[i]),
2792  mod2data->rowaggregationsbitarraysize)); /*lint !e866*/
2793  BITARRAYCLEAR(mod2data->rowaggregations[i], mod2data->rowaggregationsbitarraysize); /*lint !e866*/
2794 
2795  if( varboundstoadd[j] < 0 )
2796  {
2797  bound = SCIPcolGetLb(lpdata->cols[problem->rcols[c]]);
2798  mod2data->rhs[i] = ISODD(scip, bound);
2799  mod2data->slacks[i] = problem->rcolslbslack[c];
2800  }
2801  else
2802  {
2803  bound = SCIPcolGetUb(lpdata->cols[problem->rcols[c]]);
2804  mod2data->rhs[i] = ISODD(scip, bound);
2805  mod2data->slacks[i] = problem->rcolsubslack[c];
2806  }
2807  if( SCIPisFeasZero(scip, mod2data->slacks[i]) )
2808  mod2data->slacks[i] = 0.0;
2809 
2810  mod2data->rowsind[mod2data->nrowsind] = i;
2811  mod2data->nrowsind++;
2812  i++;
2813  }
2814 
2815  /* free temporary memory */
2816  SCIPfreeBufferArray(scip, &densecoeffscurrentrow);
2817  SCIPfreeBufferArray(scip, &varboundstoadd);
2818 
2819 #ifdef ZEROHALF__PRINT_STATISTICS
2820  ZEROHALFstatisticsMessage("\n");
2821  ZEROHALFstatisticsMessage(" | ------------------------------- subproblem ------------------------------- | ------------------------------\n");
2822  ZEROHALFstatisticsMessage(" | nrrows | nrcols | nvarbnds | ndlvbnds | max2/row | max2/col | A^T ept | \n");
2823  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8s | %8s | %8s |\n",
2824  "SUBPROBLEMDATA", problem->nrrows, problem->nrcols, mod2data->nvarbounds, nirrelevantvarbounds,
2825  hasMatrixMax2EntriesPerRow(mod2data) ? "yes" : "no", hasMatrixMax2EntriesPerColumn(mod2data) ? "yes" : "no", "n/a");
2826 #endif
2827 
2828  return SCIP_OKAY;
2829 }
2830 
2831 
2832 /* --------------------------------------------------------------------------------------------------------------------
2833  * local methods: cut generation
2834  * -------------------------------------------------------------------------------------------------------------------- */
2835 
2836 
2837 /** stores nonzero elements of dense coefficient vector as sparse vector, and calculates activity and norm */
2838 static
2840  SCIP* scip, /**< SCIP data structure */
2841  int nvars, /**< number of problem variables */
2842  SCIP_VAR** vars, /**< problem variables */
2843  SCIP_Real* cutcoefs, /**< dense coefficient vector */
2844  SCIP_Real* varsolvals, /**< dense variable LP solution vector */
2845  char normtype, /**< type of norm to use for efficacy norm calculation */
2846 
2847  SCIP_VAR** cutvars, /**< array to store variables of sparse cut vector */
2848  SCIP_Real* cutvals, /**< array to store coefficients of sparse cut vector */
2849  int* cutlen, /**< pointer to store number of nonzero entries in cut */
2850  SCIP_Real* cutact, /**< pointer to store activity of cut */
2851  SCIP_Real* cutnorm /**< pointer to store norm of cut vector */
2852  )
2853 {
2854  SCIP_Real val;
2855  SCIP_Real absval;
2856  SCIP_Real cutsqrnorm;
2857  SCIP_Real act;
2858  SCIP_Real norm;
2859  int len;
2860  int v;
2861 
2862  assert(nvars == 0 || cutcoefs != NULL);
2863  assert(nvars == 0 || varsolvals != NULL);
2864  assert(cutvars != NULL);
2865  assert(cutvals != NULL);
2866  assert(cutlen != NULL);
2867  assert(cutact != NULL);
2868  assert(cutnorm != NULL);
2869 
2870  len = 0;
2871  act = 0.0;
2872  norm = 0.0;
2873  switch(normtype)
2874  {
2875  case 'e':
2876  cutsqrnorm = 0.0;
2877  for( v = 0; v < nvars; ++v)
2878  {
2879  val = cutcoefs[v];
2880  if( !SCIPisZero(scip, val) )
2881  {
2882  act += val * varsolvals[v];
2883  cutsqrnorm += SQR(val);
2884  cutvars[len] = vars[v];
2885  cutvals[len] = val;
2886  len++;
2887  }
2888  }
2889  norm = SQRT(cutsqrnorm);
2890  break;
2891  case 'm':
2892  for( v = 0; v < nvars; ++v)
2893  {
2894  val = cutcoefs[v];
2895  if( !SCIPisZero(scip, val) )
2896  {
2897  act += val * varsolvals[v];
2898  absval = REALABS(val);
2899  norm = MAX(norm, absval);
2900  cutvars[len] = vars[v];
2901  cutvals[len] = val;
2902  len++;
2903  }
2904  }
2905  break;
2906  case 's':
2907  for( v = 0; v < nvars; ++v)
2908  {
2909  val = cutcoefs[v];
2910  if( !SCIPisZero(scip, val) )
2911  {
2912  act += val * varsolvals[v];
2913  norm += REALABS(val);
2914  cutvars[len] = vars[v];
2915  cutvals[len] = val;
2916  len++;
2917  }
2918  }
2919  break;
2920  case 'd':
2921  for( v = 0; v < nvars; ++v)
2922  {
2923  val = cutcoefs[v];
2924  if( !SCIPisZero(scip, val) )
2925  {
2926  act += val * varsolvals[v];
2927  norm = 1.0;
2928  cutvars[len] = vars[v];
2929  cutvals[len] = val;
2930  len++;
2931  }
2932  }
2933  break;
2934  default:
2935  SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", normtype);
2936  return SCIP_INVALIDDATA;
2937  }
2938 
2939  *cutlen = len;
2940  *cutact = act;
2941  *cutnorm = norm;
2942 
2943  return SCIP_OKAY;
2944 }
2945 
2946 
2947 
2948 /** adds a separated zerohalf cut to SCIP if it was successfully created and is efficacious */
2949 static
2951  SCIP* scip, /**< SCIP data structure */
2952  SCIP_SEPADATA* sepadata, /**< separator data */
2953  ZEROHALF_CUTDATA* cutdata, /**< separated zerohalf cut */
2954  int* nsepacuts, /**< pointer to store number of separated (efficacious) zerohalf cuts */
2955  SCIP_RESULT* result /**< pointer to store return code */
2956  )
2957 {
2958  assert(scip != NULL);
2959  assert(sepadata != NULL);
2960  assert(cutdata != NULL);
2961  assert(result != NULL);
2962 
2963  /* check if SCIPcalcMIR was not successful */
2964  if( !cutdata->isfeasviolated || !cutdata->success )
2965  return SCIP_OKAY;
2966 
2967  /* check if norm was not calculated correctly */
2968  if( !SCIPisPositive(scip, cutdata->norm) )
2969  {
2970  SCIPerrorMessage("Zerohalf cut norm is NOT positive!\n");
2971  return SCIP_ERROR;
2972  }
2973 
2974  /* check if cut is not efficacious */
2975  if( !sepadata->forcecutstolp && !sepadata->forcecutstosepastore
2976  && !SCIPisEfficacious(scip, cutdata->efficacy) )
2977  {
2978  return SCIP_OKAY;
2979  }
2980 
2981  /* add cut (if no cutpool is used otherwise add it at the end of the separation main method)*/
2982  if( !sepadata->usezhcutpool )
2983  {
2984  SCIP_Bool cutoff;
2985  SCIP_CALL(SCIPaddCut(scip, NULL, cutdata->cut, sepadata->forcecutstolp, &cutoff) );
2986  if ( cutoff )
2987  {
2988  *result = SCIP_CUTOFF;
2989  return SCIP_OKAY;
2990  }
2991  if( !cutdata->islocal )
2992  {
2993  SCIP_CALL(SCIPaddPoolCut(scip, cutdata->cut));
2994  }
2995  }
2996 
2997  cutdata->addedtolp = TRUE;
2998  (*nsepacuts)++;
2999 
3000  *result = SCIP_SEPARATED;
3001 
3002  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, cutdata->cut, NULL) ) );
3003 
3004  return SCIP_OKAY;
3005 }
3006 
3007 
3008 /* --------------------------------------------------------------------------------------------------------------------
3009  * local methods: preprocessing
3010  * -------------------------------------------------------------------------------------------------------------------- */
3011 
3012 
3013 
3014 /** marks a row as "removed" and stores why it has been removed using a flag */
3015 static
3016 void markRowAsRemoved(
3017  ZEROHALF_MOD2DATA* mod2data, /**< considered mod 2 data */
3018  int r, /**< mod2data->rows index of row that shall be removed */
3019  int flag /**< flag (cause of removal) */
3020  )
3021 {
3022  assert(mod2data != NULL);
3023  assert(mod2data->relatedsubproblem != NULL);
3024  assert(mod2data->nrowsind > 0);
3025  assert(r >= 0);
3026  assert(r < mod2data->nrowsind);
3027 
3028  mod2data->rowstatistics[mod2data->rowsind[r]] = flag;
3029 }
3030 
3031 
3032 
3033 /** marks a row as "removed" and stores why it has been removed using a flag. in addition it clears this column's mod 2 data */
3034 static
3036  ZEROHALF_MOD2DATA* mod2data, /**< considered mod 2 data */
3037  int c, /**< mod2data->relatedsubproblem->rcols index of column that shall be removed */
3038  int flag /**< flag (cause of removal) */
3039  )
3040 {
3041  int i;
3042  int rowsbind;
3043  BITARRAYBITMASKTYPE rowsbmask;
3045  assert(mod2data != NULL);
3046  assert(mod2data->relatedsubproblem != NULL);
3047  assert(mod2data->ncolsind > 0);
3048  assert(c >= 0);
3049  assert(c < mod2data->ncolsind);
3050 
3051 
3052  /* mark col */
3053  mod2data->colstatistics[mod2data->colsind[c]] = flag;
3054 
3055  /* clear col */
3056  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[c]);
3057  rowsbmask = ~GETBITARRAYMASK(mod2data->colsind[c]); /*lint !e701*/
3058  for( i = 0 ; i < mod2data->nrowsind ; ++i)
3059  mod2data->rows[mod2data->rowsind[i]][rowsbind] &= rowsbmask;
3060 }
3061 
3062 
3063 
3064 
3065 /** given a subset of mod 2 rows it returns a {0,1/2} weight vector used to
3066  combine the (original) LP rows. Note: original rows a stored as lhs <= a^Tx
3067  <= rhs by SCIP. Positive weights refer to "right half-rows" a^Tx <= rhs and
3068  negative weights to "left half-rows" -a^Tx <= -lhs */
3069 static
3071  SCIP* scip, /**< SCIP data structure */
3072  SCIP_SEPADATA* sepadata, /**< separator data */
3073  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3074  ZEROHALF_MOD2DATA* mod2data, /**< considered mod 2 data */
3075  BITARRAY rrowsincut, /**< subset of selected mod2data->rows */
3076  SCIP_Real** weights, /**< pointer to store the {-0.5,0,0.5} weights vector */
3077  int* nrowsincut /**< pointer to store the number of combined original LP rows */
3078  )
3079 { /*lint --e{438}*/
3080 
3081  ZEROHALF_SUBLPDATA* problem;
3082  int lppos;
3083  int i;
3084  int nnonz;
3085 
3086  assert(scip != NULL);
3087  assert(lpdata != NULL);
3088  assert(lpdata->nrows > 0);
3089  assert(mod2data != NULL);
3090  assert(mod2data->relatedsubproblem != NULL);
3091  assert(mod2data->nrowsind > 0);
3092  assert(rrowsincut != NULL);
3093  assert(weights != NULL);
3094  assert(*weights == NULL);
3095  assert(nrowsincut != NULL);
3096 
3097 
3098  /* allocate temporary memory */
3099  SCIP_CALL(SCIPallocMemoryArray(scip, weights, lpdata->nrows));
3100 
3101  /* initialize */
3102  BMSclearMemoryArray(*weights, lpdata->nrows);
3103  problem = mod2data->relatedsubproblem;
3104 
3105  /* determine row weights */
3106  *nrowsincut = 0;
3107  nnonz = 0;
3108  for( i = 0 ; i < problem->nrrows ; ++i)
3109  {
3110  lppos = problem->rrows[i];
3111  assert(0 <= lppos && lppos <= lpdata->nrows);
3112  if( BITARRAYBITISSET(rrowsincut, i) ) /*lint !e701*/
3113  {
3114  assert(lpdata->rrowsindexofleftrow[lppos] == i || lpdata->rrowsindexofrightrow[lppos] == i);
3115 
3116  SCIPdebugMessage(" %1s0.5 (int scaling: %16.4f / %16.4f) row[%d] %s\n",
3117  lpdata->rrowsindexofleftrow[lppos] == i ? "-" : "+",
3118  lpdata->intscalarsleftrow[lppos], lpdata->intscalarsrightrow[lppos],
3119  lppos, SCIProwGetName(lpdata->rows[lppos]));
3120 
3121  if( lpdata->rrowsindexofleftrow[lppos] == i )
3122  (*weights)[lppos] = lpdata->intscalarsleftrow[lppos] * (-0.5);
3123  else
3124  (*weights)[lppos] = lpdata->intscalarsrightrow[lppos] * 0.5;
3125 
3126  nnonz += SCIProwGetNLPNonz(lpdata->rows[lppos]);
3127  (*nrowsincut)++;
3128  }
3129  }
3130 
3131  /* check if row aggregation might be too dense */
3132  if( nnonz >= 5 * sepadata->maxnnonz )
3133  {
3134  SCIPfreeMemoryArray(scip, weights);
3135  weights = NULL;/*lint !e438*/
3136  }
3137 
3138  return SCIP_OKAY;
3139 }
3140 
3141 
3142 /** creates a zerohalf cut from a given weightvector */
3143 static
3145  SCIP* scip, /**< SCIP data structure */
3146  SCIP_SEPA* sepa, /**< separator */
3147  SCIP_SEPADATA* sepadata, /**< separator data */
3148  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3149  SCIP_Real* weights, /**< weightvector */
3150  char normtype, /**< SCIP normtype */
3151  int nzerohalfcuts, /**< number of zerohalf cuts (used for naming the cut) */
3152  SCIP_Real** varsolvals, /**< pointer to array of LP solution values of variables */
3153  ZEROHALF_CUTDATA* cutdata, /**< pointer to data structure used for storing the cut */
3154  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
3155  )
3156 {
3157  SCIP_Real* cutcoefs;
3158  SCIP_VAR** cutvars;
3159  SCIP_Real* cutvals;
3160  char cutname[SCIP_MAXSTRLEN];
3161 
3162  assert(scip != NULL);
3163  assert(lpdata != NULL);
3164  assert(lpdata->nvars > 0);
3165  assert(weights != NULL);
3166  assert(varsolvals != NULL);
3167  assert(cutdata != NULL);
3168  assert(cutdata->relatedsubproblem != NULL);
3169  assert(cutoff != NULL);
3170 
3171  *cutoff = FALSE;
3172 
3173  /* note: cutdata->relatedmod2data can be NULL if cut was determined
3174  * before mod 2 data structures were created */
3175 
3176  /* allocate temporary memory */
3177  SCIP_CALL(SCIPallocBufferArray(scip, &cutcoefs, lpdata->nvars));
3178 
3179  /* calculate MIR */
3180  cutdata->success = FALSE;
3181  if( sepadata->maxtestdelta == 0 )
3182  {
3183  /* generate cut for delta = 1.0 */
3186  weights, -1.0, NULL, -1, -1, NULL, 1.0, NULL, NULL, cutcoefs, &(cutdata->rhs), &(cutdata->activity),
3187  &(cutdata->success), &(cutdata->islocal), &(cutdata->cutrank)) );
3188 
3189  if( sepadata->trynegscaling )
3190  {
3193  weights, -1.0, NULL, -1, -1, NULL, -1.0, NULL, NULL, cutcoefs, &(cutdata->rhs), &(cutdata->activity),
3194  &(cutdata->success), &(cutdata->islocal), &(cutdata->cutrank)) );
3195  }
3196  }
3197  else
3198  {
3199  int ncuts;
3200  SCIP_Real bestdelta;
3201  SCIP_Bool bestdeltavalid;
3202 
3203  ncuts = 0;
3204 
3205  if( *varsolvals == NULL )
3206  {
3207  /* get the solution values for all active variables */
3208  SCIP_CALL(SCIPallocMemoryArray(scip, varsolvals, lpdata->nvars));
3209  SCIP_CALL( SCIPgetSolVals(scip, NULL, lpdata->nvars, lpdata->vars, *varsolvals) );
3210 
3211 #ifndef NDEBUG
3212  /* because later when calling SCIPcutGenerationHeuristicCmir() varsolvals are used, it is needed that the
3213  * corresponding variables have the same order here and there, so we do the same checking and test that all
3214  * variables are ordered by their problem index
3215  */
3216  {
3217  int i;
3218  for(i = lpdata->nvars - 1; i >= 0; --i )
3219  assert(i == SCIPvarGetProbindex(lpdata->vars[i]));
3220  }
3221 #endif
3222  }
3223  assert(*varsolvals != NULL);
3224 
3225  /* find best value of delta */
3226  SCIP_CALL( SCIPcutGenerationHeuristicCmir(scip, sepa, NULL, *varsolvals, sepadata->maxtestdelta, weights,
3227  -1.0, NULL, -1, -1, BOUNDSWITCH, USEVBDS, ALLOWLOCAL, FIXINTEGRALRHS, sepadata->maxnnonz, MAXWEIGHTRANGE,
3228  MINFRAC, MAXFRAC, sepadata->trynegscaling, TRUE, "zerohalf", cutoff, &ncuts, &bestdelta, &bestdeltavalid) );
3229  assert(ncuts == 0);
3230 
3231  /* best delta corresponds to an efficient cut */
3232  if( !(*cutoff) && bestdeltavalid )
3233  {
3236  weights, -1.0, NULL, -1, -1, NULL, bestdelta, NULL, NULL, cutcoefs, &(cutdata->rhs), &(cutdata->activity),
3237  &(cutdata->success), &(cutdata->islocal), &(cutdata->cutrank)) );
3238  }
3239  }
3240  assert(ALLOWLOCAL || !cutdata->islocal);
3241 
3242  cutdata->violation = cutdata->activity - cutdata->rhs;
3243 
3244  /* if successful, convert dense cut into sparse row */
3245  if( !(*cutoff) && cutdata->success )
3246  {
3247  cutdata->isfeasviolated = SCIPisFeasGT(scip, cutdata->activity, cutdata->rhs);
3248  SCIPdebugMessage("Cut is %sfeasviolated: (act: %e, rhs: %e, viol: %e)\n",
3249  cutdata->isfeasviolated ? "" : "not ", cutdata->activity, cutdata->rhs, cutdata->violation);
3250 
3251  if( cutdata->isfeasviolated )
3252  {
3253  if( *varsolvals == NULL )
3254  {
3255  /* get the solution values for all active variables */
3256  SCIP_CALL(SCIPallocMemoryArray(scip, varsolvals, lpdata->nvars));
3257  SCIP_CALL( SCIPgetSolVals(scip, NULL, lpdata->nvars, lpdata->vars, *varsolvals) );
3258  }
3259  assert(*varsolvals != NULL);
3260 
3261  /* get temporary memory for storing the cut as sparse row */
3262  SCIP_CALL(SCIPallocBufferArray(scip, &cutvars, lpdata->nvars));
3263  SCIP_CALL(SCIPallocBufferArray(scip, &cutvals, lpdata->nvars));
3264 
3265  /* store the cut as sparse row, calculate activity and norm of cut */
3266  SCIP_CALL(storeCutInArrays(scip, lpdata->nvars, lpdata->vars,
3267  cutcoefs, *varsolvals, normtype, cutvars, cutvals,
3268  &(cutdata->nnonz), &(cutdata->activity), &(cutdata->norm)));
3269 
3270  /* check cut norm and efficacy */
3271  if( SCIPisPositive(scip, cutdata->norm) )
3272  {
3273  cutdata->efficacy = (cutdata->activity - cutdata->rhs) / cutdata->norm;
3274 
3275  if( sepadata->forcecutstolp || sepadata->forcecutstosepastore
3276  || (SCIPisEfficacious(scip, cutdata->efficacy) && cutdata->nnonz < sepadata->maxnnonz) )
3277  {
3278  /* create cut */
3279  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN,"zerohalf%d_%d", SCIPgetNLPs(scip), nzerohalfcuts);
3280  SCIP_CALL(SCIPcreateEmptyRowSepa(scip, &(cutdata->cut), sepa, cutname, -SCIPinfinity(scip), cutdata->rhs,
3281  cutdata->islocal, FALSE, sepadata->dynamiccuts));
3282  SCIP_CALL(SCIPaddVarsToRow(scip, cutdata->cut, cutdata->nnonz, cutvars, cutvals));
3283  /* set cut rank */
3284  SCIProwChgRank(cutdata->cut, cutdata->cutrank);
3285  }
3286  else
3287  cutdata->success = FALSE;
3288  }
3289  else
3290  cutdata->success = FALSE;
3291 
3292  /* free temporary memory */
3293  SCIPfreeBufferArray(scip, &cutvals);
3294  SCIPfreeBufferArray(scip, &cutvars);
3295  }
3296  else
3297  cutdata->success = FALSE;
3298  }
3299 
3300  /* free temporary memory */
3301  SCIPfreeBufferArray(scip, &cutcoefs);
3302 
3303  return SCIP_OKAY;
3304 }
3305 
3306 
3307 /** searches for trivial zerohalf cuts, given as (0,..0) row with rhs=1 and slack <= maxslack */
3308 static
3310  SCIP* scip, /**< SCIP data structure */
3311  SCIP_SEPA* sepa, /**< separator */
3312  SCIP_SEPADATA* sepadata, /**< separator data */
3313  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3314  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
3315  int firstrowsind, /**< first mod2data->rows index to be considered */
3316  int lastrowsind, /**< last mod2data->rows index to be considered */
3317  char normtype, /**< SCIP normtype */
3318  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
3319  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
3320  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
3321  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
3322  ZEROHALF_CUTDATA** zerohalfcuts, /**< pointer to store a found zerohalf cut */
3323  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
3324  CUTSEPARATEDBY cutseparatedby, /**< flag */
3325  SCIP_RESULT* result /**< pointer to SCIP result value of separation */
3326  )
3327 {
3328  int r;
3329  int r2;
3330  int nrowsremoved;
3331  SCIP_Real maxslack;
3332  BITARRAY zerorow;
3333  SCIP_Bool* removerow;
3334  SCIP_Real* weights;
3335  int nrowsincut;
3336  SCIP_Bool cutoff = FALSE;
3337 
3338  assert(scip != NULL);
3339  assert(lpdata != NULL);
3340  assert(mod2data != NULL);
3341  assert(mod2data->relatedsubproblem != NULL);
3342  assert(firstrowsind >= 0);
3343  assert(lastrowsind <= mod2data->nrowsind);
3344  assert(nsepacuts != NULL);
3345  assert(nzerohalfcuts != NULL);
3346  assert(zerohalfcuts != NULL);
3347  assert(*nsepacuts <= *nzerohalfcuts);
3348  assert(varsolvals != NULL);
3349  assert(result != NULL);
3350 
3351 
3352  /* check if matrix or colind range is empty */
3353  if( mod2data->nrowsind == 0 || lastrowsind - firstrowsind <= 0 )
3354  return SCIP_OKAY;
3355 
3356 
3357  /* allocate temporary memory */
3358  SCIP_CALL(SCIPallocBufferArray(scip, &removerow, lastrowsind - firstrowsind));
3359  SCIP_CALL(SCIPallocBufferArray(scip, &zerorow, mod2data->rowsbitarraysize));
3360 
3361  /* initialize */
3362  BMSclearMemoryArray(zerorow, mod2data->rowsbitarraysize);
3363  BMSclearMemoryArray(removerow, lastrowsind - firstrowsind);
3364  maxslack = sepadata->maxslack;
3365  nrowsremoved = 0;
3366 
3367 
3368  /* check all rows */
3369  for( r = 0 ; r < lastrowsind - firstrowsind && *nsepacuts < maxsepacuts && *nzerohalfcuts < maxcuts; ++r )
3370  {
3371  if( mod2data->rhs[mod2data->rowsind[firstrowsind + r]] == TRUE )
3372  {
3373  if( SCIPisLE(scip, mod2data->slacks[mod2data->rowsind[firstrowsind + r]], maxslack ))
3374  {
3375  if( BITARRAYSAREEQUAL(mod2data->rows[mod2data->rowsind[firstrowsind + r]],
3376  zerorow, mod2data->rowsbitarraysize) ) /*lint !e647 check if row is (0 ... 0 , 1) */
3377  {
3378  /* a violated zerohalf cut has been found */
3379  weights = NULL;
3380  SCIP_CALL(getZerohalfWeightvectorFromSelectedRowsBitarray(scip, sepadata, lpdata, mod2data,
3381  mod2data->rowaggregations[mod2data->rowsind[firstrowsind + r]], &weights, &nrowsincut));
3382  if( weights == NULL )
3383  {
3384  continue;
3385  }
3386  assert(nrowsincut > 0);
3387 
3388  /* create zerohalf cut */
3389  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
3390  mod2data->relatedsubproblem, mod2data, 1, nrowsincut, cutseparatedby));
3392  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
3393 
3394  if ( cutoff )
3395  *result = SCIP_CUTOFF;
3396  else
3397  {
3398  /* add cut */
3399  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
3400  (*nzerohalfcuts)++;
3401  }
3402 
3403  /* free temporary memory */
3404  SCIPfreeMemoryArray(scip, &weights);
3405 
3406  if ( cutoff )
3407  break;
3408 
3409  removerow[r] = TRUE;
3410  nrowsremoved++;
3411  }
3412  }
3413  }
3414  }
3415 
3416  /* update mod2data->rowsind if necessary */
3417  if( ! cutoff && nrowsremoved > 0 )
3418  {
3419  r2 = firstrowsind;
3420  for( r = firstrowsind ; r < mod2data->nrowsind && r2 < mod2data->nrowsind; ++r)
3421  {
3422  if( r < lastrowsind - firstrowsind )
3423  while( removerow[r2] && r2 < mod2data->nrowsind )
3424  r2++;
3425  if( r < r2 && r2 < mod2data->nrowsind )
3426  mod2data->rowsind[r] = mod2data->rowsind[r2];
3427  r2++;
3428  }
3429  mod2data->nrowsind -= nrowsremoved;
3430  }
3431 
3432 
3433  /* free temporary memory */
3434  SCIPfreeBufferArray(scip, &zerorow);
3435  SCIPfreeBufferArray(scip, &removerow);
3436 
3437  return SCIP_OKAY;
3438 }
3439 
3440 
3441 /** applies some row reductions */
3442 static
3444  SCIP* scip, /**< SCIP data structure */
3445  SCIP_SEPADATA* sepadata, /**< separator data */
3446  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3447  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
3448  int firstrowsind, /**< first mod2data->rows index to be considered */
3449  int lastrowsind, /**< last mod2data->rows index to be considered */
3450  SCIP_Bool removezerorows, /**< should zero rows be removed? */
3451  SCIP_Bool removelargeslackrows, /**< should rows with slack > maxslack be removed? */
3452  SCIP_Bool removeidenticalrows /**< should identical rows be removed? */
3453  )
3454 { /*lint --e{647}*/
3455  int r1;
3456  int r2;
3457  SCIP_Bool* rowisprocessed;
3458  SCIP_Bool* removerow;
3459  int nzerorowsremoved;
3460  int nlargeslackrowsremoved;
3461  int nidenticalrowsremoved;
3462  SCIP_Real maxslack;
3463  BITARRAY zerorow;
3464 
3465  assert(scip != NULL);
3466  assert(lpdata != NULL);
3467  assert(mod2data != NULL);
3468  assert(mod2data->relatedsubproblem != NULL);
3469  assert(firstrowsind >= 0);
3470  assert(lastrowsind <= mod2data->nrowsind);
3471 
3472 
3473  /* check if matrix or colind range is empty */
3474  if( mod2data->nrowsind == 0 || lastrowsind - firstrowsind <= 0 )
3475  return SCIP_OKAY;
3476 
3477  /* allocate temporary memory */
3478  SCIP_CALL(SCIPallocBufferArray(scip, &rowisprocessed, lastrowsind - firstrowsind));
3479  SCIP_CALL(SCIPallocBufferArray(scip, &removerow, lastrowsind - firstrowsind));
3480  zerorow = NULL;
3481  if( removezerorows )
3482  {
3483  SCIP_CALL(SCIPallocBufferArray(scip, &zerorow, mod2data->rowsbitarraysize));
3484  }
3485  /* initialize */
3486  BMSclearMemoryArray(rowisprocessed, lastrowsind - firstrowsind);
3487  BMSclearMemoryArray(removerow, lastrowsind - firstrowsind);
3488  if( removezerorows )
3489  {
3490  BMSclearMemoryArray(zerorow, mod2data->rowsbitarraysize);
3491  }
3492  maxslack = sepadata->maxslack;
3493  nzerorowsremoved = 0;
3494  nlargeslackrowsremoved = 0;
3495  nidenticalrowsremoved = 0;
3496 
3497  /* check all pairs of rows */
3498  for( r1 = 0 ; r1 < lastrowsind - firstrowsind ; ++r1)
3499  if( !rowisprocessed[r1] )
3500  {
3501  rowisprocessed[r1] = TRUE;
3502 
3503  if( removezerorows && !removerow[r1] )
3504  if( mod2data->rhs[mod2data->rowsind[firstrowsind + r1]] == FALSE )
3505  {
3506  assert(zerorow != NULL);
3507  if( BITARRAYSAREEQUAL(mod2data->rows[mod2data->rowsind[firstrowsind + r1]],
3508  zerorow, mod2data->rowsbitarraysize) )
3509  {
3510  markRowAsRemoved(mod2data, firstrowsind + r1, ZERO_ROW);
3511  removerow[r1] = TRUE;
3512  nzerorowsremoved++;
3513  }
3514  }
3515  if( removelargeslackrows && !removerow[r1] )
3516  if( SCIPisGT(scip, mod2data->slacks[mod2data->rowsind[firstrowsind + r1]], maxslack) )
3517  {
3518  markRowAsRemoved(mod2data, firstrowsind + r1, SLACK_GREATER_THAN_MAXSLACK);
3519  removerow[r1] = TRUE;
3520  nlargeslackrowsremoved++;
3521  }
3522 
3523  if( removeidenticalrows && !removerow[r1] )
3524  for( r2 = r1 + 1 ; r2 < lastrowsind - firstrowsind ; ++r2)
3525  if( !rowisprocessed[r2] )
3526  if( mod2data->rhs[mod2data->rowsind[firstrowsind + r1]]
3527  == mod2data->rhs[mod2data->rowsind[firstrowsind + r2]] )
3528  if( BITARRAYSAREEQUAL(mod2data->rows[mod2data->rowsind[firstrowsind + r1]],
3529  mod2data->rows[mod2data->rowsind[firstrowsind + r2]], mod2data->rowsbitarraysize) )
3530  {
3531  if( SCIPisLT(scip, mod2data->slacks[mod2data->rowsind[firstrowsind + r1]],
3532  mod2data->slacks[mod2data->rowsind[firstrowsind + r2]]) )
3533  {
3534  markRowAsRemoved(mod2data, firstrowsind + r2, IDENT_TO_ROW_WITH_SMALLER_SLACK);
3535  removerow[r2] = TRUE;
3536  nidenticalrowsremoved++;
3537  rowisprocessed[r2] = TRUE;
3538  }
3539  else
3540  {
3541  markRowAsRemoved(mod2data, firstrowsind + r1, IDENT_TO_ROW_WITH_SMALLER_SLACK);
3542  removerow[r1] = TRUE;
3543  nidenticalrowsremoved++;
3544  break;
3545  }
3546  }
3547  }
3548 
3549  /* update mod2data->rowsind if necessary */
3550  if( nzerorowsremoved + nlargeslackrowsremoved + nidenticalrowsremoved > 0 )
3551  {
3552  r2 = firstrowsind;
3553  for( r1 = firstrowsind ; r1 < mod2data->nrowsind && r2 < mod2data->nrowsind; ++r1)
3554  {
3555  if( r1 < lastrowsind - firstrowsind )
3556  while( removerow[r2] && r2 < mod2data->nrowsind )
3557  r2++;
3558  if( r1 < r2 && r2 < mod2data->nrowsind )
3559  mod2data->rowsind[r1] = mod2data->rowsind[r2];
3560  r2++;
3561  }
3562  mod2data->nrowsind -= (nzerorowsremoved + nlargeslackrowsremoved + nidenticalrowsremoved);
3563  }
3564 
3565 
3566  /* free temporary memory */
3567  if( removezerorows && zerorow != NULL )
3568  {
3569  SCIPfreeBufferArray(scip, &zerorow);
3570  }
3571  SCIPfreeBufferArray(scip, &removerow);
3572  SCIPfreeBufferArray(scip, &rowisprocessed);
3573 
3574  return SCIP_OKAY;
3575 }
3576 
3577 
3578 /** applies some column reductions */
3579 static
3581  SCIP* scip, /**< SCIP data structure */
3582  SCIP_SEPADATA* sepadata, /**< separator data */
3583  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3584  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
3585  int firstcolsind, /**< first mod2data->rows index to be considered */
3586  int lastcolsind, /**< last mod2data->rows index to be considered */
3587  SCIP_Bool removezerocols, /**< should zero columns be removed? */
3588  SCIP_Bool removecolsingletons,/**< should column singletons be removed? */
3589  SCIP_Bool checkresultingrows /**< should rows whose slack becomes larger than maxslack be removed? */
3590  )
3591 {
3592  SCIP_Real maxslack;
3593  int maxnnonzentries;
3594  int nzerocolsremoved;
3595  int ncolsingletonsremoved;
3596  int nunprocessedcols;
3597  int nconsideredcols;
3598  int nnonzentries;
3599  SCIP_Bool* removecol;
3600  SCIP_Bool* colisprocessed;
3601  int rowofcolsingleton;
3602  int rowsbind;
3603  BITARRAYBITMASKTYPE rowsbmask;
3604  int r;
3605  int c;
3606  int j;
3607 
3608  assert(scip != NULL);
3609  assert(sepadata != NULL);
3610  assert(lpdata != NULL);
3611  assert(mod2data != NULL);
3612  assert(mod2data->relatedsubproblem != NULL);
3613  assert(firstcolsind >= 0);
3614  assert(lastcolsind <= mod2data->ncolsind);
3615  assert(removezerocols || removecolsingletons);
3616 
3617 
3618  nconsideredcols = lastcolsind - firstcolsind;
3619 
3620  /* check if matrix or colind range is empty */
3621  if( mod2data->ncolsind == 0 || mod2data->nrowsind == 0 || nconsideredcols <= 0 )
3622  return SCIP_OKAY;
3623 
3624 
3625  /* allocate temporary memory */
3626  SCIP_CALL(SCIPallocBufferArray(scip, &colisprocessed, nconsideredcols));
3627  SCIP_CALL(SCIPallocBufferArray(scip, &removecol, nconsideredcols));
3628 
3629  /* initialize */
3630  BMSclearMemoryArray(colisprocessed, nconsideredcols);
3631  BMSclearMemoryArray(removecol, nconsideredcols);
3632  maxslack = sepadata->maxslack;
3633  nunprocessedcols = nconsideredcols;
3634  nzerocolsremoved = 0;
3635  ncolsingletonsremoved = 0;
3636  nnonzentries = 0;
3637  rowofcolsingleton = -1;
3638  if( removecolsingletons )
3639  maxnnonzentries = 1;
3640  else
3641  maxnnonzentries = 0;
3642 
3643  /* check all columns if they contain exactly one nonzero entry */
3644  while(nunprocessedcols > 0)
3645  {
3646  for( c = 0 ; c < nconsideredcols ; ++c )
3647  if( colisprocessed[c] == FALSE )
3648  break;
3649  assert(firstcolsind + c < mod2data->ncolsind);
3650 
3651  nnonzentries = 0;
3652  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[firstcolsind + c]);
3653  rowsbmask = GETBITARRAYMASK(mod2data->colsind[firstcolsind + c]); /*lint !e701*/
3654 
3655  for( r = 0 ; r < mod2data->nrowsind ; ++r)
3656  if( mod2data->rows[mod2data->rowsind[r]][rowsbind] & rowsbmask )
3657  {
3658  nnonzentries++;
3659  if( nnonzentries > maxnnonzentries )
3660  break;
3661  rowofcolsingleton = r;
3662  }
3663 
3664  /* check if a zero column has been found */
3665  if( removezerocols )
3666  if( nnonzentries == 0 )
3667  {
3668  /* remove zero columns */
3669  removecol[c] = TRUE;
3670  nzerocolsremoved++;
3671  markColAsRemovedAndClearCol(mod2data, firstcolsind + c, ZERO_COLUMN);
3672  }
3673 
3674  /* check if a column singleton has been found */
3675  if( removecolsingletons && !removecol[c] )
3676  if( nnonzentries == 1 )
3677  {
3678  r = rowofcolsingleton;
3679  removecol[c] = TRUE;
3680 
3681  /* update row slack: slack' = slack + fracsol */
3682  mod2data->slacks[mod2data->rowsind[r]] += mod2data->fracsol[mod2data->colsind[firstcolsind + c]];
3683 
3684  /* if removing col results in a row with slack > maxslack,
3685  * then the row can be removed as well */
3686  if( checkresultingrows && SCIPisGT(scip, mod2data->slacks[mod2data->rowsind[r]], maxslack) )
3687  {
3689  for( j = 0 ; j < nconsideredcols ; ++j)
3690  if( !removecol[j] && colisprocessed[j] )
3691  if( BITARRAYBITISSET(mod2data->rows[mod2data->rowsind[r]],
3692  mod2data->colsind[firstcolsind + j]) ) /*lint !e701*/
3693  {
3694  colisprocessed[j] = FALSE; /* re-consider col */
3695  nunprocessedcols++;
3696  }
3697 
3698  BMSmoveMemoryArray(&((mod2data->rowsind)[r]), &((mod2data->rowsind)[r + 1]),
3699  mod2data->nrowsind - r - 1); /*lint !e866*/
3700 
3701  mod2data->nrowsind--;
3702  }
3703 
3704  /* remove column singleton */
3705  ncolsingletonsremoved++;
3706  markColAsRemovedAndClearCol(mod2data, firstcolsind + c, SINGLETON_COLUMN);
3707  }
3708 
3709  colisprocessed[c] = TRUE;
3710  nunprocessedcols--;
3711 
3712  if( nzerocolsremoved + ncolsingletonsremoved == nconsideredcols || mod2data->nrowsind == 0 )
3713  break;
3714  }
3715 
3716  /* if all rows have been deleted, remove cols as well */
3717  if( mod2data->nrowsind == 0 )
3718  {
3719  for( c = firstcolsind ; c < mod2data->ncolsind; ++c)
3720  if( !removecol[c] )
3721  {
3722  removecol[c] = TRUE;
3723  markColAsRemovedAndClearCol(mod2data, firstcolsind + c, ZERO_COLUMN);
3724  }
3725  nzerocolsremoved = nconsideredcols - ncolsingletonsremoved;
3726  assert(nzerocolsremoved + ncolsingletonsremoved == nconsideredcols);
3727  }
3728 
3729  /* update mod2data->colsind array if necessary*/
3730  if( mod2data->nrowsind == 0 )
3731  mod2data->ncolsind = 0;
3732  else
3733  if( nzerocolsremoved + ncolsingletonsremoved > 0 )
3734  {
3735  j = firstcolsind;
3736  for( c = firstcolsind ; c < mod2data->ncolsind && j < mod2data->ncolsind; ++c)
3737  {
3738  if( c < nconsideredcols )
3739  while( removecol[j] && j < mod2data->ncolsind )
3740  j++;
3741  if( c < j && j < mod2data->ncolsind )
3742  mod2data->colsind[c] = mod2data->colsind[j];
3743  j++;
3744  }
3745  mod2data->ncolsind -= (nzerocolsremoved + ncolsingletonsremoved);
3746  }
3747 
3748  /* free temporary memory */
3749  SCIPfreeBufferArray(scip, &removecol);
3750  SCIPfreeBufferArray(scip, &colisprocessed);
3751 
3752  return SCIP_OKAY;
3753 }
3754 
3755 
3756 /** applies modified Gaussian Elimination reduction */
3757 static
3759  SCIP* scip, /**< SCIP data structure */
3760  SCIP_SEPADATA* sepadata, /**< separator data */
3761  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
3762  ZEROHALF_MOD2DATA* mod2data /**< considered (preprocessed) subproblem mod 2 */
3763  )
3764 {
3765  int nslackzerorows;
3766  int pivotrow;
3767  int pivotcol;
3768  int pivot;
3769  int identsubmatrixsize;
3770  int rowsbind;
3771  BITARRAYBITMASKTYPE rowsbmask;
3772  int r;
3773  int temp;
3774 
3775  assert(scip != NULL);
3776  assert(sepadata != NULL);
3777  assert(lpdata != NULL);
3778  assert(mod2data != NULL);
3779  assert(mod2data->relatedsubproblem != NULL);
3780 
3781  /* check if matrix or colind range is empty */
3782  if( mod2data->ncolsind == 0 || mod2data->nrowsind == 0 )
3783  return SCIP_OKAY;
3784 
3785  /* determine number of slack zero rows */
3786  nslackzerorows = 0;
3787  while( nslackzerorows < mod2data->nrowsind
3788  && SCIPisZero(scip, mod2data->slacks[mod2data->rowsind[nslackzerorows]]) )
3789  nslackzerorows++;
3790  /* check if at least one slack zero row exists */
3791  if( nslackzerorows == 0 )
3792  return SCIP_OKAY;
3793 
3794 
3795  /* sort column indices sets w.r.t. to their primsol values NON-INCREASINGLY */
3796  if( mod2data->ncolsind > 1 )
3797  {
3798  SCIPsortInd( mod2data->colsind , compRealNonIncreasing , (void*) mod2data->fracsol , mod2data->ncolsind );
3799  }
3800 
3801  /* sort row indices sets w.r.t. to their slack values NON-DECREASINGLY */
3802  if( mod2data->nrowsind > 1 )
3803  {
3804  SCIPsortInd( mod2data->rowsind , compRealNonDecreasing , (void*) mod2data->slacks , mod2data->nrowsind );
3805  }
3806 
3807 
3808  identsubmatrixsize = 0;
3809 
3810  /* create maximal identity submatrix */
3811  /* determine pivot col */
3812  for( pivotcol = 0 ; pivotcol < mod2data->ncolsind ; ++pivotcol)
3813  {
3814  if( identsubmatrixsize == mod2data->nrowsind )
3815  break;
3816 
3817  /* determine pivot row */
3818  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[pivotcol]);
3819  rowsbmask = GETBITARRAYMASK(mod2data->colsind[pivotcol]); /*lint !e701*/
3820  for( pivotrow = identsubmatrixsize ; pivotrow < nslackzerorows ; ++pivotrow)
3821  if( mod2data->rows[mod2data->rowsind[pivotrow]][rowsbind] & rowsbmask )
3822  break;
3823  if( pivotrow == nslackzerorows )
3824  continue;
3825 
3826  /* Gaussian elimination step */
3827  for( r = 0 ; r < nslackzerorows ; ++r)
3828  {
3829  if( r == pivotrow )
3830  continue;
3831  if( mod2data->rows[mod2data->rowsind[r]][rowsbind] & rowsbmask )
3832  {
3833  /* add pivot row to r-th row */
3834  BITARRAYSXOR(mod2data->rows[mod2data->rowsind[pivotrow]],
3835  mod2data->rows[mod2data->rowsind[r]],mod2data->rowsbitarraysize);
3836  BITARRAYSXOR(mod2data->rowaggregations[mod2data->rowsind[pivotrow]],
3837  mod2data->rowaggregations[mod2data->rowsind[r]],mod2data->rowaggregationsbitarraysize);
3838  mod2data->rhs[mod2data->rowsind[r]] =
3839  XOR(mod2data->rhs[mod2data->rowsind[pivotrow]],mod2data->rhs[mod2data->rowsind[r]]);
3840  /* all rows have slack zero: */
3841  /* // mod2data->slacks[[mod2data->rowsind[r]] += mod2data->slacks[[mod2data->rowsind[pivotrow]]; */
3842  }
3843  }
3844 
3845  /* swap index set positions */
3846  temp = mod2data->rowsind[pivotrow];
3847  mod2data->rowsind[pivotrow] = mod2data->rowsind[identsubmatrixsize];
3848  mod2data->rowsind[identsubmatrixsize] = temp;
3849  temp = mod2data->colsind[pivotcol];
3850  mod2data->colsind[pivotcol] = mod2data->colsind[identsubmatrixsize];
3851  mod2data->colsind[identsubmatrixsize] = temp;
3852 
3853  identsubmatrixsize++;
3854  }
3855 
3856  if( identsubmatrixsize > 0 )
3857  {
3858  /* add rows of identity submatrix properly to rows with positive slack
3859  * to transform each column of the identity submatrix into a column singleton */
3860  for( pivot = 0 ; pivot < identsubmatrixsize ; ++pivot)
3861  {
3862  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[pivot]);
3863  rowsbmask = GETBITARRAYMASK(mod2data->colsind[pivot]); /*lint !e701*/
3864  for( r = nslackzerorows ; r < mod2data->nrowsind ; ++r)
3865  if( mod2data->rows[mod2data->rowsind[r]][rowsbind] & rowsbmask )
3866  {
3867  /* add pivot row to r-th row */
3868  BITARRAYSXOR(mod2data->rows[mod2data->rowsind[pivot]],
3869  mod2data->rows[mod2data->rowsind[r]],mod2data->rowsbitarraysize);
3870  BITARRAYSXOR(mod2data->rowaggregations[mod2data->rowsind[pivot]],
3871  mod2data->rowaggregations[mod2data->rowsind[r]],mod2data->rowaggregationsbitarraysize);
3872  mod2data->rhs[mod2data->rowsind[r]] =
3873  XOR(mod2data->rhs[mod2data->rowsind[pivot]],mod2data->rhs[mod2data->rowsind[r]]);
3874  /* all identity submatrix rows have slack zero */
3875  /* // mod2data->slacks[[mod2data->rowsind[r]] += mod2data->slacks[[mod2data->rowsind[pivot]]; */
3876  }
3877  }
3878 
3879  /* remove generated column singletons */
3880  SCIP_CALL(preprocessColumns(scip, sepadata, lpdata, mod2data,
3881  0, /*identsubmatrixsize*/ mod2data->ncolsind, FALSE, TRUE, TRUE));
3882 
3883  /* remove zero rows */
3884  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
3885  0, mod2data->nrowsind, TRUE, FALSE, FALSE));
3886  }
3887 
3888  return SCIP_OKAY;
3889 }
3890 
3891 
3892 /** decomposes the problem into subproblems which can be considered separately */
3893 static
3895  SCIP* scip, /**< SCIP data structure */
3896  SCIP_SEPADATA* sepadata, /**< separator data */
3897  ZEROHALF_LPDATA* lpdata /**< data of current LP relaxation */
3898  )
3899 {
3900 
3901 #ifdef WITHDECOMPOSE
3902  /**@todo this is buggy in different ways.
3903  * 1. it might happen that we ignore a variable of the current row and of all other rows.
3904  * thus at the end, the variable will not occur in any subproblem. BUT, currently we do not update
3905  * lpdata->subproblemsindexofcol[lppos] and lpdata->rcolsindexofcol[lppos] accordingly.
3906  * consequently, it might happen that lpdata->rcolsindexofcol[lppos] > problem->nrcols, with
3907  * with problem being the subproblem still associated to our column. therefore, a corresponding assert
3908  * assert(rcolsindex < problem->nrcols) in storeMod2Data() is violated
3909  * [e.g., for IP/atamtuerk/mik/unbounded/mik.250-1-50.3.mps.gz].
3910  * we could recognize whether a variable is never added to a subproblem and update its data structures,
3911  * but I'm not sure whether this will be correct, i.e., whether it is really ok to ignore some variables here.
3912  * 2. in particular, it seems like that this method has not been adapted to that we can deal with
3913  * continuous variables now. (see the below todo of Manuel)
3914  * 3. in case we end up with only one subproblem, we use the old problem. but in this case we do not update
3915  * the problem data and hence it is not consistent with the lpdata anymore where we might have set some
3916  * rows to be irrelevant.
3917  *
3918  * therefore, we will currently do nothing in here.
3919  */
3920  BITARRAY processedrows;
3921  int nprocessedrows;
3922  int processedrowsbitarraysize;
3923  int unprocessedrowidx;
3924 
3925  BITARRAY processedcols;
3926  int nprocessedcols;
3927  int processedcolsbitarraysize;
3928 
3929  int* queue;
3930  int queuefirst;
3931  int queuelast;
3932 
3933  int i;
3934  int j;
3935  int k;
3936 
3937  SCIP_COL** colsofrow;
3938  SCIP_ROW** rowsofcol;
3939 
3940  SCIP_Real* colvals;
3941  SCIP_Real* rowvals;
3942  int ncolvals;
3943  int nrowvals;
3944  int cidx;
3945  int ridx;
3946  int lppos;
3947 
3948  int rrowsidx;
3949  int rcolsidx;
3950 
3951  SCIP_Bool fliplhsrhs;
3952 
3953  ZEROHALF_SUBLPDATA* problem;
3954  int problemindex;
3955  ZEROHALF_SUBLPDATA* subproblem;
3956 
3957  int* rrowsinsubprob;
3958  int* rcolsinsubprob;
3959  SCIP_Bool* rrowsinsubproboddrhs;
3960  int nrrowsinsubprob;
3961  int nrcolsinsubprob;
3962 
3963  int totalnrrows;
3964  int totalnrcols;
3965 
3966  int nrrowsinitial;
3967  int nrcolsinitial;
3968  int ndelvarbounds;
3969 
3970  int rowindex;
3971  int colindex;
3972 
3973  SCIP_Real maxslack;
3974 
3975  assert(scip != NULL);
3976  assert(sepadata != NULL);
3977  assert(lpdata != NULL);
3978  assert(lpdata->subproblems != NULL);
3979  assert(lpdata->nsubproblems > 0);
3980 
3981  problemindex = 0;
3982 
3983  assert(problemindex >= 0);
3984  assert(problemindex <= lpdata->nsubproblems);
3985 
3986  problem = lpdata->subproblems[problemindex];
3987 
3988  assert(problem != NULL);
3989  assert(problem->rcols != NULL);
3990  assert(problem->nrcols > 0);
3991  assert(problem->rcolslbslack != NULL);
3992  assert(problem->rcolsubslack != NULL);
3993  assert(problem->rrows != NULL);
3994  assert(problem->nrrows > 0);
3995  assert(problem->rrowsrhs != NULL);
3996  assert(problem->rrowsslack != NULL);
3997 
3998  if( sepadata->dtimer == NULL )
3999  {
4000  ZEROHALFcreateTimer((sepadata->dtimer));
4001  }
4002  ZEROHALFstartTimer(sepadata->dtimer);
4003 
4004  processedrowsbitarraysize = (int) GETREQUIREDBITARRAYSIZE(problem->nrrows);
4005  processedcolsbitarraysize = (int) GETREQUIREDBITARRAYSIZE(problem->nrcols);
4006 
4007  SCIPfreeMemoryArray(scip, &(lpdata->subproblems));
4008 
4009  /* allocate temporary memory */
4010  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->subproblems), problem->nrrows));
4011  SCIP_CALL(SCIPallocBufferArray(scip, &processedrows, processedrowsbitarraysize));
4012  SCIP_CALL(SCIPallocBufferArray(scip, &processedcols, processedcolsbitarraysize));
4013  SCIP_CALL(SCIPallocBufferArray(scip, &queue, problem->nrrows));
4014  SCIP_CALL(SCIPallocMemoryArray(scip, &rrowsinsubprob, problem->nrrows));
4015  SCIP_CALL(SCIPallocMemoryArray(scip, &rrowsinsubproboddrhs, problem->nrrows));
4016  SCIP_CALL(SCIPallocMemoryArray(scip, &rcolsinsubprob, problem->nrcols));
4017 
4018  /* initialize temporary memory */
4019  BMSclearMemoryArray(processedrows, processedrowsbitarraysize);
4020  BMSclearMemoryArray(processedcols, processedcolsbitarraysize);
4021  lpdata->nsubproblems = 0;
4022  maxslack = sepadata->maxslack;
4023 
4024  nrrowsinitial = problem->nrrows;
4025  nrcolsinitial = problem->nrcols;
4026  totalnrrows = 0;
4027  totalnrcols = 0;
4028  ndelvarbounds = 0;
4029  nprocessedrows = 0;
4030  nprocessedcols = 0;
4031  k = 0;
4032  unprocessedrowidx = 0;
4033 
4034  while( nprocessedrows < problem->nrrows )
4035  {
4036  ++k;
4037  nrrowsinsubprob = 0;
4038  nrcolsinsubprob = 0;
4039 
4040  for( i = unprocessedrowidx ; i < problem->nrrows ; ++i)
4041  {
4042  if( BITARRAYBITISSET(processedrows, i) ) /*lint !e701*/
4043  unprocessedrowidx++;
4044  else
4045  break;
4046  }
4047  BITARRAYBITSET(processedrows, i); /*lint !e701*/
4048 
4049  queue[0] = i;
4050  queuefirst = 0;
4051  queuelast = 1;
4052 
4053  while( queuelast > queuefirst )
4054  {
4055  assert(queuelast <= problem->nrrows);
4056 
4057  i = queue[queuefirst];
4058  queuefirst++;
4059 
4060  rrowsinsubprob[nrrowsinsubprob] = i;
4061  nrrowsinsubprob++;
4062 
4063  fliplhsrhs = FALSE;
4064 
4065  colsofrow = SCIProwGetCols(lpdata->rows[problem->rrows[i]]);
4066  colvals = SCIProwGetVals(lpdata->rows[problem->rrows[i]]);
4067  ncolvals = SCIProwGetNLPNonz(lpdata->rows[problem->rrows[i]]);
4068 
4069  for( cidx = 0 ; cidx < ncolvals ; ++cidx)
4070  {
4071  lppos = SCIPcolGetLPPos(colsofrow[cidx]);
4072  if( lppos == -1 )
4073  continue;
4074  rcolsidx = lpdata->rcolsindexofcol[lppos];
4075 
4076  if( lpdata->subproblemsindexofcol[lppos] != problemindex || rcolsidx < 0 )
4077  {
4078  if( ISODD(scip, colvals[cidx]) )
4079  fliplhsrhs = XOR(fliplhsrhs,
4080  (lpdata->rcolsindexofcol[lppos] == LP_SOL_EQUALS_ODD_LB
4081  || lpdata->rcolsindexofcol[lppos] == LP_SOL_EQUALS_ODD_UB));
4082 
4083  /**@todo analogue for continuous variables? */
4084 
4085  continue; /* col is not relevant */
4086  }
4087  if( nprocessedcols == problem->nrcols )
4088  continue;
4089 
4090  if( BITARRAYBITISSET(processedcols, rcolsidx) ) /*lint !e701*/
4091  continue;
4092 
4093  if( ISEVEN(scip, colvals[cidx]) )
4094  continue;
4095 
4096  rcolsinsubprob[nrcolsinsubprob] = rcolsidx;
4097  nrcolsinsubprob++;
4098  BITARRAYBITSET(processedcols, rcolsidx); /*lint !e701*/
4099 
4100  rowsofcol = SCIPcolGetRows(colsofrow[cidx]);
4101  rowvals = SCIPcolGetVals(colsofrow[cidx]);
4102  nrowvals = SCIPcolGetNNonz(colsofrow[cidx]);
4103  for( ridx = 0 ; ridx < nrowvals ; ++ridx)
4104  {
4105  lppos = SCIProwGetLPPos(rowsofcol[ridx]);
4106  if( lppos == -1 )
4107  continue;
4108  rrowsidx = lpdata->rrowsindexofleftrow[lppos];
4109  if( lpdata->subproblemsindexofrow[lppos] == problemindex
4110  && rrowsidx >= 0 )
4111  {
4112  if( !BITARRAYBITISSET(processedrows, rrowsidx) ) /*lint !e701*/
4113  if( ISODD(scip, rowvals[ridx]) )
4114  {
4115  queue[queuelast] = rrowsidx;
4116  queuelast++;
4117  BITARRAYBITSET(processedrows, rrowsidx); /*lint !e701*/
4118  }
4119  }
4120  rrowsidx = lpdata->rrowsindexofrightrow[lppos];
4121  if( lpdata->subproblemsindexofrow[lppos] == problemindex
4122  && rrowsidx >= 0 )
4123  {
4124  if( !BITARRAYBITISSET(processedrows, rrowsidx) ) /*lint !e701*/
4125  if( ISODD(scip, rowvals[ridx]) )
4126  {
4127  queue[queuelast] = rrowsidx;
4128  queuelast++;
4129  BITARRAYBITSET(processedrows, rrowsidx); /*lint !e701*/
4130  }
4131  }
4132  }
4133  nprocessedcols++;
4134  }
4135  rrowsinsubproboddrhs[nrrowsinsubprob-1] = XOR(ISODD(scip, problem->rrowsrhs[i]),fliplhsrhs);
4136  nprocessedrows++;
4137  }
4138 
4139  /* a subproblem consisting only of rows with even rhs values can be ignored.
4140  * note: varbounds have to be considered! */
4141  for( i = 0 ; i < nrrowsinsubprob ; ++i)
4142  if( rrowsinsubproboddrhs[i] )
4143  break;
4144  for( j = 0 ; j < nrcolsinsubprob ; ++j)
4145  if( (SCIPisLE(scip, problem->rcolsubslack[rcolsinsubprob[j]], maxslack)
4146  && ISODD(scip, SCIPcolGetUb(lpdata->cols[problem->rcols[rcolsinsubprob[j]]])))
4147  || (SCIPisLE(scip, problem->rcolslbslack[rcolsinsubprob[j]], maxslack)
4148  && ISODD(scip, SCIPcolGetLb(lpdata->cols[problem->rcols[rcolsinsubprob[j]]]))) )
4149  break; /* a relevant odd varbound has been found */
4150  if( i == nrrowsinsubprob && j == nrcolsinsubprob )
4151  {
4152  /* no odd rhs value exists */
4153  for( i = 0 ; i < nrrowsinsubprob ; ++i)
4154  {
4155  lppos = SCIProwGetLPPos(lpdata->rows[problem->rrows[rrowsinsubprob[i]]]);
4156  lpdata->subproblemsindexofrow[lppos] = IRRELEVANT;
4157  if( lpdata->rrowsindexofleftrow[lppos] == rrowsinsubprob[i] )
4158  lpdata->rrowsindexofleftrow[lppos] = ROW_IN_SUBPROB_WITHOUT_ODD_RHS;
4159  if( lpdata->rrowsindexofrightrow[lppos] == rrowsinsubprob[i] )
4160  lpdata->rrowsindexofrightrow[lppos] = ROW_IN_SUBPROB_WITHOUT_ODD_RHS;
4161  }
4162  for( j = 0 ; j < nrcolsinsubprob ; ++j)
4163  {
4164  lppos = SCIPcolGetLPPos(lpdata->cols[problem->rcols[rcolsinsubprob[j]]]);
4165  lpdata->subproblemsindexofcol[lppos] = IRRELEVANT;
4166  lpdata->rcolsindexofcol[lppos] = COLUMN_IN_SUBPROB_WITHOUT_ODD_RHS;
4167 
4168  /* statistics */
4169  if( !SCIPisInfinity(scip, problem->rcolslbslack[rcolsinsubprob[j]]) )
4170  ndelvarbounds++;
4171  if( !SCIPisInfinity(scip, problem->rcolsubslack[rcolsinsubprob[j]]) )
4172  ndelvarbounds++;
4173  }
4174  continue;
4175  }
4176 
4177  /* don't create new "sub"problem if problem can't be decomposed */
4178  if( lpdata->nsubproblems == 0 && nprocessedrows == problem->nrrows )
4179  continue;
4180 
4181  /* create new subproblem */
4182  SCIP_CALL(ZerohalfSubLPDataCreate(scip, &subproblem));
4183  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rrows), nrrowsinsubprob));
4184  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rrowsrhs), nrrowsinsubprob));
4185  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rrowsslack), nrrowsinsubprob));
4186  subproblem->nrrows = nrrowsinsubprob;
4187  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rcols), nrcolsinsubprob));
4188  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rcolslbslack), nrcolsinsubprob));
4189  SCIP_CALL(SCIPallocMemoryArray(scip, &(subproblem->rcolsubslack), nrcolsinsubprob));
4190  subproblem->nrcols = nrcolsinsubprob;
4191 
4192  for( i = 0 ; i < nrrowsinsubprob ; ++i)
4193  {
4194  rowindex = problem->rrows[rrowsinsubprob[i]];
4195 
4196  subproblem->rrows[i] = rowindex;
4197  subproblem->rrowsrhs[i] = problem->rrowsrhs[rrowsinsubprob[i]];
4198  subproblem->rrowsslack[i] = problem->rrowsslack[rrowsinsubprob[i]];
4199 
4200  if( lpdata->subproblemsindexofrow[rowindex] != IRRELEVANT )
4201  {
4202  assert(lpdata->rrowsindexofleftrow[rowindex] >= 0
4203  || lpdata->rrowsindexofrightrow[rowindex] >= 0);
4204  lpdata->subproblemsindexofrow[rowindex] = lpdata->nsubproblems;
4205  if( lpdata->rrowsindexofleftrow[rowindex] >= 0 )
4206  lpdata->rrowsindexofleftrow[rowindex] = i;
4207  if( lpdata->rrowsindexofrightrow[rowindex] >= 0 )
4208  lpdata->rrowsindexofrightrow[rowindex] = i;
4209  }
4210  }
4211 
4212  for( i = 0 ; i < nrcolsinsubprob ; ++i)
4213  {
4214  colindex = problem->rcols[rcolsinsubprob[i]];
4215 
4216  subproblem->rcols[i] = colindex;
4217  subproblem->rcolslbslack[i] = problem->rcolslbslack[rcolsinsubprob[i]];
4218  subproblem->rcolsubslack[i] = problem->rcolsubslack[rcolsinsubprob[i]];
4219 
4220  if( lpdata->subproblemsindexofcol[colindex] != IRRELEVANT )
4221  {
4222  assert(lpdata->rcolsindexofcol[colindex] >= 0);
4223  lpdata->subproblemsindexofcol[colindex] = lpdata->nsubproblems;
4224  lpdata->rcolsindexofcol[colindex] = i;
4225  }
4226  }
4227 
4228  lpdata->subproblems[lpdata->nsubproblems] = subproblem;
4229  lpdata->nsubproblems++;
4230 
4231  totalnrrows += subproblem->nrrows;
4232  totalnrcols += subproblem->nrcols;
4233 
4234  SCIPdebugMessage("subproblem %d: %d rrows, %d rcols\n", k, subproblem->nrrows, subproblem->nrcols);
4235  }
4236  if( lpdata->nsubproblems == 0 )
4237  {
4238  /* problem couldn't be decomposed into different subproblems, hence keep the entire problem */
4239  lpdata->subproblems[0] = problem;
4240  lpdata->nsubproblems = 1;
4241  totalnrrows = problem->nrrows;
4242  totalnrcols = problem->nrcols;
4243 
4244  }
4245  else
4246  {
4247  ZerohalfSubLPDataFree(scip, &problem);
4248  }
4249 
4250  /* free temporary memory */
4251  SCIPfreeMemoryArray(scip, &rcolsinsubprob);
4252  SCIPfreeMemoryArray(scip, &rrowsinsubproboddrhs);
4253  SCIPfreeMemoryArray(scip, &rrowsinsubprob);
4254  SCIPfreeBufferArray(scip, &queue);
4255  SCIPfreeBufferArray(scip, &processedcols);
4256  SCIPfreeBufferArray(scip, &processedrows);
4257 
4258 
4259  ZEROHALFstopTimer(sepadata->dtimer);
4260  ZEROHALFstatisticsMessage("\n");
4261  ZEROHALFstatisticsMessage(" | --------------------------------- problem \
4262 -------------------------------- | ----- callback ---- | --total-\n");
4263  ZEROHALFstatisticsMessage(" | nrrows | nrcols | ndlrrows | ndlrcols \
4264 | nsubprob | ndelsubp | ndlvbnds | nsepcuts | ncutsfnd | time\n");
4265  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8d | %8d | %8d | %8d | %8d | %8.4f\n",
4266  "DECOMPOSITION", totalnrrows, totalnrcols, nrrowsinitial - totalnrrows, nrcolsinitial - totalnrcols,
4267  lpdata->nsubproblems, k - lpdata->nsubproblems,
4268  ndelvarbounds,
4269  0, 0, ZEROHALFevalTimer(sepadata->dtimer));
4270 
4271 #else
4272  assert(scip != NULL);
4273  assert(sepadata != NULL);
4274  assert(lpdata != NULL);
4275 #endif
4276 
4277  return SCIP_OKAY;
4278 }
4279 
4280 
4281 /** removes the largest number of columns such that the sum of the corresponding variables is at most delta */
4282 static
4284  SCIP* scip, /**< SCIP data structure */
4285  SCIP_SEPADATA* sepadata, /**< separator data */
4286  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
4287  SCIP_Real delta /**< delta value */
4288  )
4289 {
4290  int ncolsremoved;
4291  int c;
4292  SCIP_Real maxsumfracsols;
4293  SCIP_Real sumfracsols;
4294 
4295 
4296  assert(scip != NULL);
4297  assert(sepadata != NULL);
4298  assert(mod2data != NULL);
4299  assert(delta >= 0.0);
4300  assert(delta <= 1.0);
4301 
4302 
4303  /* check if matrix contains rows or columns */
4304  if( mod2data->ncolsind == 0 || mod2data->nrowsind == 0 )
4305  return SCIP_OKAY;
4306 
4307  /* check if delta is positive */
4308  if( !SCIPisPositive(scip, delta) )
4309  return SCIP_OKAY;
4310 
4311 
4312  ncolsremoved = 0;
4313  sumfracsols = 0.0;
4314  maxsumfracsols = sepadata->maxslack * delta;
4315 
4316  /* sort column indices sets w.r.t. to their primsol values NON-INCREASINGLY */
4317  if( mod2data->ncolsind > 1 )
4318  {
4319  SCIPsortInd( mod2data->colsind , compRealNonIncreasing , (void*) mod2data->fracsol , mod2data->ncolsind );
4320  }
4321 
4322  for( c = mod2data->ncolsind - 1 ; c >= 0 ; --c)
4323  {
4324  if( SCIPisGT(scip, sumfracsols + mod2data->fracsol[mod2data->colsind[c]], maxsumfracsols) )
4325  break;
4326 
4327  sumfracsols += mod2data->fracsol[mod2data->colsind[c]];
4329  ncolsremoved++;
4330  }
4331 
4332  if( ncolsremoved > 0 )
4333  {
4334  mod2data->ncolsind -= ncolsremoved;
4335  sepadata->maxslack -= sumfracsols;
4336  }
4337 
4338  return SCIP_OKAY;
4339 }
4340 
4341 
4342 /** removes some rows that cannot be combined because the resulting slack would be larger than maxslack */
4343 static
4345  SCIP* scip, /**< SCIP data structure */
4346  SCIP_SEPADATA* sepadata, /**< separator data */
4347  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
4348  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
4349  SCIP_Bool removelargeslackrows, /**< should rows with slack + minslack > maxslack be removed? */
4350  SCIP_Bool removelargecolrows /**< should rows with "large valued" columns that cannot be negated be removed? */
4351  )
4352 {
4353  int first;
4354  int last;
4355  int temp;
4356  SCIP_Real minslackoddrhsrows;
4357  SCIP_Real minslackrowwithnonz;
4358  int noddrhsrows;
4359  int nlslrowsremoved;
4360  int nlcolrowsremoved;
4361 #ifndef NDEBUG
4362  int r;
4363 #endif
4364  int c;
4365  SCIP_Bool* removerow;
4366  int i;
4367  int j;
4368  int rowsbind;
4369  BITARRAYBITMASKTYPE rowsbmask;
4370 
4371  assert(scip != NULL);
4372  assert(sepadata != NULL);
4373  assert(lpdata != NULL);
4374  assert(mod2data != NULL);
4375  assert(removelargeslackrows || removelargecolrows);
4376 
4377 
4378  /* check if( A mod 2, b mod 2) is empty */
4379  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 )
4380  return SCIP_OKAY;
4381 
4382 
4383  /* partition rows into odd-rhs-rows and even-rhs-rows */
4384  first = 0;
4385  last = mod2data->nrowsind - 1;
4386  while(first < last)
4387  {
4388  if( !mod2data->rhs[mod2data->rowsind[first]] )
4389  {
4390  temp = mod2data->rowsind[first];
4391  mod2data->rowsind[first] = mod2data->rowsind[last];
4392  mod2data->rowsind[last] = temp;
4393  --last;
4394  }
4395  else
4396  ++first;
4397  }
4398  noddrhsrows = first + (mod2data->rhs[mod2data->rowsind[first]] ? 1 : 0);
4399 
4400 
4401  /* check if odd rows exists */
4402  if( noddrhsrows == 0 )
4403  return SCIP_OKAY;
4404 
4405  /* sort each partition by nondecreasing slacks */
4406  assert(noddrhsrows >= 0);
4407  SCIPsortInd( mod2data->rowsind , compRealNonDecreasing , (void*) mod2data->slacks , noddrhsrows );
4408  if( noddrhsrows < mod2data->nrowsind )
4409  {
4410  SCIPsortInd( mod2data->rowsind + noddrhsrows , compRealNonDecreasing , (void*) mod2data->slacks ,
4411  mod2data->nrowsind - noddrhsrows );
4412  }
4413 
4414  minslackoddrhsrows = mod2data->slacks[mod2data->rowsind[0]];
4415  nlslrowsremoved = 0;
4416  nlcolrowsremoved = 0;
4417 
4418  if( SCIPisFeasZero(scip, minslackoddrhsrows) )
4419  return SCIP_OKAY;
4420 
4421  /* check if a zerohalf cut may be generated */
4422  if( SCIPisGT(scip, minslackoddrhsrows, sepadata->maxslack) )
4423  {
4424  if( removelargeslackrows )
4425  {
4426  for( i = 0 ; i < mod2data->nrowsind ; ++i )
4428  for( i = 0 ; i < mod2data->ncolsind ; ++i )
4430  mod2data->nrowsind = 0;
4431  mod2data->ncolsind = 0;
4432  }
4433  }
4434  else
4435  {
4436  SCIP_CALL(SCIPallocBufferArray(scip, &removerow, mod2data->nrowsind));
4437  BMSclearMemoryArray(removerow, mod2data->nrowsind);
4438 
4439  /* remove all rows with even rhs and slack > maxslack - minslackoddrhsrows */
4440  if( removelargeslackrows )
4441  {
4442  for( i = noddrhsrows ; i < mod2data->nrowsind ; ++i)
4443  if( SCIPisGT(scip, minslackoddrhsrows + mod2data->slacks[mod2data->rowsind[i]], sepadata->maxslack) )
4444  break;
4445  nlslrowsremoved += mod2data->nrowsind - i;
4446  while(i < mod2data->nrowsind)
4447  {
4448 #ifndef NDEBUG
4449  r = mod2data->rowsind[i];
4450 #endif
4451  assert(!mod2data->rhs[r]);
4452  assert(SCIPisGT(scip, minslackoddrhsrows + mod2data->slacks[r], sepadata->maxslack));
4454  removerow[i] = TRUE;
4455  i++;
4456  }
4457  }
4458 
4459  /* consider cols */
4460  if( removelargecolrows )
4461  {
4462  if( mod2data->ncolsind > 0 )
4463  {
4464  /* sort column indices sets w.r.t. to their primsol values NON-INCREASINGLY */
4465  if( mod2data->ncolsind > 1 )
4466  {
4467  SCIPsortInd( mod2data->colsind , compRealNonIncreasing , (void*) mod2data->fracsol , mod2data->ncolsind );
4468  }
4469 
4470  j = 0;
4471  while( j < mod2data->ncolsind && SCIPisGT(scip, mod2data->fracsol[mod2data->colsind[j]] + minslackoddrhsrows, sepadata->maxslack) )
4472  {
4473  c = mod2data->colsind[j];
4474  minslackrowwithnonz = 1.0;
4475  rowsbind = (int) GETBITARRAYINDEX(c);
4476  rowsbmask = GETBITARRAYMASK(c); /*lint !e701*/
4477  for( i = 0 ; i < mod2data->nrowsind ; ++i)
4478  if( !removerow[i] )
4479  if( mod2data->rows[mod2data->rowsind[i]][rowsbind] & rowsbmask )
4480  if( SCIPisLT(scip, mod2data->slacks[mod2data->rowsind[i]], minslackrowwithnonz) )
4481  minslackrowwithnonz = mod2data->slacks[mod2data->rowsind[i]];
4482 
4483  if( minslackrowwithnonz < 1.0 )
4484  {
4485  for( i = 0 ; i < mod2data->nrowsind ; ++i)
4486  if( !removerow[i] )
4487  if( mod2data->rows[mod2data->rowsind[i]][rowsbind] & rowsbmask )
4488  if( SCIPisGT(scip, minslackrowwithnonz + mod2data->slacks[mod2data->rowsind[i]], sepadata->maxslack) )
4489  {
4490  markRowAsRemoved(mod2data, i, LARGE_COL_EXISTS);
4491  removerow[i] = TRUE;
4492  nlcolrowsremoved++;
4493  }
4494  }
4495  j++;
4496  }
4497  }
4498  }
4499 
4500  /* update mod2data->rowsind if necessary */
4501  if( nlslrowsremoved + nlcolrowsremoved > 0 )
4502  {
4503  j = 0;
4504  for( i = 0 ; i < mod2data->nrowsind && j < mod2data->nrowsind; ++i)
4505  {
4506  if( i < mod2data->nrowsind )
4507  while( removerow[j] && j < mod2data->nrowsind )
4508  j++;
4509  if( i < j && j < mod2data->nrowsind )
4510  mod2data->rowsind[i] = mod2data->rowsind[j];
4511  j++;
4512  }
4513  mod2data->nrowsind -= (nlslrowsremoved + nlcolrowsremoved);
4514  }
4515 
4516  /* free temporary memory */
4517  SCIPfreeBufferArray(scip, &removerow);
4518  }
4519 
4520  return SCIP_OKAY;
4521 }
4522 
4523 
4524 /** aggregates identical columns into one column whose (artificial) LP solution is the sum of the aggregated columns */
4525 static
4527  SCIP* scip, /**< SCIP data structure */
4528  ZEROHALF_MOD2DATA* mod2data /**< considered (preprocessed) subproblem mod 2 */
4529  )
4530 {
4531  int c1;
4532  int c2;
4533  int r;
4534  int rowsbind1;
4536  int rowsbind2;
4537  BITARRAYBITMASKTYPE rowsbmask2;
4538  int ncolsremoved;
4539  SCIP_Bool* removecol;
4540 
4541  assert(scip != NULL);
4542  assert(mod2data != NULL);
4543 
4544  /* check if( A mod 2, b mod 2) is empty */
4545  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 || mod2data->ncolsind == 0 )
4546  return SCIP_OKAY;
4547 
4548 
4549  /* allocate and initialize temporary memory */
4550  SCIP_CALL(SCIPallocBufferArray(scip, &removecol, mod2data->ncolsind));
4551  BMSclearMemoryArray(removecol, mod2data->ncolsind);
4552  ncolsremoved = 0;
4553 
4554 
4555  /* check each pair of columns */
4556  for( c1 = 0 ; c1 < mod2data->ncolsind - 1 ; ++c1)
4557  {
4558  rowsbind1 = (int) GETBITARRAYINDEX(mod2data->colsind[c1]);
4559  rowsbmask1 = GETBITARRAYMASK(mod2data->colsind[c1]); /*lint !e701*/
4560  for( c2 = c1 + 1 ; c2 < mod2data->ncolsind ; ++c2)
4561  {
4562  rowsbind2 = (int) GETBITARRAYINDEX(mod2data->colsind[c2]);
4563  rowsbmask2 = GETBITARRAYMASK(mod2data->colsind[c2]); /*lint !e701*/
4564  for( r = 0 ; r < mod2data->nrowsind ; ++r)
4565  if( (mod2data->rows[mod2data->rowsind[r]][rowsbind1] & rowsbmask1)
4566  != (mod2data->rows[mod2data->rowsind[r]][rowsbind2] & rowsbmask2) )
4567  break;
4568  if( r == mod2data->nrowsind )
4569  {
4570  /* a pair of identical columns have been found */
4571 
4572  mod2data->fracsol[mod2data->colsind[c2]] += mod2data->fracsol[mod2data->colsind[c1]];
4573  removecol[c1] = TRUE;
4574  ncolsremoved++;
4576  }
4577  }
4578  }
4579 
4580  /* update mod2data->colsind array if necessary*/
4581  if( ncolsremoved > 0 )
4582  {
4583  c1 = 0;
4584  for( c2 = 0 ; c2 < mod2data->ncolsind && c1 < mod2data->ncolsind; ++c2)
4585  {
4586  if( c2 < mod2data->ncolsind )
4587  while( removecol[c1] && c1 < mod2data->ncolsind )
4588  c1++;
4589  if( c2 < c1 && c1 < mod2data->ncolsind )
4590  mod2data->colsind[c2] = mod2data->colsind[c1];
4591  c1++;
4592  }
4593  mod2data->ncolsind -= ncolsremoved;
4594  }
4595 
4596  /* free temporary memory */
4597  SCIPfreeBufferArray(scip, &removecol);
4598 
4599  return SCIP_OKAY;
4600 }
4601 
4602 
4603 /** preprocess subproblem */
4604 static
4606  SCIP* scip, /**< SCIP data structure */
4607  SCIP_SEPA* sepa, /**< separator */
4608  SCIP_SEPADATA* sepadata, /**< separator data */
4609  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
4610  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
4611  char normtype, /**< type of norm to use for efficacy norm calculation */
4612  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
4613  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
4614  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
4615  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
4616  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
4617  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
4618  SCIP_RESULT* result /**< pointer to SCIP result value of separation */
4619  )
4620 {
4621  int i;
4622 #ifdef ZEROHALF__PRINT_STATISTICS
4623  int ncolsbeforeppm;
4624  int ncolsinitial;
4625  int nrowsbeforeppm;
4626  int nrowsinitial;
4627  int nsepacutsbeforeppm;
4628  int nsepacutsinitial;
4629  int nzerohalfcutsbeforeppm;
4630  int nzerohalfcutsinitial;
4631  SCIP_CLOCK* timer;
4632  SCIP_CLOCK* pptimer;
4633 #endif
4634  char ppname[SCIP_MAXSTRLEN];
4635 
4636  assert(scip != NULL);
4637  assert(sepadata != NULL);
4638  assert(lpdata != NULL);
4639  assert(mod2data != NULL);
4640  assert(maxsepacuts >= 0);
4641  assert(maxcuts >= 0);
4642  assert(result != NULL);
4643  assert(nsepacuts != NULL);
4644  assert(nzerohalfcuts != NULL);
4645  assert(zerohalfcuts != NULL);
4646  assert(*nsepacuts <= *nzerohalfcuts);
4647 
4648  assert(mod2data->relatedsubproblem != NULL);
4649  assert(mod2data->rows != NULL);
4650  assert(mod2data->rowaggregations != NULL);
4651  assert(mod2data->rhs != NULL);
4652  assert(mod2data->slacks != NULL);
4653  assert(mod2data->fracsol != NULL);
4654  assert(mod2data->nrows > 0);
4655  assert(mod2data->rowsind != NULL);
4656  assert(mod2data->colsind != NULL);
4657 
4658  if( sepadata->nppmethods == -1 )
4659  {
4660  sepadata->nppmethods = (int) strlen(sepadata->ppmethods);
4661  if( sepadata->nppmethods > 0 && sepadata->ppmethods[0] == '-' )
4662  sepadata->nppmethods = 0;
4663  }
4664 
4665  if( sepadata->nppmethods == 0 )
4666  return SCIP_OKAY;
4667 
4668  /* statistics */
4669 #ifdef ZEROHALF__PRINT_STATISTICS
4670  if( sepadata->pptimers == NULL )
4671  {
4672  SCIP_CALL( SCIPallocMemoryArray(scip, &(sepadata->pptimers), sepadata->nppmethods + 1) );
4673  for( i = 0 ; i < sepadata->nppmethods + 1 ; ++i)
4674  {
4675  ZEROHALFcreateTimer((sepadata->pptimers[i]));
4676  }
4677  }
4678  ZEROHALFstartTimer(sepadata->pptimers[sepadata->nppmethods]);
4679 #endif
4680 
4681  if( mod2data->nrowsind == 0 || mod2data->ncolsind == 0 )
4682  return SCIP_OKAY;
4683 
4684 #ifdef ZEROHALF__PRINT_STATISTICS
4685  ncolsinitial = mod2data->ncolsind;
4686  nrowsinitial = mod2data->nrowsind;
4687  nsepacutsinitial = *nsepacuts;
4688  nzerohalfcutsinitial = *nzerohalfcuts;
4689 #endif
4690 
4691 #ifdef ZEROHALF__PRINT_STATISTICS
4692  ZEROHALFstatisticsMessage("\n");
4693  ZEROHALFstatisticsMessage(" | ------------------------------- subproblem\
4694  ------------------------------- | ----- callback ---- | --total-\n");
4695  ZEROHALFstatisticsMessage(" | nrowsind | ncolsind | ndelrows | ndelcols \
4696 | nsepcuts | ncutsfnd | time | nsepcuts | ncutsfnd | time\n");
4697  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8d | %8d | %8.4f | %8d | %8d | %8.4f\n",
4698  "START PREPROCSS", mod2data->nrowsind, mod2data->ncolsind, 0, 0, 0, 0, 0.0,
4699  *nsepacuts, *nzerohalfcuts, ZEROHALFevalTimer(sepadata->pptimers[sepadata->nppmethods]));
4700  ZEROHALFcreateNewTimer(timer);
4701  ZEROHALFstartTimer(timer);
4702 
4703  ZEROHALFcreateNewTimer(pptimer);
4704 #endif
4705 
4706  for( i = 0 ; i < sepadata->nppmethods ; ++i)
4707  {
4708  /* abort if enough cuts have already been found */
4709  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
4710  break;
4711 #ifndef ZEROHALF__PRINT_STATISTICS
4712  /* abort preprocessing if matrix is empty */
4713  if( mod2data->nrowsind == 0 && mod2data->ncolsind == 0 )
4714  break;
4715 #endif
4716 
4717 #ifdef ZEROHALF__PRINT_STATISTICS
4718  /* statistics*/
4719  ZEROHALFstartTimer(pptimer);
4720  ZEROHALFstartTimer(sepadata->pptimers[i]);
4721  ncolsbeforeppm = mod2data->ncolsind;
4722  nrowsbeforeppm = mod2data->nrowsind;
4723  nsepacutsbeforeppm = *nsepacuts;
4724  nzerohalfcutsbeforeppm = *nzerohalfcuts;
4725 #endif
4726 
4727  /* apply preprocessing method */
4728  switch(sepadata->ppmethods[i])
4729  {
4731  SCIP_CALL(preprocessModGaussElim(scip, sepadata, lpdata, mod2data));
4732  strncpy(ppname,"gauss",SCIP_MAXSTRLEN);
4733  break;
4734  case DELETEZEROROWS:
4735  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
4736  0, mod2data->nrowsind, TRUE, FALSE, FALSE));
4737  strncpy(ppname,"zero rows",SCIP_MAXSTRLEN);
4738  break;
4739  case DELETEZEROCOLS:
4740  SCIP_CALL(preprocessColumns(scip, sepadata, lpdata, mod2data,
4741  0, mod2data->ncolsind, TRUE, FALSE, FALSE));
4742  strncpy(ppname,"zero columns",SCIP_MAXSTRLEN);
4743  break;
4744  case DELETECOLSINGLETONS:
4745  SCIP_CALL(preprocessColumns(scip, sepadata, lpdata, mod2data,
4746  0, mod2data->ncolsind, FALSE, TRUE, TRUE));
4747  strncpy(ppname,"col singletons",SCIP_MAXSTRLEN);
4748  break;
4749  case ADDTRIVIALCUTS:
4750  SCIP_CALL(preprocessTrivialZerohalfCuts(scip, sepa, sepadata, lpdata, mod2data,
4751  0, mod2data->nrowsind, normtype, maxsepacuts, maxcuts, nsepacuts,
4752  nzerohalfcuts, zerohalfcuts, varsolvals, PPZEROONEROW, result));
4753  strncpy(ppname,"trivial cuts",SCIP_MAXSTRLEN);
4754  break;
4755  case DELETEIDENTROWS:
4756  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
4757  0, mod2data->nrowsind, FALSE, FALSE, TRUE));
4758  strncpy(ppname,"identical rows",SCIP_MAXSTRLEN);
4759  break;
4760  case MERGEIDENTCOLS:
4761  SCIP_CALL(preprocessIdenticalColums(scip, mod2data));
4762  strncpy(ppname,"identical cols",SCIP_MAXSTRLEN);
4763  break;
4764  case DELETELARGESLACKROWS:
4765  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
4766  0, mod2data->nrowsind, FALSE, TRUE, FALSE));
4767  strncpy(ppname,"sl>maxsl rows",SCIP_MAXSTRLEN);
4768  break;
4769  case PPCOLUMNS:
4770  SCIP_CALL(preprocessColumns(scip, sepadata, lpdata, mod2data,
4771  0, mod2data->ncolsind, TRUE, TRUE, TRUE));
4772  strncpy(ppname,"(pp cols)",SCIP_MAXSTRLEN);
4773  break;
4774  case PPROWS:
4775  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
4776  0, mod2data->nrowsind, TRUE, TRUE, TRUE));
4777  strncpy(ppname,"(pp rows)",SCIP_MAXSTRLEN);
4778  break;
4780  SCIP_CALL(preprocessColumnsWithSmallFracsol(scip, sepadata, mod2data,
4781  sepadata->ppdelta));
4782  strncpy(ppname,"delta heur",SCIP_MAXSTRLEN);
4783  break;
4784  case DELETEROWSWRTMINSLACK:
4785  SCIP_CALL(preprocessConsiderMinSlack(scip, sepadata, lpdata, mod2data, TRUE, TRUE));
4786  strncpy(ppname,"s_odd",SCIP_MAXSTRLEN);
4787  break;
4788  default:
4789  SCIPerrorMessage("invalid preprocessing method '%c'\n", sepadata->ppmethods[i]);
4790  return SCIP_INVALIDDATA;
4791  }
4792 
4793 #ifdef ZEROHALF__PRINT_STATISTICS
4794  /* statistics */
4795  ZEROHALFstopTimer(sepadata->pptimers[i]);
4796  ZEROHALFstopTimer(pptimer);
4797  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8d | %8d | %8.4f | %8d | %8d | %8.4f\n",
4798  ppname, mod2data->nrowsind, mod2data->ncolsind,
4799  nrowsbeforeppm - mod2data->nrowsind, ncolsbeforeppm - mod2data->ncolsind,
4800  *nsepacuts - nsepacutsbeforeppm, *nzerohalfcuts - nzerohalfcutsbeforeppm,
4801  ZEROHALFevalTimer(pptimer), *nsepacuts, *nzerohalfcuts,
4802  ZEROHALFevalTimer(sepadata->pptimers[i]));
4803  ZEROHALFresetTimer(pptimer);
4804 #endif
4805  }
4806 
4807 #ifdef ZEROHALF__PRINT_STATISTICS
4808  /* statistics */
4809  ZEROHALFstopTimer(timer);
4810  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8d | %8d | %8.4f | %8d | %8d | %8.4f\n",
4811  "PREPROCESSED", mod2data->nrowsind, mod2data->ncolsind,
4812  nrowsinitial - mod2data->nrowsind, ncolsinitial - mod2data->ncolsind,
4813  *nsepacuts - nsepacutsinitial, *nzerohalfcuts - nzerohalfcutsinitial,
4814  ZEROHALFevalTimer(timer), *nsepacuts, *nzerohalfcuts,
4815  ZEROHALFevalTimer(sepadata->pptimers[sepadata->nppmethods]));
4816  ZEROHALFstatisticsMessage("\n");
4817  ZEROHALFfreeTimer(timer);
4818  ZEROHALFfreeTimer(pptimer);
4819  ZEROHALFstopTimer(sepadata->pptimers[sepadata->nppmethods]);
4820 
4821  ZEROHALFstatisticsMessage(" | ------------------------------- subproblem ------------------------------- | ------------------------------\n");
4822  ZEROHALFstatisticsMessage(" | | max2/row | max2/col | A^T ept | \n");
4823  ZEROHALFstatisticsMessage("%15s | | %8s | %8s | %8s |\n",
4824  "SUBPROBSTRUCT",
4825  hasMatrixMax2EntriesPerRow(mod2data) ? "yes" : "no", hasMatrixMax2EntriesPerColumn(mod2data) ? "yes" : "no", "n/a");
4826  ZEROHALFstatisticsMessage("\n");
4827 #endif
4828 
4829  return SCIP_OKAY;
4830 }
4831 
4832 
4833 /* --------------------------------------------------------------------------------------------------------------------
4834  * local methods: separating methods
4835  * -------------------------------------------------------------------------------------------------------------------- */
4836 
4837 
4838 /** returns the objective weights for the weighted feasibility AuxIP */
4839 static
4841  BITARRAY rowaggregation, /**< row aggregation bitarray */
4842  int nrrows /**< number of relevant rows */
4843  )
4844 {
4845  int i;
4846  int naggregatedrrows;
4847 
4848  assert(rowaggregation != NULL);
4849  assert(nrrows > 0);
4850 
4851  naggregatedrrows = 0;
4852  for( i = 0 ; i < nrrows ; ++i)
4853  if( BITARRAYBITISSET(rowaggregation, i) ) /*lint !e701*/
4854  naggregatedrrows++;
4855 
4856  return (SCIP_Real) naggregatedrrows;
4857 }
4858 
4859 
4860 /** creates a "subscip" representing the following auxiliary IP (AuxIP):
4861  * min z := s^T v + x^T y
4862  * s.t. (b (mod 2))^T v - 2q = 1
4863  * (A (mod 2))^T v - y - -2r = 0
4864  *
4865  * v \\in {0,1}^nrowsind
4866  * y \\in {0,1}^ncolsind
4867  * r \\in Z^ncolsind_+
4868  * q \\in Z_+
4869  */
4870 #define BRANCHPRIORITY__AVOID_BRANCHING 0
4871 #define BRANCHPRIORITY__PREFER_BRANCHING 0
4872 static
4874  SCIP* scip, /**< SCIP data structure */
4875  SCIP_SEPADATA* sepadata, /**< separator data */
4876  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
4877  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
4878  ZEROHALF_AUXIPDATA* auxipdata, /**< pointer to data structure to store the auxiliary IP data */
4879  SCIP_Bool setnodelimit /**< should a node limit be set? */
4880  )
4881 {
4882  SCIP_VAR** consvars;
4883  SCIP_Real* consvals;
4884  SCIP_Real maxslack;
4885  char consname[SCIP_MAXSTRLEN];
4886  char varname[SCIP_MAXSTRLEN];
4887  int i;
4888  int j;
4889  int maxnconsvars;
4890  int nconsvars;
4891  SCIP_Bool isfeasip;
4892  SCIP_Bool isweighted;
4893  SCIP_Bool ispenalized;
4894  SCIP_Bool settingsfileexists;
4895 
4896  int nrrows;
4897 
4898  int rowsbind;
4899  BITARRAYBITMASKTYPE rowsbmask;
4900 
4901  SCIP_Bool success;
4902 
4903  SCIP_Real feastol;
4904 
4905  assert(scip != NULL);
4906  assert(sepadata != NULL);
4907  assert(lpdata != NULL);
4908  assert(mod2data != NULL);
4909  assert(auxipdata != NULL);
4910 
4911  assert(mod2data->relatedsubproblem != NULL);
4912  assert(mod2data->rows != NULL);
4913  assert(mod2data->rowaggregations != NULL);
4914  assert(mod2data->rhs != NULL);
4915  assert(mod2data->slacks != NULL);
4916  assert(mod2data->fracsol != NULL);
4917  assert(mod2data->rowsind != NULL);
4918  assert(mod2data->colsind != NULL);
4919 
4920  assert(auxipdata->subscip == NULL);
4921  assert(auxipdata->v == NULL);
4922  assert(auxipdata->y == NULL);
4923  assert(auxipdata->r == NULL);
4924  assert(auxipdata->q == NULL);
4925  assert(auxipdata->feasipcons == NULL);
4926  assert(auxipdata->oddrhscons == NULL);
4927  assert(auxipdata->columnsumcons == NULL);
4928 
4929 
4930  auxipdata->m = mod2data->nrowsind;
4931  auxipdata->n = mod2data->ncolsind;
4932 
4933  /* alloc temporary memory for subscipdata elements*/
4934  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxipdata->v), auxipdata->m));
4935  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxipdata->y), auxipdata->n));
4936  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxipdata->r), auxipdata->n));
4937  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxipdata->columnsumcons), auxipdata->n));
4938 
4939  /* initialize allocated data structures */
4940  BMSclearMemoryArray(auxipdata->v, auxipdata->m); /* NULL = 0x0 */
4941  BMSclearMemoryArray(auxipdata->y, auxipdata->n); /* NULL = 0x0 */
4942  BMSclearMemoryArray(auxipdata->r, auxipdata->n); /* NULL = 0x0 */
4943  BMSclearMemoryArray(auxipdata->columnsumcons, auxipdata->n); /* NULL = 0x0 */
4944 
4945  maxslack = sepadata->maxslack;
4946  nrrows = mod2data->relatedsubproblem->nrrows;
4947 
4948  /* determine subscip limits */
4949  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &auxipdata->timelimit) );
4950  if( !SCIPisInfinity(scip, auxipdata->timelimit) )
4951  auxipdata->timelimit -= SCIPgetSolvingTime(scip);
4952 
4953  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
4954  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &auxipdata->memorylimit) );
4955  if( !SCIPisInfinity(scip, auxipdata->memorylimit) )
4956  {
4957  auxipdata->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
4958  auxipdata->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
4959  }
4960 
4961  if( setnodelimit == TRUE )
4962  auxipdata->nodelimit = 3000;
4963  else
4964  auxipdata->nodelimit = -1;
4965 
4966  feastol = SCIPfeastol(scip);
4967  auxipdata->objectivelimit = MIN(1.0, maxslack + feastol);
4968 
4969  /* abort if not enough memory available */
4970  if( auxipdata->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
4971  return SCIP_OKAY;
4972 
4973  /* abort if not enough time available */
4974  if( auxipdata->timelimit <= 0.0 )
4975  return SCIP_OKAY;
4976 
4977  /* alloc further temporary memory */
4978  maxnconsvars = auxipdata->m + auxipdata->n + 2;
4979  SCIP_CALL(SCIPallocBufferArray(scip, &consvals, maxnconsvars));
4980  SCIP_CALL(SCIPallocBufferArray(scip, &consvars, maxnconsvars));
4981 
4982  /* create and initialize framework */
4983 
4984  SCIP_CALL( SCIPcreate(&(auxipdata->subscip)) );
4985  success = FALSE;
4986 #ifndef NDEBUG
4987  SCIP_CALL( SCIPcopyPlugins(scip, auxipdata->subscip, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
4988  TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, &success) );
4989 #else
4990  SCIP_CALL( SCIPcopyPlugins(scip, auxipdata->subscip, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE,
4991  TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, &success) );
4992 #endif
4993  SCIPdebugMessage("Copying the plugins was %s successful.\n", success ? "" : "not");
4994 
4995  SCIP_CALL( SCIPcreateProb(auxipdata->subscip, "sepa_zerohalf auxiliary IP (AuxIP)",
4996  NULL, NULL , NULL , NULL , NULL , NULL , NULL) );
4997 
4998  settingsfileexists = TRUE;
4999  if( strlen(sepadata->subscipsettings) == 0 )
5000  settingsfileexists = FALSE;
5001  if( strlen(sepadata->subscipsettings) == 1 && sepadata->subscipsettings[0] == '-' )
5002  settingsfileexists = FALSE;
5003 
5004  if( settingsfileexists )
5005  {
5006  /* read subscip settings file */
5007  SCIP_CALL(SCIPreadParams(auxipdata->subscip, sepadata->subscipsettings));
5008  }
5009  else
5010  {
5011  /* do not abort subscip on CTRL-C */
5012  SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "misc/catchctrlc", FALSE));
5013 
5014  /* disable output to console */
5015 #ifdef SCIP_DEBUG
5016  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "display/verblevel", 4));
5017  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "display/freq", 1));
5018 #else
5019  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "display/verblevel", 0));
5020  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "display/freq", 1000));
5021 #endif
5022  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "display/nsols/active", 2));
5023 
5024  /* forbid recursive call of heuristics solving subMIPs */
5025  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/rins/freq", -1));
5026  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/rens/freq", -1));
5027  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/localbranching/freq", -1));
5028  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/crossover/freq", -1));
5029 
5030  /* disable cut separation in subscip */
5031  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "separating/zerohalf/freq", -1));
5032  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "separating/maxrounds", 0)); */
5033  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "separating/maxroundsroot", 0)); */
5034  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "separating/maxcuts", 0)); */
5035  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "separating/maxcutsroot", 0)); */
5036 
5037  /* use pseudo cost branching without strong branching */
5038  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "branching/pscost/priority", INT_MAX/4)); */
5039 
5040  /* disable expensive presolving */
5041  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "presolving/probing/maxrounds", 0)); */
5042  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "constraints/linear/maxpresolpairrounds", 0)); */
5043  /* SCIP_CALL(SCIPsetRealParam(auxipdata->subscip, "constraints/linear/maxaggrnormscale", 0.0)); */
5044 
5045  /* disable conflict analysis */
5046  /* SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "conflict/useprop", FALSE)); */
5047  /* SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "conflict/useinflp", FALSE)); */
5048  /* SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "conflict/useboundlp", FALSE)); */
5049  /* SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "conflict/usesb", FALSE)); */
5050  /* SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "conflict/usepseudo", FALSE)); */
5051 
5052  SCIP_CALL(SCIPsetBoolParam(auxipdata->subscip, "branching/preferbinary", TRUE));
5053  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/shifting/freq", 3));
5054  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/simplerounding/freq", 1));
5055  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/rounding/freq", 1));
5056  SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/oneopt/freq", 1));
5057 
5058  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/pscostdiving/freq", 1)); */
5059  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/feaspump/freq", 3)); */
5060 
5061  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/coefdiving/freq", -1)); */
5062  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/fracdiving/freq", -1)); */
5063  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/guideddiving/freq", -1)); */
5064  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/linesearchdiving/freq", -1)); */
5065  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/objpscostdiving/freq", -1)); */
5066  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/rootsoldiving/freq", -1)); */
5067  /* SCIP_CALL(SCIPsetIntParam(auxipdata->subscip, "heuristics/veclendiving/freq", -1)); */
5068  }
5069 
5070  /* get type of auxiliary IP objective function */
5071  isfeasip = (sepadata->subscipobjective == 'v' ? FALSE : TRUE);
5072  isweighted = (sepadata->subscipobjective == 'w' ? TRUE : FALSE);
5073  ispenalized = (sepadata->subscipobjective == 'p' ? TRUE : FALSE);
5074 
5075  /* set limits of subscip */
5076  SCIP_CALL( SCIPsetLongintParam(auxipdata->subscip, "limits/nodes", (SCIP_Longint) auxipdata->nodelimit) );
5077  SCIP_CALL( SCIPsetRealParam(auxipdata->subscip, "limits/time", auxipdata->timelimit) );
5078  SCIP_CALL( SCIPsetRealParam(auxipdata->subscip, "limits/memory", auxipdata->memorylimit) );
5079 
5080  if( !isfeasip )
5081  {
5082  SCIP_CALL( SCIPsetObjlimit(auxipdata->subscip, auxipdata->objectivelimit) );
5083  }
5084  SCIP_CALL( SCIPsetIntParam(auxipdata->subscip, "limits/solutions", sepadata->subscipsollimit) );
5085 
5086 
5087  /* create variables and set objective */
5088  /* q */
5089  SCIP_CALL( SCIPcreateVar(auxipdata->subscip, &(auxipdata->q), "q", 0.0, SCIPinfinity(auxipdata->subscip),
5091  SCIP_CALL( SCIPaddVar(auxipdata->subscip, auxipdata->q) );
5092  SCIP_CALL( SCIPchgVarBranchPriority(auxipdata->subscip, auxipdata->q, BRANCHPRIORITY__AVOID_BRANCHING) );
5093  /* r */
5094  for( j = 0 ; j < auxipdata->n ; ++j)
5095  {
5096  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "r_colsind%d(rcols%d)", j, mod2data->colsind[j]);
5097  SCIP_CALL( SCIPcreateVar(auxipdata->subscip, &(auxipdata->r[j]), varname, 0.0, SCIPinfinity(auxipdata->subscip),
5099  SCIP_CALL( SCIPaddVar(auxipdata->subscip, auxipdata->r[j]) );
5100  SCIP_CALL( SCIPchgVarBranchPriority(auxipdata->subscip, auxipdata->q, BRANCHPRIORITY__AVOID_BRANCHING) );
5101  }
5102  /* v */
5103  for( i = 0 ; i < auxipdata->m ; ++i)
5104  {
5105  SCIP_Real objcoef;
5106  assert(mod2data->rows[mod2data->rowsind[i]] != NULL);
5107 
5108  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "v_rowsind%d(rrows%d)", i, mod2data->rowsind[i]);
5109  if( isfeasip )
5110  {
5111  if( isweighted )
5112  {
5113  objcoef = calcObjWeight(mod2data->rowaggregations[mod2data->rowsind[i]], nrrows);
5114  }
5115  else if( ispenalized )
5116  {
5117  objcoef = mod2data->slacks[mod2data->rowsind[i]]
5118  + (sepadata->subscipobjpen
5119  * calcObjWeight(mod2data->rowaggregations[mod2data->rowsind[i]], nrrows));
5120  }
5121  else
5122  objcoef = 1.0;
5123  }
5124  else
5125  objcoef = mod2data->slacks[mod2data->rowsind[i]];
5126  assert(!SCIPisFeasNegative(scip, objcoef));
5127  SCIP_CALL( SCIPcreateVar(auxipdata->subscip, &(auxipdata->v[i]), varname, 0.0, 1.0, objcoef,
5129  SCIP_CALL( SCIPaddVar(auxipdata->subscip, auxipdata->v[i]) );
5130  SCIP_CALL(SCIPchgVarBranchPriority(auxipdata->subscip, auxipdata->q, BRANCHPRIORITY__PREFER_BRANCHING));
5131  }
5132  /* y */
5133  for( j = 0 ; j < auxipdata->n ; ++j)
5134  {
5135  SCIP_Real objcoef;
5136  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "y_%d(%d)", j, mod2data->colsind[j]);
5137  if( isfeasip )
5138  objcoef = 0.0;
5139  else
5140  objcoef = mod2data->fracsol[mod2data->colsind[j]];
5141  SCIP_CALL( SCIPcreateVar(auxipdata->subscip, &(auxipdata->y[j]), varname, 0.0, 1.0, objcoef,
5143  SCIP_CALL( SCIPaddVar(auxipdata->subscip, auxipdata->y[j]) );
5144  }
5145 
5146  /* create constraints */
5147  /* "feasibility constraint" */
5148  if( isfeasip )
5149  {
5150  nconsvars = 0;
5151  for( i = 0 ; i < auxipdata->m ; ++i)
5152  {
5153  consvals[nconsvars] = mod2data->slacks[mod2data->rowsind[i]];
5154  consvars[nconsvars] = auxipdata->v[i];
5155  nconsvars++;
5156  }
5157  for( j = 0 ; j < auxipdata->n ; ++j)
5158  {
5159  consvals[nconsvars] = mod2data->fracsol[mod2data->colsind[j]];
5160  consvars[nconsvars] = auxipdata->y[j];
5161  nconsvars++;
5162  }
5163  SCIP_CALL( SCIPcreateConsLinear(auxipdata->subscip, &(auxipdata->oddrhscons), "feas",
5164  nconsvars, consvars, consvals, 0.0, auxipdata->objectivelimit,
5165  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5166  SCIP_CALL( SCIPaddCons(auxipdata->subscip, auxipdata->oddrhscons) );
5167  }
5168  /* "odd rhs" */
5169  nconsvars = 0;
5170  for( i = 0 ; i < auxipdata->m ; ++i)
5171  if( mod2data->rhs[mod2data->rowsind[i]] == TRUE )
5172  {
5173  consvals[nconsvars] = 1.0;
5174  consvars[nconsvars] = auxipdata->v[i];
5175  nconsvars++;
5176  }
5177  consvals[nconsvars] = -2.0;
5178  consvars[nconsvars] = auxipdata->q;
5179  nconsvars++;
5180  SCIP_CALL( SCIPcreateConsLinear(auxipdata->subscip, &(auxipdata->oddrhscons), "odd_rhs",
5181  nconsvars, consvars, consvals, 1.0, 1.0,
5182  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5183  SCIP_CALL( SCIPaddCons(auxipdata->subscip, auxipdata->oddrhscons) );
5184  /* "column sum" */
5185  for( j = 0 ; j < auxipdata->n ; ++j)
5186  {
5187  nconsvars = 0;
5188 
5189  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[j]);
5190  rowsbmask = GETBITARRAYMASK(mod2data->colsind[j]); /*lint !e701*/
5191  for( i = 0 ; i < auxipdata->m ; ++i) {
5192  if( mod2data->rows[mod2data->rowsind[i]][rowsbind] & rowsbmask )
5193  {
5194  consvals[nconsvars] = 1.0;
5195  consvars[nconsvars] = auxipdata->v[i];
5196  nconsvars++;
5197  }
5198  }
5199  consvals[nconsvars] = -1.0;
5200  consvars[nconsvars] = auxipdata->y[j];
5201  nconsvars++;
5202  consvals[nconsvars] = -2.0;
5203  consvars[nconsvars] = auxipdata->r[j];
5204  nconsvars++;
5205 
5206  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "col_%d(%d)_sum", j, mod2data->colsind[j]);
5207  SCIP_CALL( SCIPcreateConsLinear(auxipdata->subscip, &(auxipdata->columnsumcons[j]) , consname, nconsvars, consvars, consvals, 0.0, 0.0,
5208  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5209  SCIP_CALL( SCIPaddCons(auxipdata->subscip, auxipdata->columnsumcons[j]) );
5210  }
5211 
5212  /* free temporary memory */
5213  SCIPfreeBufferArray(scip, &consvars);
5214  SCIPfreeBufferArray(scip, &consvals);
5215 
5216  SCIPdebug( SCIP_CALL( SCIPprintOrigProblem(auxipdata->subscip, NULL, NULL, TRUE) ) );
5217 
5218  return SCIP_OKAY;
5219 }
5220 
5221 
5222 /** solves the auxiliary IP given as subscip */
5223 static
5225  SCIP* scip, /**< SCIP data structure */
5226  SCIP_SEPADATA* sepadata, /**< separator data */
5227  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
5228  ZEROHALF_AUXIPDATA* auxipdata, /**< auxiliary IP data */
5229  SCIP_SOL*** sols, /**< pointer to store array of solutions */
5230  int* nsols /**< pointer to store number of solutions */
5231  )
5232 {
5233  SCIP_RETCODE retcode;
5234  SCIP_STAGE subscipstage;
5235  SCIP_Real maxslack;
5236  int i;
5237  int j;
5238 
5239  assert(sepadata != NULL);
5240  assert(mod2data != NULL);
5241  assert(auxipdata != NULL);
5242  assert(auxipdata->subscip != NULL);
5243  assert(sols != NULL);
5244  assert(*sols == NULL);
5245  assert(*nsols == 0);
5246 
5247  /* solve AuxIP */
5248  retcode = SCIPsolve(auxipdata->subscip);
5249 
5250  /* errors in solving the subproblem should not kill the overall solving process;
5251  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
5252  if ( retcode != SCIP_OKAY )
5253  {
5254 #ifndef NDEBUG
5255  SCIP_CALL( retcode );
5256 #endif
5257  SCIPwarningMessage(scip, "Error while solving subproblem in zerohalf separator; sub-SCIP terminated with code <%d>\n", retcode);
5258  *nsols = 0;
5259  return SCIP_OKAY;
5260  }
5261 
5262  /* print statistic */
5263  SCIPdebug( SCIP_CALL( SCIPprintStatistics(auxipdata->subscip, NULL) ) );
5264 
5265  maxslack = sepadata->maxslack;
5266 
5267  /* check if solving was successful and get solutions */
5268  subscipstage = SCIPgetStage(auxipdata->subscip);
5269  if( subscipstage == SCIP_STAGE_SOLVING || subscipstage == SCIP_STAGE_SOLVED )
5270  *nsols = SCIPgetNSols(auxipdata->subscip);
5271  else
5272  *nsols = 0;
5273  if( *nsols > 0 )
5274  {
5275  *sols = SCIPgetSols(auxipdata->subscip);
5276  /* check if only the best solution should be used */
5277  if( !sepadata->subscipuseallsols )
5278  *nsols = 1;
5279  }
5280 
5281  /* check if proper a proper solution was found */
5282  if( sepadata->subscipobjective == 'v' )
5283  {
5284  for( i = 0 ; i < *nsols ; ++i)
5285  if( SCIPisGT(scip, SCIPgetSolOrigObj(auxipdata->subscip , (*sols)[i]), maxslack) )
5286  break;
5287  *nsols = i;
5288  }
5289  else
5290  {
5291  SCIP_Real z;
5292  SCIP_Real* viols;
5293  SCIP_SOL** propersols;
5294 
5295  SCIP_Bool swapped;
5296  SCIP_Real tempviol;
5297  SCIP_SOL* tempsol;
5298 
5299  int npropersols;
5300 
5301  SCIP_CALL(SCIPallocBufferArray(scip, &viols, *nsols));
5302  SCIP_CALL(SCIPallocMemoryArray(scip, &propersols, *nsols));
5303  npropersols = 0;
5304  for( i = 0 ; i < *nsols ; ++i)
5305  {
5306  z = 0.0;
5307  for( j = 0 ; j < auxipdata->m ; ++j)
5308  z += mod2data->slacks[mod2data->rowsind[j]]
5309  * SCIPgetSolVal(auxipdata->subscip, (*sols)[i], auxipdata->v[j]);
5310  for( j = 0 ; j < auxipdata->n ; ++j)
5311  z += mod2data->fracsol[mod2data->colsind[j]]
5312  * SCIPgetSolVal(auxipdata->subscip, (*sols)[i], auxipdata->y[j]);
5313 
5314  if( SCIPisLE(scip, z, maxslack) )
5315  {
5316  /* proper sol has been found */
5317  propersols[npropersols] = (*sols)[i];
5318  viols[npropersols] = z;
5319  npropersols++;
5320  }
5321  }
5322 
5323 
5324  swapped = TRUE;
5325  for( i = 1 ; i < npropersols && swapped; ++i)
5326  {
5327  swapped = FALSE;
5328  for( j = 0 ; j < npropersols - i ; ++j)
5329  {
5330  if( viols[j] > viols[j+1] )
5331  {
5332  tempviol = viols[j+1];
5333  viols[j+1] = viols[j];
5334  viols[j] = tempviol;
5335  tempsol = propersols[j+1];
5336  propersols[j+1] = propersols[j];
5337  propersols[j] = tempsol;
5338  swapped = TRUE;
5339  }
5340  }
5341  }
5342 
5343  *sols = propersols;
5344  *nsols = npropersols;
5345  SCIPfreeBufferArray(scip, &viols);
5346 
5347  }
5348 
5349  return SCIP_OKAY;
5350 }
5351 
5352 
5353 
5354 
5355 /** determines the weightvector for a single row */
5356 static
5358  SCIP* scip, /**< SCIP data structure */
5359  SCIP_SEPADATA* sepadata, /**< separator data */
5360  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
5361  int rowsindex, /**< lpdata->rows index */
5362  int rrowsindex, /**< "subproblem"->rrows index */
5363  SCIP_Real** weights /**< pointer to store the weight vector */
5364  )
5365 { /*lint --e{438}*/
5367  assert(scip != NULL);
5368  assert(lpdata != NULL);
5369  assert(lpdata->nrows > 0);
5370  assert(0 <= rowsindex);
5371  assert(rowsindex < lpdata->nrows);
5372  assert(lpdata->rrowsindexofleftrow[rowsindex] == rrowsindex
5373  || lpdata->rrowsindexofrightrow[rowsindex] == rrowsindex);
5374  assert(weights != NULL);
5375  assert(*weights == NULL);
5376 
5377 
5378  /* allocate temporary memory */
5379  SCIP_CALL(SCIPallocMemoryArray(scip, weights, lpdata->nrows));
5380 
5381  /* initialize */
5382  BMSclearMemoryArray(*weights, lpdata->nrows);
5383 
5384  /* determine row weights */
5385  if( lpdata->rrowsindexofleftrow[rowsindex] == rrowsindex )
5386  (*weights)[rowsindex] = lpdata->intscalarsleftrow[rowsindex] * (-0.5);
5387  else
5388  (*weights)[rowsindex] = lpdata->intscalarsrightrow[rowsindex] * 0.5;
5389 
5390  if( SCIProwGetNLPNonz(lpdata->rows[rowsindex]) >= sepadata->maxnnonz )
5391  {
5392  SCIPfreeMemoryArray(scip, weights);
5393  weights = NULL;
5394  }
5395 
5396  return SCIP_OKAY;
5397 }
5398 
5399 
5400 /** gets the subset of rows that should be combined to a violated zerohalf cut */
5401 static
5403  SCIP* scip, /**< SCIP data structure */
5404  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
5405  ZEROHALF_AUXIPDATA* auxipdata, /**< auxiliary IP data */
5406  SCIP_SOL* solution, /**< considered solution */
5407  BITARRAY* rrowsincut, /**< pointer to store the subset of rows as bitarray (length: number of relevant rows) */
5408  int* nrrowsincut /**< number of combined relevant rows */
5409  )
5410 {
5411  int i;
5412 
5413  assert(scip != NULL);
5414  assert(mod2data != NULL);
5415  assert(mod2data->nrowsind > 0);
5416  assert(auxipdata != NULL);
5417  assert(auxipdata->subscip != NULL);
5418  assert(auxipdata->v != NULL);
5419  assert(solution != NULL);
5420  assert(rrowsincut != NULL);
5421  assert(*rrowsincut == NULL);
5422  assert(nrrowsincut != NULL);
5423 
5424 
5425  /* allocate and initialize temporary memory for calculating the symmetric difference */
5426  SCIP_CALL(SCIPallocMemoryArray(scip, rrowsincut, mod2data->rowaggregationsbitarraysize));
5427  BITARRAYCLEAR(*rrowsincut, mod2data->rowaggregationsbitarraysize);
5428 
5429  *nrrowsincut = 0;
5430 
5431  /* calculate symmetric difference of rrowsincut and specific rowaggregations */
5432  for( i = 0 ; i < mod2data->nrowsind ; ++i)
5433  if( auxipdata->v[i] != NULL )
5434  if( !SCIPisZero(scip, SCIPgetSolVal(auxipdata->subscip, solution, auxipdata->v[i])) )
5435  {
5436  BITARRAYSXOR(mod2data->rowaggregations[mod2data->rowsind[i]], (*rrowsincut) ,
5437  mod2data->rowaggregationsbitarraysize);
5438  (*nrrowsincut)++;
5439  }
5440 
5441  return SCIP_OKAY;
5442 }
5443 
5444 
5445 /** separates violated zerohalf cuts by solving an auxiliary IP. (exact method; exponential time) */
5446 static
5448  SCIP* scip, /**< SCIP data structure */
5449  SCIP_SEPA* sepa, /**< separator */
5450  SCIP_SEPADATA* sepadata, /**< separator data */
5451  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
5452  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
5453  char normtype, /**< SCIP normtype */
5454  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
5455  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
5456  SCIP_Bool setnodelimit, /**< should a node limit be set for solving the auxiliary IP? */
5457  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
5458  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
5459  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
5460  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
5461  SCIP_RESULT* result /**< pointer to SCIP result value of separation */
5462  )
5463 {
5464  ZEROHALF_AUXIPDATA* auxipdata;
5465  SCIP_SOL** sols;
5466  int nsols;
5467  int s;
5468  BITARRAY rrowsincut;
5469  int nrrowsincut;
5470  SCIP_Real* weights;
5471  int nrowsincut;
5472  SCIP_Bool cutoff = FALSE;
5473 
5474  assert(scip != NULL);
5475  assert(sepadata != NULL);
5476  assert(lpdata != NULL);
5477  assert(mod2data != NULL);
5478  assert(maxsepacuts >= 0);
5479  assert(maxcuts >= 0);
5480  assert(nsepacuts != NULL);
5481  assert(nzerohalfcuts != NULL);
5482  assert(zerohalfcuts != NULL);
5483  assert(*nsepacuts <= *nzerohalfcuts);
5484  assert(varsolvals != NULL);
5485  assert(result != NULL);
5486 
5487  assert(mod2data->relatedsubproblem != NULL);
5488  assert(mod2data->rows != NULL);
5489  assert(mod2data->rowaggregations != NULL);
5490  assert(mod2data->rhs != NULL);
5491  assert(mod2data->slacks != NULL);
5492  assert(mod2data->fracsol != NULL);
5493  assert(mod2data->rowsind != NULL);
5494  assert(mod2data->colsind != NULL);
5495 
5496 
5497  /* check if( A mod 2, b mod 2) is empty */
5498  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 )
5499  return SCIP_OKAY;
5500 
5501  /* check if enough cuts have been found */
5502  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
5503  return SCIP_OKAY;
5504 
5505  /* allocate temporary memory for subscip data structure */
5506  SCIP_CALL(ZerohalfAuxIPDataCreate(scip, &auxipdata));
5507 
5508  /* create subscip */
5509  SCIP_CALL(createSubscip(scip, sepadata, lpdata, mod2data, auxipdata, setnodelimit));
5510 
5511  /* abort if subscip was not created */
5512  if( auxipdata->subscip == NULL )
5513  {
5514  SCIP_CALL(ZerohalfAuxIPDataFree(scip, &auxipdata));
5515  return SCIP_OKAY;
5516  }
5517 
5518  /* solve subscip and get solutions yielding a zerohalf cut with violation >= minviolation */
5519  sols = NULL;
5520  nsols = 0;
5521  SCIP_CALL(solveSubscip(scip, sepadata, mod2data, auxipdata, &sols, &nsols));
5522 
5523 
5524  /* process solutions */
5525  for( s = 0; s < nsols ; ++s)
5526  {
5527  /* check if enough cuts have been found */
5528  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
5529  break;
5530 
5531  /* determine rrows of the related subproblem that have to be combined */
5532  rrowsincut = NULL;
5533  SCIP_CALL(getBitarrayOfSelectedRows(scip, mod2data, auxipdata, sols[s],
5534  &rrowsincut, &nrrowsincut));
5535  assert(nrrowsincut > 0);
5536 
5537  /* calculate rows zerohalf weightvector */
5538  weights = NULL;
5540  mod2data, rrowsincut, &weights, &nrowsincut));
5541  if ( weights == NULL )
5542  {
5543  SCIPfreeMemoryArray(scip, &rrowsincut);
5544  continue;
5545  }
5546  assert(nrowsincut > 0);
5547 
5548 
5549 #ifdef SCIP_DEBUG
5550  SCIP_CALL( debugPrintLPRowsAndCols(scip, lpdata) );
5551  SCIPdebugMessage("\n");
5552  debugPrintSubLpData(scip, lpdata, mod2data->relatedsubproblem);
5553  debugPrintMod2Data(scip, lpdata, mod2data, TRUE);
5554  SCIPdebugMessage("\n");
5555  SCIP_CALL( SCIPprintOrigProblem(auxipdata->subscip, NULL, NULL, TRUE) );
5556  SCIPdebugMessage("\n");
5557  SCIP_CALL( SCIPprintBestSol(auxipdata->subscip, NULL , FALSE) );
5558 #endif
5559 
5560  /* create zerohalf cut */
5561  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
5562  mod2data->relatedsubproblem, mod2data, nrrowsincut, nrowsincut, AUXIP));
5564  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
5565 
5566  if ( cutoff )
5567  *result = SCIP_CUTOFF;
5568  else
5569  {
5570  /* add cut */
5571  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
5572  (*nzerohalfcuts)++;
5573  }
5574 
5575  /* free temporary memory */
5576  SCIPfreeMemoryArray(scip, &weights);
5577  SCIPfreeMemoryArray(scip, &rrowsincut);
5578 
5579  if ( cutoff )
5580  break;
5581  }
5582 
5583  /* free temporary memory */
5584  if( sepadata->subscipobjective != 'v' )
5585  {
5586  SCIPfreeMemoryArray(scip, &sols);
5587  }
5588  SCIP_CALL(ZerohalfAuxIPDataFree(scip, &auxipdata));
5589 
5590  return SCIP_OKAY;
5591 }
5592 
5593 
5594 /** calculates the inner product of mod2data->row and the LP solution */
5595 static
5597  SCIP* scip, /**< SCIP data structure */
5598  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
5599  BITARRAY row, /**< considered mod2data->row */
5600  SCIP_Real maxinnerproduct, /**< calculation is aborted if innerproduct >= maxinnerproduct */
5601  SCIP_Real* innerproduct /**< pointer to store the inner product */
5602  )
5603 {
5604  int c;
5605  int rcolindex;
5606 
5607  assert(scip != NULL);
5608  assert(mod2data != NULL);
5609  assert(row != NULL);
5610  assert(maxinnerproduct >= 0);
5611  assert(innerproduct != NULL);
5612 
5613 
5614  *innerproduct = 0.0;
5615 
5616  /* check if( A mod 2, b mod 2) is empty */
5617  if( mod2data->nrows == 0 || mod2data->nrowsind == 0
5618  || mod2data->ncolsind == 0 )
5619  return SCIP_OKAY;
5620 
5621  /* calculate the inner product of rows[rowsindex] and fracsol */
5622  for( c = 0 ; c < mod2data->ncolsind ; ++c)
5623  {
5624  rcolindex = mod2data->colsind[c];
5625  if( BITARRAYBITISSET(row, rcolindex) ) /*lint !e701*/
5626  *innerproduct += mod2data->fracsol[rcolindex];
5627  if( SCIPisGT(scip, *innerproduct, maxinnerproduct) )
5628  break;
5629  }
5630 
5631  return SCIP_OKAY;
5632 }
5633 
5634 
5635 /** separate violated zerohalf cuts by enumerating possible row combinations. (heuristic; polynomial time) */
5636 static
5638  SCIP* scip, /**< SCIP data structure */
5639  SCIP_SEPA* sepa, /**< separator */
5640  SCIP_SEPADATA* sepadata, /**< separator data */
5641  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
5642  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
5643  char normtype, /**< SCIP normtype */
5644  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
5645  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
5646  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
5647  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
5648  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
5649  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
5650  SCIP_RESULT* result, /**< pointer to SCIP result value of separation */
5651  int maxncombinedrows /**< maximal number of combined rows; currently only 1 or 2 is supported */
5652  )
5653 {
5654  int first;
5655  int last;
5656  int temp;
5657  SCIP_Real minslackoddrhsrows;
5658  int ncombinedrows;
5659  int noddrhsrows;
5660  int r1;
5661  int r2;
5662  BITARRAY combinedrow;
5663  BITARRAY rrowsincut;
5664  SCIP_Real roundingdownweakening;
5665  SCIP_Real slack1;
5666  SCIP_Real slack2;
5667  int i;
5668  int j;
5669  SCIP_Real* weights;
5670  int nrowsincut;
5671  SCIP_Bool cutoff = FALSE;
5672 
5673  assert(scip != NULL);
5674  assert(sepadata != NULL);
5675  assert(lpdata != NULL);
5676  assert(mod2data != NULL);
5677  assert(maxsepacuts >= 0);
5678  assert(maxcuts >= 0);
5679  assert(nsepacuts != NULL);
5680  assert(nzerohalfcuts != NULL);
5681  assert(zerohalfcuts != NULL);
5682  assert(*nsepacuts <= *nzerohalfcuts);
5683  assert(varsolvals != NULL);
5684  assert(result != NULL);
5685  assert(maxncombinedrows >= 1);
5686 
5687  assert(mod2data->relatedsubproblem != NULL);
5688  assert(mod2data->rows != NULL);
5689  assert(mod2data->rowaggregations != NULL);
5690  assert(mod2data->rhs != NULL);
5691  assert(mod2data->slacks != NULL);
5692  assert(mod2data->fracsol != NULL);
5693  assert(mod2data->rowsind != NULL);
5694  assert(mod2data->colsind != NULL);
5695 
5696 
5697  /* check if( A mod 2, b mod 2) is empty */
5698  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 )
5699  return SCIP_OKAY;
5700 
5701  /* check if enough cuts have been found */
5702  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
5703  return SCIP_OKAY;
5704 
5705 
5706  /* partition rows into odd-rhs-rows and even-rhs-rows */
5707  first = 0;
5708  last = mod2data->nrowsind - 1;
5709  while(first < last)
5710  {
5711  if( !mod2data->rhs[mod2data->rowsind[first]] )
5712  {
5713  temp = mod2data->rowsind[first];
5714  mod2data->rowsind[first] = mod2data->rowsind[last];
5715  mod2data->rowsind[last] = temp;
5716  --last;
5717  }
5718  else
5719  ++first;
5720  }
5721  noddrhsrows = first + (mod2data->rhs[mod2data->rowsind[first]] ? 1 : 0);
5722 
5723  /* check if odd rows exists */
5724  if( noddrhsrows == 0 )
5725  return SCIP_OKAY;
5726 
5727  /* allocate and initialize temporary memory for calculating the symmetric difference */
5728  combinedrow = NULL;
5729  rrowsincut = NULL;
5730  if( maxncombinedrows > 1 )
5731  {
5732  SCIP_CALL(SCIPallocBufferArray(scip, &combinedrow, mod2data->rowsbitarraysize));
5733  SCIP_CALL(SCIPallocBufferArray(scip, &rrowsincut, mod2data->rowaggregationsbitarraysize));
5734  BITARRAYCLEAR(rrowsincut, mod2data->rowaggregationsbitarraysize);
5735  }
5736 
5737  /* sort each partition by nondecreasing slacks */
5738  assert(noddrhsrows >= 0);
5739  SCIPsortInd( mod2data->rowsind , compRealNonDecreasing , (void*) mod2data->slacks , noddrhsrows );
5740 
5741  if( noddrhsrows < mod2data->nrowsind )
5742  {
5743  SCIPsortInd( mod2data->rowsind + noddrhsrows , compRealNonDecreasing , (void*) mod2data->slacks , mod2data->nrowsind - noddrhsrows );
5744  }
5745 
5746  minslackoddrhsrows = mod2data->slacks[mod2data->rowsind[0]];
5747 
5748  if( SCIPisLE(scip, minslackoddrhsrows, sepadata->maxslack) )
5749  {
5750  for( ncombinedrows = 1 ; ncombinedrows <= maxncombinedrows ; ++ncombinedrows )
5751  {
5752  switch( ncombinedrows )
5753  {
5754  case 1:
5755  /* check all rows r1 with rhs(r1) odd */
5756  for( i = 0 ; i < noddrhsrows ; ++i)
5757  {
5758  r1 = mod2data->rowsind[i];
5759  assert(mod2data->rhs[r1]);
5760  if( *nzerohalfcuts == maxcuts || *nsepacuts == maxsepacuts )
5761  break;
5762  slack1 = mod2data->slacks[r1];
5763  if( SCIPisGT(scip, slack1, sepadata->maxslack) )
5764  break; /* because rowsind is sorted */
5765  SCIP_CALL(calcInnerProductOfRowAndFracsol(scip, mod2data, mod2data->rows[r1],
5766  sepadata->maxslack, &roundingdownweakening));
5767  if( SCIPisLE(scip, roundingdownweakening + slack1, sepadata->maxslack) )
5768  {
5769  /* a violated zerohalf cut has been found */
5770 
5771  /* calculate rows zerohalf weightvector */
5772  weights = NULL;
5774  mod2data, mod2data->rowaggregations[r1], &weights, &nrowsincut));
5775  if( weights == NULL )
5776  {
5777  continue;
5778  }
5779  assert(nrowsincut > 0);
5780 
5781  /* create zerohalf cut */
5782  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
5783  mod2data->relatedsubproblem, mod2data, 2, nrowsincut, HEURISTICSENUM));
5785  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
5786 
5787  if ( cutoff )
5788  *result = SCIP_CUTOFF;
5789  else
5790  {
5791  /* add cut */
5792  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
5793  (*nzerohalfcuts)++;
5794  }
5795 
5796  /* free temporary memory */
5797  SCIPfreeMemoryArray(scip, &weights);
5798  }
5799  }
5800  break;
5801  case 2:
5802  assert(combinedrow != NULL);
5803  assert(rrowsincut != NULL);
5804  if( noddrhsrows == mod2data->nrowsind )
5805  break;
5806  if( mod2data->nrowsind < 2 )
5807  break;
5808 
5809  /* check all pairs (r1,r2) with rhs(r1) odd and rhs(r1) even */
5810  for( i = 0 ; i < noddrhsrows ; ++i)
5811  {
5812  r1 = mod2data->rowsind[i];
5813  assert(mod2data->rhs[r1]);
5814  if( *nzerohalfcuts == maxcuts || *nsepacuts == maxsepacuts )
5815  break;
5816  slack1 = mod2data->slacks[r1];
5817  if( SCIPisGT(scip, slack1, sepadata->maxslack) )
5818  break; /* because rowsind_odd is sorted */
5819 
5820  for( j = noddrhsrows ; j < mod2data->ncolsind ; ++j)
5821  {
5822  r2 = mod2data->rowsind[j];
5823  assert(!mod2data->rhs[r2]);
5824  if( *nzerohalfcuts == maxcuts || *nsepacuts == maxsepacuts )
5825  break;
5826  slack2 = mod2data->slacks[r2];
5827  if( SCIPisGT(scip, slack1 + slack2, sepadata->maxslack) )
5828  break; /* because rowsind_even is sorted */
5829  BMScopyMemoryArray(combinedrow, mod2data->rows[r1], mod2data->rowsbitarraysize);
5830  BITARRAYSXOR(mod2data->rows[r2], combinedrow, mod2data->rowsbitarraysize);
5831  SCIP_CALL(calcInnerProductOfRowAndFracsol(scip, mod2data, combinedrow,
5832  sepadata->maxslack, &roundingdownweakening));
5833  if( SCIPisLE(scip, roundingdownweakening + slack1 + slack2, sepadata->maxslack) )
5834  {
5835  /* a violated zerohalf cut has been found */
5836 
5837  /* determine rrows of the related subproblem that have to be combined */
5838  BMScopyMemoryArray(rrowsincut, mod2data->rowaggregations[r1],
5839  mod2data->rowaggregationsbitarraysize);
5840  BITARRAYSXOR(mod2data->rowaggregations[r2], rrowsincut,
5841  mod2data->rowaggregationsbitarraysize);
5842 
5843  /* calculate rows zerohalf weightvector */
5844  weights = NULL;
5846  mod2data, rrowsincut, &weights, &nrowsincut));
5847  if ( weights == NULL )
5848  {
5849  continue;
5850  }
5851  assert(nrowsincut > 0);
5852 
5853  /* create zerohalf cut */
5854  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
5855  mod2data->relatedsubproblem, mod2data, 2, nrowsincut, HEURISTICSENUM));
5857  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
5858 
5859  if ( cutoff )
5860  *result = SCIP_CUTOFF;
5861  else
5862  {
5863  /* add cut */
5864  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
5865  (*nzerohalfcuts)++;
5866  }
5867 
5868  /* free temporary memory */
5869  SCIPfreeMemoryArray(scip, &weights);
5870  }
5871  }
5872  }
5873  break;
5874  default:
5875  SCIPerrorMessage("invalid ncombinedrows '%d'\n", ncombinedrows);
5876  return SCIP_INVALIDDATA;
5877  }
5878 
5879  if ( cutoff )
5880  break;
5881  }
5882  }
5883 
5884  /* free temporary memory */
5885  if( rrowsincut != NULL )
5886  {
5887  SCIPfreeBufferArray(scip, &rrowsincut);
5888  }
5889  if( combinedrow != NULL )
5890  {
5891  SCIPfreeBufferArray(scip, &combinedrow);
5892  }
5893  return SCIP_OKAY;
5894 }
5895 
5896 
5897 #if 0
5898 /** prints a node of the auxiliary graph */
5899 static
5900 void debugPrintAuxGraphNode(
5901  ZEROHALF_AUXGRAPH_NODE* node /**< node to be printed */
5902  )
5903 {
5904  int i;
5905 
5906  assert(node != NULL);
5907 
5908  SCIPdebugMessage("\nnode: %p\n", node);
5909  for( i = 0 ; i < node->nneighbors ; ++i)
5910  {
5911  SCIPdebugMessage(" neighbor %4d: %p weight: %6f rrow: %4d\n",
5912  i, node->neighbors[i], node->edgeweights[i], node->relatedrows[i]);
5913  }
5914  SCIPdebugMessage(" nneighbors: %d distance: %6f previous: %p\n",
5915  node->nneighbors, node->distance, node->previous);
5916 }
5917 #endif
5918 
5919 
5920 /** adds an edge (and its "copy" w.r.t. the node copies) to the auxiliary graph */
5921 static
5923  SCIP* scip, /**< SCIP data structure */
5924  ZEROHALF_AUXGRAPH* graph, /**< auxiliary graph */
5925  int node1index, /**< start node of edge */
5926  int node2index, /**< end node of edge */
5927  SCIP_Bool isodd, /**< is the rhs value of the corresponding mod2data->row odd? */
5928  SCIP_Real weight, /**< weight of the edge */
5929  int relatedrow /**< corresponding mod2data->row */
5930  )
5932  ZEROHALF_AUXGRAPH_NODE* node1;
5933  ZEROHALF_AUXGRAPH_NODE* node2;
5934  ZEROHALF_AUXGRAPH_NODE* node1copy;
5935  ZEROHALF_AUXGRAPH_NODE* node2copy;
5936  int n1;
5937  int n2;
5938 
5939  int maxnumberofneighbors;
5940 
5941  assert(scip != NULL);
5942  assert(graph != NULL);
5943  assert(node1index >= 0);
5944  assert(node1index < graph->nnodes);
5945  assert(node2index >= 0);
5946  assert(node2index < graph->nnodes);
5947  assert(!SCIPisNegative(scip, weight));
5948 
5949  maxnumberofneighbors = 2 * graph->nnodes - 2;
5950 
5951  if( isodd )
5952  {
5953  node1 = graph->nodes[node1index];
5954  node2 = graph->nodecopies[node2index];
5955  node1copy = graph->nodecopies[node1index];
5956  node2copy = graph->nodes[node2index];
5957  }
5958  else
5959  {
5960  node1 = graph->nodes[node1index];
5961  node2 = graph->nodes[node2index];
5962  node1copy = graph->nodecopies[node1index];
5963  node2copy = graph->nodecopies[node2index];
5964  }
5965 
5966  if( node1->nneighbors == 0 )
5967  {
5968  assert(maxnumberofneighbors > 0);
5969  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1->neighbors), maxnumberofneighbors));
5970  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1->edgeweights), maxnumberofneighbors));
5971  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1->relatedrows), maxnumberofneighbors));
5972 
5973  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1copy->neighbors), maxnumberofneighbors));
5974  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1copy->edgeweights), maxnumberofneighbors));
5975  SCIP_CALL(SCIPallocMemoryArray(scip, &(node1copy->relatedrows), maxnumberofneighbors));
5976  }
5977 
5978  if( node2->nneighbors == 0 )
5979  {
5980  assert(maxnumberofneighbors > 0);
5981  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2->neighbors), maxnumberofneighbors));
5982  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2->edgeweights), maxnumberofneighbors));
5983  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2->relatedrows), maxnumberofneighbors));
5984 
5985  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2copy->neighbors), maxnumberofneighbors));
5986  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2copy->edgeweights), maxnumberofneighbors));
5987  SCIP_CALL(SCIPallocMemoryArray(scip, &(node2copy->relatedrows), maxnumberofneighbors));
5988  }
5989 
5990  n2 = node2->nneighbors;
5991  for( n1 = 0 ; n1 < node1->nneighbors ; ++n1)
5992  if( node1->neighbors[n1] == node2 )
5993  break;
5994  if( n1 < node1->nneighbors)
5995  for( n2 = 0 ; n2 < node2->nneighbors ; ++n2)
5996  if( node2->neighbors[n2] == node1 )
5997  break;
5998  if( n1 < node1->nneighbors )
5999  {
6000  /* if node2 is neighbor of node1, then node1 is neighbor of node2 */
6001  assert(node1->neighbors[n1] == node2);
6002  assert(n2 < node2->nneighbors);
6003  assert(node2->neighbors[n2] == node1);
6004  assert(node1->edgeweights[n1] == node2->edgeweights[n2]); /*lint !e777*/
6005  }
6006 
6007  if( n1 == node1->nneighbors || SCIPisLT(scip, weight, node1->edgeweights[n1]) )
6008  {
6009  node1->neighbors[n1] = node2;
6010  node1->edgeweights[n1] = weight;
6011  node1->relatedrows[n1] = relatedrow;
6012  node1->nneighbors++;
6013 
6014  node2->neighbors[n2] = node1;
6015  node2->edgeweights[n2] = weight;
6016  node2->relatedrows[n2] = relatedrow;
6017  node2->nneighbors++;
6018 
6019  node1copy->neighbors[n1] = node2copy;
6020  node1copy->edgeweights[n1] = weight;
6021  node1copy->relatedrows[n1] = relatedrow;
6022  node1copy->nneighbors++;
6023 
6024  node2copy->neighbors[n2] = node1copy;
6025  node2copy->edgeweights[n2] = weight;
6026  node2copy->relatedrows[n2] = relatedrow;
6027  node2copy->nneighbors++;
6028  }
6029 
6030  return SCIP_OKAY;
6031 }
6032 
6033 
6034 /** Dijkstra's shortest path algorithm. Calculates the shortest path between
6035  sourcenode and targetnode. The calculation is aborted if the shortest path
6036  cannot be shorter than maxdistance */
6037 static
6039  SCIP* scip, /**< SCIP data structure */
6040  ZEROHALF_AUXGRAPH* graph, /**< auxiliary graph */
6041  ZEROHALF_AUXGRAPH_NODE* sourcenode, /**< start node */
6042  ZEROHALF_AUXGRAPH_NODE* targetnode, /**< end node */
6043  SCIP_Real maxdistance /**< calculation will be aborted if a proof is found that no shortest path with
6044  * length less than maxdistance exists */
6045  )
6046 {
6047  ZEROHALF_AUXGRAPH_NODE** unprocessednodes;
6048  int nunprocessednodes;
6049  int u;
6050  int v;
6051  int n;
6052  SCIP_Real mindistance;
6053  SCIP_Real newdistance;
6054  ZEROHALF_AUXGRAPH_NODE* currentnode;
6055 
6056 
6057  assert(scip != NULL);
6058  assert(graph != NULL);
6059  assert(graph->nnodes > 0);
6060  assert(sourcenode != NULL);
6061  assert(targetnode != NULL);
6062  assert(maxdistance > 0.0);
6063  assert(maxdistance <= 1.0);
6064 
6065  /* allocate temporary memory */
6066  SCIP_CALL(SCIPallocBufferArray(scip, &unprocessednodes, 2 * graph->nnodes));
6067 
6068  /* initialize */
6069  nunprocessednodes = 0;
6070  mindistance = 1.0;
6071  for( v = 0; v < graph->nnodes ; ++v)
6072  {
6073  graph->nodes[v]->distance = 1.0;
6074  graph->nodes[v]->previous = NULL;
6075 
6076  graph->nodecopies[v]->distance = 1.0;
6077  graph->nodecopies[v]->previous = NULL;
6078 
6079  unprocessednodes[nunprocessednodes] = graph->nodes[v];
6080  ++nunprocessednodes;
6081  unprocessednodes[nunprocessednodes] = graph->nodecopies[v];
6082  ++nunprocessednodes;
6083  }
6084  sourcenode->distance = 0.0;
6085  sourcenode->previous = NULL;
6086 
6087  assert(nunprocessednodes == 2 * graph->nnodes);
6088  assert(nunprocessednodes > 0);
6089 
6090  /* for all nodes */
6091  while( nunprocessednodes > 0 )
6092  {
6093  /* get unprocessed node with minimum distance from sourcenode */
6094  u = 0;
6095  mindistance = unprocessednodes[0]->distance;
6096  for( v = 1 ; v < nunprocessednodes ; ++v)
6097  if( unprocessednodes[v]->distance < mindistance )
6098  {
6099  u = v;
6100  mindistance = unprocessednodes[v]->distance;
6101  }
6102  /* if mindistance is greater than maxdistance then abort dijkstra */
6103  if( SCIPisGT(scip, mindistance, maxdistance) )
6104  goto exitdijkstra;
6105  /* set minimum distance node as currentnode */
6106  currentnode = unprocessednodes[u];
6107  unprocessednodes[u] = unprocessednodes[nunprocessednodes-1];
6108  nunprocessednodes--;
6109 
6110  /* for all neighbors of currentnode */
6111  for( n = 0 ; n < currentnode->nneighbors ; ++n)
6112  {
6113  newdistance = currentnode->distance + currentnode->edgeweights[n];
6114  /* check if distance via currentnode is less than their actual distance */
6115  if( SCIPisLT(scip, newdistance , currentnode->neighbors[n]->distance) )
6116  {
6117  currentnode->neighbors[n]->distance = newdistance;
6118  currentnode->neighbors[n]->previous = currentnode;
6119  /* if neighbors is targetnode then abort dijkstra */
6120  if( currentnode->neighbors[n] == targetnode )
6121  goto exitdijkstra;
6122  }
6123  }
6124  }
6125 
6126  exitdijkstra:
6127  SCIPfreeBufferArray(scip, &unprocessednodes);
6128  return SCIP_OKAY;
6129 }
6130 
6131 
6132 /** separates violated zerohalf cuts by searching for minweight odd-valued
6133  cycles within an auxiliary graph. (exact method, but only applicable if
6134  each row contains at most two odd entries; polynomial time) */
6135 static
6137  SCIP* scip, /**< SCIP data structure */
6138  SCIP_SEPA* sepa, /**< separator */
6139  SCIP_SEPADATA* sepadata, /**< separator data */
6140  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
6141  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
6142  char normtype, /**< SCIP normtype */
6143  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
6144  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
6145  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
6146  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
6147  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
6148  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
6149  SCIP_RESULT* result, /**< pointer to SCIP result value of separation */
6150  SCIP_Bool* wrongstructure /**< pointer to store if there is a row with more than two odd entries */
6151  )
6152 {
6153  ZEROHALF_AUXGRAPH* auxgraph;
6154  int rowsindex;
6155  int i;
6156  int j;
6157  int k;
6158  int n;
6159  int q;
6160 
6161  SCIP_Real* weights;
6162  int nrowsincut;
6163  int nrrowsincut;
6164  BITARRAY rrowsincut;
6165  ZEROHALF_AUXGRAPH_NODE* node;
6166  SCIP_Bool cutoff = FALSE;
6167 
6168  assert(scip != NULL);
6169  assert(sepadata != NULL);
6170  assert(lpdata != NULL);
6171  assert(mod2data != NULL);
6172  assert(maxsepacuts >= 0);
6173  assert(maxcuts >= 0);
6174  assert(nsepacuts != NULL);
6175  assert(nzerohalfcuts != NULL);
6176  assert(zerohalfcuts != NULL);
6177  assert(*nsepacuts <= *nzerohalfcuts);
6178  assert(varsolvals != NULL);
6179  assert(result != NULL);
6180  assert(wrongstructure != NULL);
6181 
6182  *wrongstructure = FALSE;
6183 
6184  /* check if( A mod 2, b mod 2) is empty */
6185  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 )
6186  return SCIP_OKAY;
6187 
6188  /* check if enough cuts have been found */
6189  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
6190  return SCIP_OKAY;
6191 
6192  /* check if matrix has proper structure */
6193  if( !hasMatrixMax2EntriesPerRow(mod2data) )
6194  {
6195  *wrongstructure = TRUE;
6196  return SCIP_OKAY;
6197  }
6198 
6199  /* check if only one row exists */
6200  if( mod2data->nrowsind == 1 )
6201  {
6202  SCIP_CALL(separateByEnumerationHeuristics(scip, sepa, sepadata, lpdata, mod2data,
6203  normtype, maxsepacuts, maxcuts, nsepacuts, nzerohalfcuts, zerohalfcuts,
6204  varsolvals, result, 1));
6205  return SCIP_OKAY;
6206  }
6207 
6208 
6209  /* build auxiliary graph */
6210  SCIP_CALL(ZerohalfAuxGraphCreate(scip, &auxgraph));
6211 
6212  /* create nodes */
6213  auxgraph->nnodes = mod2data->ncolsind + 1;
6214  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxgraph->nodes), auxgraph->nnodes));
6215  SCIP_CALL(SCIPallocMemoryArray(scip, &(auxgraph->nodecopies), auxgraph->nnodes));
6216  q = auxgraph->nnodes - 1;
6217 
6218  for( j = 0 ; j < auxgraph->nnodes ; ++j)
6219  {
6220  SCIP_CALL(ZerohalfAuxGraphNodeCreate(scip, &(auxgraph->nodes[j])));
6221  SCIP_CALL(ZerohalfAuxGraphNodeCreate(scip, &(auxgraph->nodecopies[j])));
6222  }
6223  /* create edges */
6224  for( i = 0 ; i < mod2data->nrowsind ; ++i)
6225  {
6226  rowsindex = mod2data->rowsind[i];
6227  for( j = 0 ; j < mod2data->ncolsind; ++j)
6228  if( BITARRAYBITISSET(mod2data->rows[rowsindex], mod2data->colsind[j]) ) /*lint !e701*/
6229  break;
6230  for( k = j+1 ; k < mod2data->ncolsind; ++k)
6231  if( BITARRAYBITISSET(mod2data->rows[rowsindex], mod2data->colsind[k]) ) /*lint !e701*/
6232  break;
6233 
6234  /* check if row i is a zero row */
6235  if( j >= mod2data->ncolsind )
6236  {
6237  if( mod2data->rhs[rowsindex] )
6238  {
6239  if( SCIPisLE(scip, mod2data->slacks[rowsindex], sepadata->maxslack) )
6240  {
6241  /* violated {0,1/2} cut has been found */
6242  weights = NULL;
6243  nrrowsincut = 1;
6244  nrowsincut = 0;
6245  SCIP_CALL(getZerohalfWeightvectorFromSelectedRowsBitarray(scip, sepadata, lpdata, mod2data,
6246  mod2data->rowaggregations[rowsindex], &weights, &nrowsincut));
6247  if( weights == NULL )
6248  {
6249  continue;
6250  }
6251  assert(nrowsincut > 0);
6252 
6253  /* create zerohalf cut */
6254  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
6255  mod2data->relatedsubproblem, mod2data, nrrowsincut, nrowsincut, AUXGRAPH));
6257  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
6258 
6259  if ( cutoff )
6260  *result = SCIP_CUTOFF;
6261  else
6262  {
6263  /* add cut */
6264  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
6265  (*nzerohalfcuts)++;
6266  }
6267 
6268  /* free temporary memory */
6269  assert( weights != NULL );
6270  SCIPfreeMemoryArray(scip, &weights);
6271  weights = NULL;
6272 
6273  if ( cutoff )
6274  break;
6275  }
6276  }
6277  continue;
6278  }
6279  assert( ! cutoff );
6280 
6281  /* check if row i has only one entry */
6282  if( k >= mod2data->ncolsind )
6283  {
6284  /* add edges (j,q), (j',q') or (j,q'), (j',q) w.r.t. rhs_i mod 2 */
6285  SCIP_CALL(addEdgeToAuxGraph(scip, auxgraph, j, q,
6286  mod2data->rhs[rowsindex], mod2data->slacks[rowsindex], rowsindex));
6287  continue;
6288  }
6289 
6290  /* row i has two entries */
6291  /* add edges (j,k), (j',k') or (j,k'), (j',k) w.r.t. rhs_i mod 2 */
6292  SCIP_CALL(addEdgeToAuxGraph(scip, auxgraph, j, k,
6293  mod2data->rhs[rowsindex], mod2data->slacks[rowsindex], rowsindex));
6294 
6295  }
6296 
6297  if ( ! cutoff )
6298  {
6299  /* create edges (j,q) and (j',q') for all nodes j */
6300  for( n = 0 ; n < auxgraph->nnodes && n != q ; ++n)
6301  {
6302  SCIP_CALL(addEdgeToAuxGraph(scip, auxgraph, n, q,
6303  FALSE, mod2data->fracsol[mod2data->colsind[n]], -1));
6304  }
6305  }
6306  if( cutoff || auxgraph->nnodes == 0 )
6307  {
6308  /* free temporary memory */
6309  SCIP_CALL(ZerohalfAuxGraphFree(scip, &auxgraph));
6310  return SCIP_OKAY;
6311  }
6312 
6313  weights = NULL;
6314 
6315  /* calculate shortest (node_i, nodecopy_i)-paths using the dijkstra algorithm */
6316  for( n = 0 ; n < auxgraph->nnodes && n != q ; ++n)
6317  {
6318  SCIP_CALL(dijkstra(scip, auxgraph,
6319  auxgraph->nodes[n], auxgraph->nodecopies[n], sepadata->maxslack));
6320 
6321  if( SCIPisLE(scip, auxgraph->nodecopies[n]->distance, sepadata->maxslack) )
6322  {
6323  /* a violated {0,1/2} cut has been found */
6324 
6325  /* determine original rows that have to be combined */
6326  SCIP_CALL(SCIPallocBufferArray(scip, &rrowsincut, mod2data->rowaggregationsbitarraysize));
6327  BITARRAYCLEAR(rrowsincut, mod2data->rowaggregationsbitarraysize);
6328 
6329  nrrowsincut = 0;
6330  nrowsincut = 0;
6331  node = auxgraph->nodecopies[n];
6332  while( node->previous != NULL )
6333  {
6334  for( i = 0 ; i < node->nneighbors ; ++i)
6335  if( node->neighbors[i] == node->previous )
6336  break;
6337  assert(i < node->nneighbors);
6338  rowsindex = node->relatedrows[i];
6339  BITARRAYSXOR(mod2data->rowaggregations[rowsindex], rrowsincut ,
6340  mod2data->rowaggregationsbitarraysize);
6341  node = node->previous;
6342  ++nrrowsincut;
6343  }
6344 
6345  /* get {0,1/2}-weight vector */
6346  assert(weights == NULL);
6348  mod2data, rrowsincut, &weights, &nrowsincut));
6349  if( weights == NULL )
6350  {
6351  SCIPfreeBufferArray(scip, &rrowsincut);
6352  continue;
6353  }
6354  assert(nrowsincut > 0);
6355 
6356  /* create zerohalf cut */
6357  SCIP_CALL(ZerohalfCutDataCreate(scip, &(zerohalfcuts[*nzerohalfcuts]),
6358  mod2data->relatedsubproblem, mod2data, nrrowsincut, nrowsincut, AUXGRAPH));
6360  lpdata, weights, normtype, *nzerohalfcuts, varsolvals, zerohalfcuts[*nzerohalfcuts], &cutoff));
6361 
6362  if ( cutoff )
6363  *result = SCIP_CUTOFF;
6364  else
6365  {
6366  /* add cut */
6367  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[*nzerohalfcuts], nsepacuts, result) );
6368  (*nzerohalfcuts)++;
6369  }
6370 
6371  /* free temporary memory */
6372  assert( weights != NULL );
6373  SCIPfreeMemoryArray(scip, &weights);
6374  weights = NULL;
6375 
6376  if( rrowsincut != NULL )
6377  {
6378  SCIPfreeBufferArray(scip, &rrowsincut);
6379  rrowsincut = NULL;
6380  }
6381  }
6382  if ( cutoff )
6383  break;
6384  }
6385 
6386  /* free temporary memory */
6387  SCIP_CALL(ZerohalfAuxGraphFree(scip, &auxgraph));
6388 
6389  return SCIP_OKAY;
6390 }
6391 
6392 
6393 
6394 /** separates violated zerohalf cuts using an extended Gaussian elimination. (heuristic; polynomial time) */
6395 static
6397  SCIP* scip, /**< SCIP data structure */
6398  SCIP_SEPA* sepa, /**< separator */
6399  SCIP_SEPADATA* sepadata, /**< separator data */
6400  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
6401  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
6402  char normtype, /**< SCIP normtype */
6403  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
6404  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
6405  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
6406  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
6407  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
6408  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
6409  SCIP_RESULT* result /**< pointer to SCIP result value of separation */
6410  )
6411 {
6412  int pivotrow;
6413  int pivotcol;
6414  int identsubmatrixsize;
6415  int rowsbind;
6416  BITARRAYBITMASKTYPE rowsbmask;
6417  int r;
6418  int temp;
6419 
6420  assert(scip != NULL);
6421  assert(sepadata != NULL);
6422  assert(lpdata != NULL);
6423  assert(mod2data != NULL);
6424  assert(maxsepacuts >= 0);
6425  assert(maxcuts >= 0);
6426  assert(nsepacuts != NULL);
6427  assert(nzerohalfcuts != NULL);
6428  assert(zerohalfcuts != NULL);
6429  assert(*nsepacuts <= *nzerohalfcuts);
6430  assert(varsolvals != NULL);
6431  assert(result != NULL);
6432 
6433 
6434  /* check if( A mod 2, b mod 2) is empty */
6435  if( mod2data->nrows == 0 || mod2data->nrowsind == 0 )
6436  return SCIP_OKAY;
6437 
6438  /* check if enough cuts have been found */
6439  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
6440  return SCIP_OKAY;
6441 
6442  if( mod2data->nrowsind == 1 )
6443  {
6444  SCIP_CALL(separateByEnumerationHeuristics(scip, sepa, sepadata, lpdata, mod2data,
6445  normtype, maxsepacuts, maxcuts, nsepacuts, nzerohalfcuts, zerohalfcuts,
6446  varsolvals, result, 1));
6447  return SCIP_OKAY;
6448  }
6449 
6450  identsubmatrixsize = 0;
6451 
6452  /* apply Gaussian elimination mod 2 */
6453 
6454  /* choose pivot col */
6455  for( pivotcol = 0; pivotcol < mod2data->ncolsind; ++pivotcol )
6456  {
6457  if( identsubmatrixsize == mod2data->nrowsind )
6458  break;
6459 
6460  /* sort row indices sets w.r.t. to their slack values NON-DECREASINGLY */
6461  SCIPsortInd(mod2data->rowsind + identsubmatrixsize , compRealNonDecreasing ,
6462  (void*) mod2data->slacks , mod2data->nrowsind - identsubmatrixsize);
6463 
6464  /* break if no unprocessed row with slack <= maxslack is left */
6465  if( SCIPisGT(scip, mod2data->slacks[mod2data->rowsind[identsubmatrixsize]], sepadata->maxslack) )
6466  break;
6467 
6468  /* determine pivot row */
6469  rowsbind = (int) GETBITARRAYINDEX(mod2data->colsind[pivotcol]);
6470  rowsbmask = GETBITARRAYMASK(mod2data->colsind[pivotcol]); /*lint !e701*/
6471  for( pivotrow = identsubmatrixsize ; pivotrow < mod2data->nrowsind ; ++pivotrow)
6472  if( mod2data->rows[mod2data->rowsind[pivotrow]][rowsbind] & rowsbmask )
6473  break;
6474  if( pivotrow == mod2data->nrowsind )
6475  continue;
6476 
6477  /* Gaussian elimination step */
6478  for( r = 0 ; r < mod2data->nrowsind
6479  && SCIPisLE(scip, mod2data->slacks[mod2data->rowsind[r]], sepadata->maxslack) ; ++r)
6480  {
6481  if( r == pivotrow )
6482  continue;
6483  if( mod2data->rows[mod2data->rowsind[r]][rowsbind] & rowsbmask )
6484  {
6485  /* add pivot row to r-th row */
6486  mod2data->slacks[mod2data->rowsind[r]] += mod2data->slacks[mod2data->rowsind[pivotrow]];
6487 
6488 #ifndef SCIP_DEBUG
6489  /* avoid expensive operations on rows with slack > maxslack */
6490  if( SCIPisLE(scip, mod2data->slacks[mod2data->rowsind[r]], sepadata->maxslack) )
6491 #endif
6492  {
6493  BITARRAYSXOR(mod2data->rows[mod2data->rowsind[pivotrow]],
6494  mod2data->rows[mod2data->rowsind[r]],mod2data->rowsbitarraysize);
6495  BITARRAYSXOR(mod2data->rowaggregations[mod2data->rowsind[pivotrow]],
6496  mod2data->rowaggregations[mod2data->rowsind[r]],mod2data->rowaggregationsbitarraysize);
6497  mod2data->rhs[mod2data->rowsind[r]] =
6498  XOR(mod2data->rhs[mod2data->rowsind[pivotrow]],mod2data->rhs[mod2data->rowsind[r]]);
6499  }
6500  }
6501  }
6502 
6503  /* swap index set positions */
6504  temp = mod2data->rowsind[pivotrow];
6505  mod2data->rowsind[pivotrow] = mod2data->rowsind[identsubmatrixsize];
6506  mod2data->rowsind[identsubmatrixsize] = temp;
6507  temp = mod2data->colsind[pivotcol];
6508  mod2data->colsind[pivotcol] = mod2data->colsind[identsubmatrixsize];
6509  mod2data->colsind[identsubmatrixsize] = temp;
6510 
6511  identsubmatrixsize++;
6512  }
6513 
6514  /* remove (generated) column singletons */
6515  SCIP_CALL(preprocessColumns(scip, sepadata, lpdata, mod2data,
6516  0, mod2data->ncolsind, FALSE, TRUE, TRUE));
6517 
6518  /* remove zero rows and rows with slack > maxslack */
6519  SCIP_CALL(preprocessRows(scip, sepadata, lpdata, mod2data,
6520  0, mod2data->nrowsind, TRUE, TRUE, FALSE));
6521 
6522  /* search for zerohalf cuts */
6523  SCIP_CALL(preprocessTrivialZerohalfCuts(scip, sepa, sepadata, lpdata, mod2data,
6524  0, mod2data->nrowsind, normtype, maxsepacuts, maxcuts, nsepacuts,
6525  nzerohalfcuts, zerohalfcuts, varsolvals, HEURISTICSGAUSS, result));
6526 
6527  return SCIP_OKAY;
6528 }
6529 
6530 
6531 /** processes subproblem (i.e. runs separation algorithms)*/
6532 static
6534  SCIP* scip, /**< SCIP data structure */
6535  SCIP_SEPA* sepa, /**< separator */
6536  SCIP_SEPADATA* sepadata, /**< separator data */
6537  ZEROHALF_LPDATA* lpdata, /**< data of current LP relaxation */
6538  ZEROHALF_MOD2DATA* mod2data, /**< considered (preprocessed) subproblem mod 2 */
6539  char normtype, /**< SCIP normtype */
6540  int maxsepacuts, /**< maximal number of zerohalf cuts separated per separation round */
6541  int maxcuts, /**< maximal number of zerohalf cuts found per separation round (incl. ineff. cuts) */
6542  int* nsepacuts, /**< pointer to store current number of separated zerohalf cuts */
6543  int* nzerohalfcuts, /**< pointer to store current number of found zerohalf cuts */
6544  ZEROHALF_CUTDATA** zerohalfcuts, /**< array to store found zerohalf cuts */
6545  SCIP_Real** varsolvals, /**< dense variable LP solution vector */
6546  SCIP_RESULT* result /**< pointer to SCIP result value of separation */
6547  )
6548 {
6549  char sepamethod;
6550  int i;
6551  SCIP_Bool stop;
6552 
6553  char sepaname[SCIP_MAXSTRLEN];
6554 #ifdef ZEROHALF__PRINT_STATISTICS
6555  int nsepacutsbefore;
6556  int nsepacutsinitial;
6557  int nzerohalfcutsbefore;
6558  int nzerohalfcutsinitial;
6559  SCIP_CLOCK* timer;
6560  SCIP_CLOCK* sepatimer;
6561 #endif
6562 
6563  int ncutsfoundbefore;
6564  SCIP_Bool wrongstructure;
6565 
6566  assert(scip != NULL);
6567  assert(sepadata != NULL);
6568  assert(lpdata != NULL);
6569  assert(mod2data != NULL);
6570  assert(maxsepacuts >= 0);
6571  assert(maxcuts >= 0);
6572  assert(result != NULL);
6573  assert(nsepacuts != NULL);
6574  assert(nzerohalfcuts != NULL);
6575  assert(zerohalfcuts != NULL);
6576  assert(*nsepacuts <= *nzerohalfcuts);
6577 
6578  assert(mod2data->relatedsubproblem != NULL);
6579  assert(mod2data->rows != NULL);
6580  assert(mod2data->rowaggregations != NULL);
6581  assert(mod2data->rhs != NULL);
6582  assert(mod2data->slacks != NULL);
6583  assert(mod2data->fracsol != NULL);
6584  assert(mod2data->nrows > 0);
6585  assert(mod2data->rowsind != NULL);
6586  assert(mod2data->colsind != NULL);
6587 
6588  sepadata->nsepamethods = (int) strlen(sepadata->sepamethods);
6589  if( sepadata->nsepamethods > 0 && sepadata->sepamethods[0] == '-' )
6590  sepadata->nsepamethods = 0;
6591 
6592  if( sepadata->nsepamethods == 0 )
6593  return SCIP_OKAY;
6594 
6595 
6596  /* statistics */
6597 #ifdef ZEROHALF__PRINT_STATISTICS
6598  if( sepadata->sepatimers == NULL )
6599  {
6600  SCIP_CALL( SCIPallocMemoryArray(scip, &(sepadata->sepatimers), sepadata->nsepamethods + 1) );
6601  for( i = 0 ; i < sepadata->nsepamethods + 1 ; ++i)
6602  {
6603  ZEROHALFcreateTimer((sepadata->sepatimers[i]));
6604  }
6605  SCIP_CALL( SCIPallocMemoryArray(scip, &(sepadata->nsepacutsalgo), sepadata->nsepamethods + 1) );
6606  SCIP_CALL( SCIPallocMemoryArray(scip, &(sepadata->nzerohalfcutsalgo), sepadata->nsepamethods + 1) );
6607  BMSclearMemoryArray(sepadata->nsepacutsalgo, sepadata->nsepamethods + 1);
6608  BMSclearMemoryArray(sepadata->nzerohalfcutsalgo, sepadata->nsepamethods + 1);
6609  }
6610 
6611  nsepacutsinitial = *nsepacuts;
6612  nzerohalfcutsinitial = *nzerohalfcuts;
6613 
6614  ZEROHALFstatisticsMessage("\n");
6615  ZEROHALFstatisticsMessage(" | -------------------------- subproblem ----\
6616 ---------- | - callback (algo) - | ----- callback ---- | --total-\n");
6617  ZEROHALFstatisticsMessage(" | nrowsind | ncolsind | nsepcuts | ncutsfnd \
6618 | time | nsepcuts | ncutsfnd | nsepcuts | ncutsfnd | time\n");
6619  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8.4f | %8s | %8s | %8d | %8d | %8.4f\n",
6620  "START PROCESSG", mod2data->nrowsind, mod2data->ncolsind,
6621  0, 0, 0.0, " ", " ", *nsepacuts, *nzerohalfcuts, ZEROHALFevalTimer(sepadata->sepatimers[sepadata->nsepamethods]));
6622 #endif
6623 
6624  if( mod2data->nrowsind == 0 || mod2data->ncolsind == 0 )
6625  return SCIP_OKAY;
6626 
6627 #ifdef ZEROHALF__PRINT_STATISTICS
6628  ZEROHALFcreateNewTimer(timer);
6629  ZEROHALFcreateNewTimer(sepatimer);
6630  ZEROHALFstartTimer(sepadata->sepatimers[sepadata->nsepamethods]);
6631  ZEROHALFstartTimer(timer);
6632 #endif
6633 
6634  stop = FALSE;
6635  for( i = 0 ; i < sepadata->nsepamethods && !stop; ++i)
6636  {
6637  /* statistics*/
6638 #ifdef ZEROHALF__PRINT_STATISTICS
6639  ZEROHALFstartTimer(sepatimer);
6640  ZEROHALFstartTimer(sepadata->sepatimers[i]);
6641  nsepacutsbefore = *nsepacuts;
6642  nzerohalfcutsbefore = *nzerohalfcuts;
6643 
6644  /* abort if enough cuts have already been found */
6645  if( *nsepacuts >= maxsepacuts || *nzerohalfcuts >= maxcuts )
6646  break;
6647  /* abort if matrix is empty */
6648  if( mod2data->nrowsind == 0 || mod2data->ncolsind == 0 )
6649  break;
6650 #endif
6651 
6652  /* process */
6653  sepamethod = sepadata->sepamethods[i];
6654 
6655  switch(sepamethod)
6656  {
6657  case STOPIFCUTWASFOUND:
6658  if( *nsepacuts > 0 )
6659  {
6660  stop = TRUE;
6661  }
6662  strncpy(sepaname,"nsepcuts>0 ?",SCIP_MAXSTRLEN);
6663  break;
6664  case SOLVEAUXSCIP:
6665  case SOLVEAUXSCIPEXACT:
6666  ncutsfoundbefore = *nzerohalfcuts;
6667  SCIP_CALL(separateBySolvingAuxIP(scip, sepa, sepadata, lpdata, mod2data, normtype,
6668  maxsepacuts, maxcuts, (sepamethod == SOLVEAUXSCIP),
6669  nsepacuts, nzerohalfcuts, zerohalfcuts, varsolvals, result));/*lint !e641*/
6670  strncpy(sepaname,"auxiliary ip",SCIP_MAXSTRLEN);
6671  if( *nzerohalfcuts == ncutsfoundbefore )
6672  {
6673  /* no violated cut has been found. hence a proof of non-existence is given */
6674  stop = TRUE;
6675  }
6676  break;
6677  case ENUMHEURNMAX1:
6678  SCIP_CALL(separateByEnumerationHeuristics(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts,
6679  maxcuts, nsepacuts, nzerohalfcuts, zerohalfcuts, varsolvals, result, 1));
6680  strncpy(sepaname,"enum k=1",SCIP_MAXSTRLEN);
6681  break;
6682  case ENUMHEURNMAX2:
6683  SCIP_CALL(separateByEnumerationHeuristics(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts,
6684  maxcuts, nsepacuts, nzerohalfcuts, zerohalfcuts, varsolvals, result, 2));
6685  strncpy(sepaname,"enum k=1..2",SCIP_MAXSTRLEN);
6686  break;
6687  case GAUSSHEUR:
6688  SCIP_CALL(separateByGaussHeuristics(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts, maxcuts,
6689  nsepacuts, nzerohalfcuts, zerohalfcuts, varsolvals, result));
6690  strncpy(sepaname,"Gauss heur",SCIP_MAXSTRLEN);
6691  break;
6692  case MAX2ODDENTRIESPERROW:
6693  ncutsfoundbefore = *nzerohalfcuts;
6694  SCIP_CALL(separateByAuxGraph(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts, maxcuts,
6695  nsepacuts, nzerohalfcuts, zerohalfcuts, varsolvals, result, &wrongstructure));
6696  strncpy(sepaname,"auxgraph",SCIP_MAXSTRLEN);
6697  if( ! wrongstructure )
6698  {
6699  if( *nzerohalfcuts == ncutsfoundbefore )
6700  {
6701  /* no violated cut has been found. hence a proof of non-existence is given */
6702  stop = TRUE;
6703  }
6704  }
6705  break;
6706  default:
6707  SCIPerrorMessage("invalid sepamethod '%c'\n", sepadata->sepamethods[i]);
6708  return SCIP_INVALIDDATA;
6709  }
6710 
6711 #ifdef ZEROHALF__PRINT_STATISTICS
6712  /* statistics */
6713  ZEROHALFstopTimer(sepadata->sepatimers[i]);
6714  ZEROHALFstopTimer(sepatimer);
6715  sepadata->nsepacutsalgo[i] += *nsepacuts - nsepacutsbefore;
6716  sepadata->nzerohalfcutsalgo[i] += *nzerohalfcuts - nzerohalfcutsbefore;
6717  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8.4f | %8d | %8d | %8d | %8d | %8.4f\n",
6718  sepaname, mod2data->nrowsind, mod2data->ncolsind,
6719  *nsepacuts - nsepacutsbefore, *nzerohalfcuts - nzerohalfcutsbefore,
6720  ZEROHALFevalTimer(sepatimer),
6721  sepadata->nsepacutsalgo[i], sepadata->nzerohalfcutsalgo[i],
6722  *nsepacuts, *nzerohalfcuts, ZEROHALFevalTimer(sepadata->sepatimers[i]));
6723  ZEROHALFresetTimer(sepatimer);
6724 #endif
6725  }
6726 
6727 #ifdef ZEROHALF__PRINT_STATISTICS
6728  /* statistics */
6729  ZEROHALFstopTimer(timer);
6730  ZEROHALFstatisticsMessage("%15s | %8d | %8d | %8d | %8d | %8.4f | %8s | %8s | %8d | %8d | %8.4f\n",
6731  "PROCESSED", mod2data->nrowsind, mod2data->ncolsind,
6732  *nsepacuts - nsepacutsinitial , *nzerohalfcuts - nzerohalfcutsinitial,
6733  ZEROHALFevalTimer(timer), " ", " ", *nsepacuts, *nzerohalfcuts,
6734  ZEROHALFevalTimer(sepadata->sepatimers[sepadata->nsepamethods]));
6735  ZEROHALFfreeTimer(timer);
6736  ZEROHALFfreeTimer(sepatimer);
6737  ZEROHALFstopTimer(sepadata->sepatimers[sepadata->nsepamethods]);
6738 #endif
6739 
6740  return SCIP_OKAY;
6741 }
6742 
6743 
6744 #ifdef ZEROHALF__PRINT_STATISTICS
6745 /** prints statistical information about the found zerohalfcuts as table */
6746 static
6747 void printZerohalfCutsStatistics(
6748  SCIP* scip, /**< SCIP data structure */
6749  ZEROHALF_CUTDATA** zerohalfcuts, /**< array of zerohalf cuts */
6750  int nzerohalfcuts, /**< number of zerohalf cuts */
6751  int* zerohalfcutsindices,/**< sorted index set (or NULL) */
6752  SCIP_Real* zerohalfcutsprios, /**< sorted priorities (or NULL) */
6753  SCIP_Real* zerohalfcutsminortho,/**< sorted minimal orthogonalities (or NULL) */
6754  int nsepacuts /**< number of separated zerohalf cuts */
6755  )
6756 {
6757  ZEROHALF_CUTDATA* cut;
6758  int si;
6759  int i;
6760 
6761  assert(scip != NULL);
6762  assert(zerohalfcuts != NULL);
6763  assert(nzerohalfcuts >= 0);
6764 
6765  ZEROHALFstatisticsMessage("\n");
6766  ZEROHALFstatisticsMessage(" NZEROHALFCUTS: %6d\n", nzerohalfcuts);
6767  ZEROHALFstatisticsMessage(" NSEPACUTS: %6d\n", nsepacuts);
6768 
6769  if( nzerohalfcuts == 0 )
6770  return;
6771 
6772  ZEROHALFstatisticsMessage("%15s | index | A | viol | efficacy | ef? \
6773 | minortho | #nonz | norm | #origrows | #preprows | by | priority\n", " ");
6774  for( i = 0 ; i < nzerohalfcuts ; ++i)
6775  {
6776  if( zerohalfcutsindices == NULL )
6777  si = i;
6778  else
6779  si = zerohalfcutsindices[i];
6780  assert(0 <= i);
6781  assert(i < nzerohalfcuts);
6782  cut = zerohalfcuts[si];
6783  ZEROHALFstatisticsMessage("%15s | %6d | %1s | %8f | %8f | %3s | %8f | %8d | %8.2f | %9d | %9d | %2s | %8.6f\n",
6784  "ZEROHALFCUT", si,
6785  cut->addedtolp ? "A" : "-",
6786  cut->violation, cut->efficacy,
6787  SCIPisEfficacious(scip, cut->efficacy) ? "yes" : " no",
6788  zerohalfcutsminortho != NULL ? zerohalfcutsminortho[i] : 0.0,
6789  cut->nnonz, cut->norm, cut->nrowsincut, cut->nrrowsincut,
6790  (cut->separatedby == AUXIP ? "IP" :
6791  (cut->separatedby == DECOMPOSITION ? "DC" :
6792  (cut->separatedby == PPZEROONEROW ? "PP" :
6793  (cut->separatedby == HEURISTICSENUM ? "HE" :
6794  (cut->separatedby == HEURISTICSGAUSS ? "HG" :
6795  (cut->separatedby == AUXGRAPH ? "2R" :
6796  "?"
6797  )))))),
6798  zerohalfcutsprios != NULL ? zerohalfcutsprios[i] : 0.0
6799  );
6800  }
6801 }
6802 #endif
6803 
6804 
6805 
6806 /* --------------------------------------------------------------------------------------------------------------------
6807  * callback methods of separator
6808  * -------------------------------------------------------------------------------------------------------------------- */
6809 
6810 
6811 /** copy method for separator plugins (called when SCIP copies plugins) */
6812 static
6813 SCIP_DECL_SEPACOPY(sepaCopyZerohalf)
6814 { /*lint --e{715}*/
6815  assert(scip != NULL);
6816  assert(sepa != NULL);
6817  assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
6818 
6819  /* call inclusion method of constraint handler */
6821 
6822  return SCIP_OKAY;
6823 }
6824 
6825 /** destructor of separator to free user data (called when SCIP is exiting) */
6826 static
6827 SCIP_DECL_SEPAFREE(sepaFreeZerohalf)
6828 {
6829  SCIP_SEPADATA* sepadata;
6830 
6831  assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
6832 
6833  /* free separator data */
6834  sepadata = SCIPsepaGetData(sepa);
6835  assert(sepadata != NULL);
6837  if( sepadata->pptimers != NULL )
6838  {
6839 #ifdef ZEROHALF__PRINT_STATISTICS
6840  int i;
6841 
6842  for( i = 0 ; i < sepadata->nppmethods + 1 ; ++i)
6843  {
6844  ZEROHALFfreeTimer((sepadata->pptimers[i]));
6845  }
6846 #endif
6847  SCIPfreeMemoryArray(scip, &(sepadata->pptimers));
6848  }
6849 
6850  if( sepadata->sepatimers != NULL )
6851  {
6852 #ifdef ZEROHALF__PRINT_STATISTICS
6853  int i;
6854 
6855  for( i = 0 ; i < sepadata->nsepamethods + 1 ; ++i)
6856  {
6857  ZEROHALFfreeTimer((sepadata->sepatimers[i]));
6858  }
6859 #endif
6860  SCIPfreeMemoryArray(scip, &(sepadata->sepatimers));
6861  }
6862 
6863 #ifdef ZEROHALF__PRINT_STATISTICS
6864  if( sepadata->dtimer != NULL )
6865  {
6866  ZEROHALFfreeTimer((sepadata->dtimer));
6867  }
6868 #endif
6869 
6870  if( sepadata->nsepacutsalgo != NULL )
6871  {
6872  SCIPfreeMemoryArray(scip, &(sepadata->nsepacutsalgo));
6873  }
6874  if( sepadata->nzerohalfcutsalgo != NULL )
6875  {
6876  SCIPfreeMemoryArray(scip, &(sepadata->nzerohalfcutsalgo));
6877  }
6878  if( sepadata->origrows != NULL )
6879  {
6880  SCIPfreeMemoryArray(scip, &(sepadata->origrows));
6881  }
6882  SCIPfreeMemory(scip, &sepadata);
6883  SCIPsepaSetData(sepa, NULL);
6884 
6885  return SCIP_OKAY;
6886 }
6887 
6888 
6889 /** LP solution separation method of separator */
6890 static
6891 SCIP_DECL_SEPAEXECLP(sepaExeclpZerohalf)
6892 {
6893  SCIP_SEPADATA* sepadata;
6894  ZEROHALF_LPDATA* lpdata;
6895  ZEROHALF_MOD2DATA* mod2data;
6896  ZEROHALF_CUTDATA** zerohalfcuts;
6897  SCIP_Real* varsolvals;
6898  SCIP_Real* subproblempriorities;
6899  int* sortedsubproblems;
6900  int ncalls;
6901  int depth;
6902  int maxsepacuts;
6903  int maxcuts;
6904  int nsepacuts;
6905  int nzerohalfcuts;
6906  int subproblemindex;
6907  int i;
6908  int j;
6909  char normtype;
6910  SCIP_Longint totalncalls;
6911  SCIP_Real nrcolsfactor;
6912  SCIP_Bool cutoff = FALSE;
6913 
6914  assert(sepa != NULL);
6915  assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
6916  assert(scip != NULL);
6917  assert(result != NULL);
6918 
6919  *result = SCIP_DIDNOTRUN;
6920  sepadata = SCIPsepaGetData(sepa);
6921  assert(sepadata != NULL);
6922  depth = SCIPgetDepth(scip);
6923  ncalls = SCIPsepaGetNCallsAtNode(sepa);
6924  totalncalls = SCIPsepaGetNCalls(sepa);
6925 
6926  /* only call separator, if we are not close to terminating */
6927  if( SCIPisStopped(scip) )
6928  return SCIP_OKAY;
6929 
6930  /* only call the {0,1/2}-cut separator a given number of times at all */
6931  if( sepadata->maxncalls > -1 && totalncalls > sepadata->maxncalls - 1 )
6932  return SCIP_OKAY;
6933 
6934  /* only call the {0,1/2}-cut separator a given number of times at each node */
6935  if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
6936  || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
6937  return SCIP_OKAY;
6938 
6939  /* only call separator if depth<=maxdepth or maxdepth unlimited */
6940  if( sepadata->maxdepth > -1 && depth > sepadata->maxdepth )
6941  return SCIP_OKAY;
6942 
6943  /* only call separator, if an optimal LP solution is at hand */
6945  return SCIP_OKAY;
6946 
6947  /* only call separator, if there are fractional variables */
6948  if( SCIPgetNLPBranchCands(scip) == 0 )
6949  return SCIP_OKAY;
6950 
6951  /* allocate temporary memory for LP data structures */
6952  SCIP_CALL(ZerohalfLPDataCreate(scip, &lpdata));
6953 
6954  /* get variables data */
6955  SCIP_CALL(SCIPgetVarsData(scip, &(lpdata->vars), &(lpdata->nvars), NULL, NULL, NULL, NULL));
6956 
6957  /* get LP data */
6958  SCIP_CALL(SCIPgetLPColsData(scip, &(lpdata->cols), &(lpdata->ncols)));
6959  SCIP_CALL(SCIPgetLPRowsData(scip, &(lpdata->rows), &(lpdata->nrows)));
6960  if( lpdata->ncols == 0 || lpdata->nrows == 0 )
6961  {
6962  SCIP_CALL(ZerohalfLPDataFree(scip, &lpdata));
6963  return SCIP_OKAY;
6964  }
6965 
6966  /* store original LP rows indices if necessary */
6967  if( sepadata->onlyorigrows && sepadata->origrows == NULL )
6968  {
6969  SCIP_Bool issorted;
6970  int temp;
6971 
6972  SCIP_CALL( SCIPallocMemoryArray(scip, &(sepadata->origrows), lpdata->nrows) );
6973  for( i = 0 ; i < lpdata->nrows ; ++i )
6974  sepadata->origrows[i] = SCIProwGetIndex(lpdata->rows[i]);
6975  sepadata->norigrows = lpdata->nrows;
6976 
6977  /* bubble sort indices (s.t. binary search can be used to find an index) */
6978  do
6979  {
6980  issorted = TRUE;
6981  for( i = 0 ; i < sepadata->norigrows - 1 ; ++i )
6982  {
6983  if( sepadata->origrows[i] > sepadata->origrows[i+1] )
6984  {
6985  temp = sepadata->origrows[i];
6986  sepadata->origrows[i] = sepadata->origrows[i+1];
6987  sepadata->origrows[i+1] = temp;
6988  issorted = FALSE;
6989  }
6990  }
6991  }
6992  while( !issorted );
6993  }
6994 
6995  /* get the maximal number of cuts allowed in a separation round */
6996  if( depth == 0 )
6997  {
6998  maxcuts = sepadata->maxcutsroot;
6999  maxsepacuts = MIN(maxcuts, sepadata->maxsepacutsroot);
7000  }
7001  else
7002  {
7003  maxcuts = sepadata->maxcuts;
7004  maxsepacuts = MIN(maxcuts, sepadata->maxsepacuts);
7005  }
7006 
7007  /* only call the {0,1/2}-cut separator if at least one cut is allowed in a separation round */
7008  if( maxsepacuts == 0 )
7009  {
7010  SCIP_CALL(ZerohalfLPDataFree(scip, &lpdata));
7011  return SCIP_OKAY;
7012  }
7013 
7014 
7015 #ifdef ZEROHALF__PRINT_STATISTICS
7016  ZEROHALFstatisticsMessage("= SEPA_ZEROHALF ================================================================\
7017 s=============================================\n");
7018 #endif
7019 
7020  /* allocate further temporary memory */
7021  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->intscalarsleftrow), lpdata->nrows));
7022  SCIP_CALL(SCIPallocMemoryArray(scip, &(lpdata->intscalarsrightrow), lpdata->nrows));
7023 
7024  /* initialize */
7025  BMSclearMemoryArray(lpdata->intscalarsleftrow, lpdata->nrows);
7026  BMSclearMemoryArray(lpdata->intscalarsrightrow, lpdata->nrows);
7027 
7028  *result = SCIP_DIDNOTFIND;
7029  sepadata->maxslack = 1.0 - 2.0 * sepadata->minviolation;
7030  nsepacuts = 0;
7031  nzerohalfcuts = 0;
7032  varsolvals = NULL;
7033  SCIP_CALL(SCIPgetCharParam(scip, "separating/efficacynorm", &normtype));
7034 
7035 #ifdef ZEROHALF__PRINT_STATISTICS
7036  if( sepadata->nsepamethods > 0 )
7037  {
7038  assert(sepadata->nsepacutsalgo != NULL);
7039  assert(sepadata->nzerohalfcutsalgo != NULL);
7040  BMSclearMemoryArray(sepadata->nsepacutsalgo, sepadata->nsepamethods + 1);
7041  BMSclearMemoryArray(sepadata->nzerohalfcutsalgo, sepadata->nsepamethods + 1);
7042  }
7043 #endif
7044 
7045  /* determine maximal number of nonzeros allowed in a zerohalf cut */
7046  sepadata->maxnnonz = 0;
7047  for( i = 0 ; i < lpdata->nrows ; i++ )
7048  {
7049  sepadata->maxnnonz += SCIProwGetNLPNonz(lpdata->rows[i]);
7050  }
7051  sepadata->maxnnonz = (int) floor( 10.0 * sepadata->maxnnonz / (double) lpdata->nrows);
7052  sepadata->maxnnonz = (int) floor(MIN(0.1 * lpdata->ncols, sepadata->maxnnonz)) + NNONZOFFSET;
7053 
7054  /* search for relevant columns */
7055  SCIP_CALL(getRelevantColumns(scip, lpdata));
7056  if( lpdata->subproblems[0]->nrcols == 0 )
7057  {
7058  SCIP_CALL(ZerohalfLPDataFree(scip, &lpdata));
7059  return SCIP_OKAY;
7060  }
7061 
7062  /* search for relevant rows */
7063  SCIP_CALL(getRelevantRows(scip, sepadata, lpdata));
7064  if( lpdata->subproblems[0]->nrrows == 0 )
7065  {
7066  SCIP_CALL(ZerohalfLPDataFree(scip, &lpdata));
7067  return SCIP_OKAY;
7068  }
7069 
7070 #ifdef ZEROHALF__PRINT_STATISTICS
7071  SCIP_CALL( printPreprocessingStatistics(scip, lpdata) );
7072 #endif
7073 
7074  /* try to decompose problem into subproblems (and delete obviously redundant subproblems)*/
7075  if( sepadata->decomposeproblem )
7076  {
7077  SCIP_CALL( decomposeProblem(scip, sepadata, lpdata) );
7078  }
7079 
7080  /* sort subproblems */
7081  SCIP_CALL(SCIPallocBufferArray(scip, &sortedsubproblems, lpdata->nsubproblems));
7082  SCIP_CALL(SCIPallocBufferArray(scip, &subproblempriorities, lpdata->nsubproblems));
7083  nrcolsfactor = 1.0 / (2.0 * lpdata->ncols);
7084  for( i = 0 ; i < lpdata->nsubproblems; ++i)
7085  {
7086  sortedsubproblems[i] = i;
7087  subproblempriorities[i] = ((SCIP_Real) lpdata->subproblems[i]->nrrows)
7088  + nrcolsfactor * ((SCIP_Real) lpdata->subproblems[i]->nrcols);
7089  }
7090  SCIPsortRealInt(subproblempriorities, sortedsubproblems, lpdata->nsubproblems);
7091 
7092  /* allocate temporary memory for storing separated zerohalf cuts */
7093  SCIP_CALL(SCIPallocBufferArray(scip, &zerohalfcuts, maxcuts));
7094 
7095  /* process each subproblem */
7096  for( i = 0; i < lpdata->nsubproblems; ++i )
7097  {
7098  /* check if enough cuts have been found */
7099  if( nsepacuts >= maxsepacuts || nzerohalfcuts >= maxcuts )
7100  break;
7101 
7102  subproblemindex = sortedsubproblems[i];
7103  sepadata->maxslack = 1.0 - 2.0 * sepadata->minviolation; /* ignore previous changes */
7104 
7105  /* if the subproblem consists of a single row a^Tx <= b such that a = 0 and b mod 2 = 1,
7106  * then a violated zerohalf cut can be generated by multiplying this row with 0.5 and rounding down.
7107  */
7108  if( lpdata->subproblems[subproblemindex]->nrrows == 1 && lpdata->subproblems[subproblemindex]->nrcols == 0 )
7109  {
7110  SCIP_Real* weights;
7111 
7112 #ifdef SCIP_DEBUG
7113  SCIP_CALL( debugPrintLPRowsAndCols(scip, lpdata) );
7114  SCIPdebugMessage("\n");
7115  debugPrintSubLpData(scip, lpdata, lpdata->subproblems[subproblemindex]);
7116  SCIPdebugMessage("\n");
7117 #endif
7118  /* create weightvector */
7119  weights = NULL;
7120  SCIP_CALL( getZerohalfWeightvectorForSingleRow(scip, sepadata, lpdata, lpdata->subproblems[subproblemindex]->rrows[0],
7121  0, &weights) );
7122  if( weights == NULL )
7123  continue;
7124 
7125  /* create zerohalf cut */
7126  SCIP_CALL( ZerohalfCutDataCreate(scip, &(zerohalfcuts[nzerohalfcuts]),
7127  lpdata->subproblems[subproblemindex], NULL, 1, 1, DECOMPOSITION) );
7129  lpdata, weights, normtype, nzerohalfcuts, &varsolvals, zerohalfcuts[nzerohalfcuts], &cutoff) );
7130 
7131  if ( cutoff )
7132  *result = SCIP_CUTOFF;
7133  else
7134  {
7135  /* add cut to LP */
7136  SCIP_CALL( addZerohalfCutToLP(scip, sepadata, zerohalfcuts[nzerohalfcuts], &nsepacuts, result) );
7137  nzerohalfcuts++;
7138  }
7139 
7140  /* free weightsvector memory */
7141  SCIPfreeMemoryArray(scip, &weights);
7142 
7143  if ( cutoff )
7144  break;
7145 
7146  if( lpdata->rrowsindexofleftrow[lpdata->subproblems[subproblemindex]->rrows[0]] >= 0 )
7147  lpdata->rrowsindexofleftrow[lpdata->subproblems[subproblemindex]->rrows[0]] =
7149  else
7150  if( lpdata->rrowsindexofrightrow[lpdata->subproblems[subproblemindex]->rrows[0]] >= 0 )
7151  lpdata->rrowsindexofrightrow[lpdata->subproblems[subproblemindex]->rrows[0]] =
7153 
7154  continue;
7155  }
7156  assert( ! cutoff );
7157 
7158  /* check if enough cuts have been found */
7159  if( nsepacuts >= maxsepacuts || nzerohalfcuts >= maxcuts )
7160  break;
7161 
7162  /* allocate temporary memory for data (mod 2) structures */
7163  SCIP_CALL( ZerohalfMod2DataCreate(scip, &mod2data) );
7164 
7165  /* store data (mod 2) */
7166  SCIP_CALL( storeMod2Data(scip, sepadata, lpdata, subproblemindex, mod2data) );
7167 
7168  /* preprocess subproblem: reduce problem size and/or separate 'easy' zerohalf cuts */
7169  SCIP_CALL( preprocess(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts, maxcuts,
7170  &nsepacuts, &nzerohalfcuts, zerohalfcuts, &varsolvals, result) );
7171 
7172  if( nsepacuts < maxsepacuts || nzerohalfcuts < maxcuts )
7173  {
7174  /* process subproblem: separate violated zerohalf cuts */
7175  SCIP_CALL( process(scip, sepa, sepadata, lpdata, mod2data, normtype, maxsepacuts, maxcuts,
7176  &nsepacuts, &nzerohalfcuts, zerohalfcuts, &varsolvals, result) );
7177  }
7178 
7179  /* free temporary memory */
7180  SCIP_CALL( ZerohalfMod2DataFree(scip, &mod2data) );
7181 
7182  /* update pointer of zerohalfcuts that has become invalid */
7183  for( j = 0 ; j < nzerohalfcuts ; ++j)
7184  zerohalfcuts[j]->relatedmod2data = NULL;
7185  }
7186 
7187 #ifdef ZEROHALF__PRINT_STATISTICS
7188  if( !sepadata->usezhcutpool )
7189  printZerohalfCutsStatistics(scip, zerohalfcuts, nzerohalfcuts, NULL, NULL, NULL, nsepacuts);
7190 #endif
7191 
7192  if( ! cutoff && sepadata->usezhcutpool )
7193  {
7194  ZEROHALF_CUTDATA* cutdatai;
7195  ZEROHALF_CUTDATA* cutdataj;
7196  SCIP_Real* zerohalfcutpriorities;
7197  SCIP_Real* zerohalfcutminortho;
7198  int* sortedzerohalfcuts;
7199  SCIP_Real violationbucketsize;
7200  SCIP_Bool hasminorthogonality;
7201  int si;
7202  int sj;
7203  int nignoredcuts;
7204 
7205  /* allocate temporary memory */
7206  SCIP_CALL(SCIPallocBufferArray(scip, &sortedzerohalfcuts, nzerohalfcuts));
7207  SCIP_CALL(SCIPallocBufferArray(scip, &zerohalfcutpriorities, nzerohalfcuts));
7208  SCIP_CALL(SCIPallocBufferArray(scip, &zerohalfcutminortho, nzerohalfcuts));
7209 
7210  /* initialize */
7211  violationbucketsize = 10.0;
7212  nignoredcuts = 0;
7213 
7214 #if 1 /* old cutpool version */
7215  /* sort zerohalf cutpool w.r.t. the violation (primary) and the density (secondary) */
7216  for( i = 0 ; i < nzerohalfcuts; ++i)
7217  {
7218  sortedzerohalfcuts[i] = i;
7219  zerohalfcutpriorities[i] = SCIPfloor(scip, violationbucketsize * (zerohalfcuts[i])->violation)
7220  + (1.0 - (SCIP_Real) (zerohalfcuts[i])->nnonz / (SCIP_Real) lpdata->ncols);
7221  }
7222  SCIPsortDownRealInt(zerohalfcutpriorities, sortedzerohalfcuts, nzerohalfcuts);
7223 
7224  /* check orthogonality */
7225  for( si = 0; si < nzerohalfcuts; ++si )
7226  {
7227  cutdatai = zerohalfcuts[sortedzerohalfcuts[si]];
7228  if( cutdatai->cut == NULL || !cutdatai->addedtolp )
7229  continue;
7230  hasminorthogonality = TRUE;
7231  for( sj = 0; hasminorthogonality && sj < si; ++sj )
7232  {
7233  cutdataj = zerohalfcuts[sortedzerohalfcuts[sj]];
7234  if( cutdataj->cut != NULL && cutdataj->addedtolp )
7235  if( SCIPisLT(scip, SCIProwGetOrthogonality(cutdatai->cut , cutdataj->cut, ORTHOFUNC),
7236  MINORTHO) )
7237  hasminorthogonality = FALSE;
7238  }
7239 
7240  /* add cut to LP */
7241  if( hasminorthogonality && cutdatai->addedtolp )
7242  {
7243  /* use delayed cutpool for globally valid cuts */
7244  if( sepadata->delayedcuts && !cutdatai->islocal )
7245  {
7246  SCIP_CALL( SCIPaddDelayedPoolCut(scip, cutdatai->cut) );
7247  }
7248  else
7249  {
7250  SCIP_CALL(SCIPaddCut(scip, NULL, cutdatai->cut, sepadata->forcecutstolp, &cutoff) );
7251  if ( cutoff )
7252  {
7253  *result = SCIP_CUTOFF;
7254  break;
7255  }
7256  if( !cutdatai->islocal )
7257  {
7258  SCIP_CALL(SCIPaddPoolCut(scip, cutdatai->cut));
7259  }
7260  cutdatai->addedtolp = TRUE;
7261  }
7262  }
7263  else
7264  {
7265  cutdatai->addedtolp = FALSE;
7266  nignoredcuts++;
7267  }
7268  }
7269  nsepacuts -= nignoredcuts;
7270 
7271 #ifdef ZEROHALF__PRINT_STATISTICS
7272  printZerohalfCutsStatistics(scip, zerohalfcuts, nzerohalfcuts, sortedzerohalfcuts,
7273  zerohalfcutpriorities, NULL, nsepacuts);
7274 #endif
7275 #else /* new cutpool version: does not seem to be better */
7276  {
7277  int ncutpool;
7278  int ncutpoolold;
7279 
7280  ncutpool = 0;
7281 
7282  /* calculate score for all zerohalfcuts in cutpool */
7283  for( i = 0 ; i < nzerohalfcuts; ++i )
7284  {
7285  cutdatai = zerohalfcuts[i];
7286 
7287  if( cutdatai->cut == NULL || !cutdatai->addedtolp )
7288  continue;
7289 
7290  sortedzerohalfcuts[ncutpool] = i;
7291  zerohalfcutminortho[ncutpool] = 1.0;
7292  zerohalfcutpriorities[ncutpool] = SCIPfloor(scip, violationbucketsize * cutdatai->efficacy)
7293  + (1.0 - (SCIP_Real) cutdatai->nnonz / (SCIP_Real) lpdata->ncols)
7294  + SCIPfloor(scip, violationbucketsize * zerohalfcutminortho[ncutpool]);
7295 
7296  ncutpool++;
7297  }
7298  ncutpoolold = ncutpool;
7299 
7300  /* cut selection loop */
7301  while( ncutpool > 0 )
7302  {
7303  SCIP_Real bestscore;
7304  SCIP_Real priotmp;
7305  SCIP_Real minorthotmp;
7306  SCIP_Bool cutoff;
7307  int bestpos;
7308  int sortidxtmp;
7309 
7310  assert(cutdatai->addedtolp);
7311 
7312  bestscore = SCIP_REAL_MIN;
7313  bestpos = -1;
7314 
7315  /* find cut with best (highest) score */
7316  for( i = 0; i < ncutpool; i++ )
7317  {
7318  /* check if cut is current best cut */
7319  if( zerohalfcutpriorities[i] > bestscore )
7320  {
7321  bestscore = zerohalfcutpriorities[i];
7322  bestpos = i;
7323  }
7324  }
7325 
7326  cutdatai = zerohalfcuts[sortedzerohalfcuts[bestpos]];
7327 
7328  /* add best cut to LP */
7329  SCIP_CALL(SCIPaddCut(scip, NULL, cutdatai->cut, sepadata->forcecutstolp), &cutoff);
7330  if ( cutoff )
7331  {
7332  *result = SCIP_CUTOFF;
7333  break;
7334  }
7335  if( !cutdatai->islocal )
7336  {
7337  SCIP_CALL(SCIPaddPoolCut(scip, cutdatai->cut));
7338  }
7339 
7340  priotmp = zerohalfcutpriorities[bestpos];
7341  minorthotmp = zerohalfcutminortho[bestpos];
7342  sortidxtmp = sortedzerohalfcuts[bestpos];
7343 
7344  /* delete best cut from cutpool */
7345  zerohalfcutpriorities[bestpos] = zerohalfcutpriorities[ncutpool-1];
7346  zerohalfcutminortho[bestpos] = zerohalfcutminortho[ncutpool-1];
7347  sortedzerohalfcuts[bestpos] = sortedzerohalfcuts[ncutpool-1];
7348  ncutpool--;
7349 
7350  /* save data for statistic output */
7351  zerohalfcutpriorities[ncutpool] = priotmp;
7352  zerohalfcutminortho[ncutpool] = minorthotmp;
7353  sortedzerohalfcuts[ncutpool] = sortidxtmp;
7354 
7355  /* update orthogonalities of remaining cuts in cutpool */
7356  j = 0;
7357  while( j < ncutpool )
7358  {
7359  SCIP_Real thisortho;
7360 
7361  cutdataj = zerohalfcuts[sortedzerohalfcuts[j]];
7362  thisortho = SCIProwGetOrthogonality(cutdatai->cut , cutdataj->cut, ORTHOFUNC);
7363 
7364  if( thisortho < MINORTHO )
7365  {
7366  priotmp = zerohalfcutpriorities[j];
7367  minorthotmp = zerohalfcutminortho[j];
7368  sortidxtmp = sortedzerohalfcuts[j];
7369 
7370  /* delete cut from cutpool */
7371  zerohalfcutpriorities[j] = zerohalfcutpriorities[ncutpool-1];
7372  zerohalfcutminortho[j] = zerohalfcutminortho[ncutpool-1];
7373  sortedzerohalfcuts[j] = sortedzerohalfcuts[ncutpool-1];
7374  cutdataj->addedtolp = FALSE;
7375  ncutpool--;
7376  nignoredcuts++;
7377 
7378  /* save data for statistic output */
7379  zerohalfcutpriorities[ncutpool] = priotmp;
7380  zerohalfcutminortho[ncutpool] = minorthotmp;
7381  sortedzerohalfcuts[ncutpool] = sortidxtmp;
7382  }
7383  else
7384  {
7385  /* update score */
7386  if( thisortho < zerohalfcutminortho[j] )
7387  {
7388  zerohalfcutminortho[j] = thisortho;
7389  zerohalfcutpriorities[j] = SCIPfloor(scip, violationbucketsize * cutdataj->efficacy)
7390  + (1.0 - (SCIP_Real) cutdataj->nnonz / (SCIP_Real) lpdata->ncols)
7391  + SCIPfloor(scip, violationbucketsize * zerohalfcutminortho[j]);
7392  }
7393  j++;
7394  }
7395  }
7396  }
7397  nsepacuts -= nignoredcuts;
7398 
7399 #ifdef ZEROHALF__PRINT_STATISTICS
7400  printZerohalfCutsStatistics(scip, zerohalfcuts, ncutpoolold, sortedzerohalfcuts,
7401  zerohalfcutpriorities, zerohalfcutminortho, nsepacuts);
7402 #endif
7403  }
7404 #endif
7405 
7406  /* free temporary memory */
7407  SCIPfreeBufferArray(scip, &zerohalfcutminortho);
7408  SCIPfreeBufferArray(scip, &zerohalfcutpriorities);
7409  SCIPfreeBufferArray(scip, &sortedzerohalfcuts);
7410  }
7411 
7412  sepadata->totalncutsfound += nzerohalfcuts;
7413  sepadata->totalnsepacuts += nsepacuts;
7414 
7415  /* free temporary memory */
7416  if( varsolvals != NULL )
7417  {
7418  SCIPfreeMemoryArray(scip, &varsolvals);
7419  }
7420 
7421  for( i = 0 ; i < nzerohalfcuts ; ++i)
7422  {
7423  SCIP_CALL( ZerohalfCutDataFree(scip, &(zerohalfcuts[i])) );
7424  }
7425  SCIPfreeBufferArray(scip, &zerohalfcuts);
7426  SCIPfreeBufferArray(scip, &subproblempriorities);
7427  SCIPfreeBufferArray(scip, &sortedsubproblems);
7428  SCIP_CALL( ZerohalfLPDataFree(scip, &lpdata) );
7429 
7430  return SCIP_OKAY;
7431 }
7432 
7433 
7434 /* --------------------------------------------------------------------------------------------------------------------
7435  * separator specific interface methods
7436  * -------------------------------------------------------------------------------------------------------------------- */
7437 
7438 /** creates the zerohalf separator and includes it in SCIP */
7440  SCIP* scip /**< SCIP data structure */
7441  )
7442 {
7443  SCIP_SEPADATA* sepadata;
7444  SCIP_SEPA* sepa;
7445 
7446  /* description of the preprocessing methods parameter */
7447  char preprocessingmethodsdescription[SCIP_MAXSTRLEN];
7448  /* description of the sepamethods parameter */
7449  char sepamethodsdescription[SCIP_MAXSTRLEN];
7450  /* description of the subscip parameter */
7451  char subscipobjectivedescription[SCIP_MAXSTRLEN];
7452  int ncharsprinted;
7453 
7454  ncharsprinted = SCIPmemccpy(preprocessingmethodsdescription,
7455  "preprocessing methods and ordering:\n"
7456  " # 'd' columns with small LP solution,\n"
7457  " # 'G' modified Gaussian elimination,\n"
7458  " # 'i' identical columns,\n"
7459  " # 'I' identical rows,\n"
7460  " # 'L' large slack rows,\n"
7461  " # 'M' large slack rows (minslack),\n"
7462  " # 's' column singletons,\n", '\0', SCIP_MAXSTRLEN - 1);
7463 
7464  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7465 
7466  ncharsprinted += SCIPmemccpy(&(preprocessingmethodsdescription[ncharsprinted - 1]),
7467  " # 'X' add trivial zerohalf cuts,\n"
7468  " # 'z' zero columns,\n"
7469  " # 'Z' zero rows,\n"
7470  " # 'C' fast {'z','s'},\n"
7471  " # 'R' fast {'Z','L','I'}\n"
7472  " #\n"
7473  " # '-' no preprocessing\n"
7474  " #", '\0', (unsigned int) (SCIP_MAXSTRLEN - ncharsprinted - 1));
7475 
7476  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7477 
7478  ncharsprinted = SCIPmemccpy(sepamethodsdescription,
7479  "separating methods and ordering:\n"
7480  " # '!' stop further processing if a cut was found,\n"
7481  " # '2' exact polynomial time algorithm (only if matrix has max 2 odd entries per row),\n"
7482  " # 'e' enumeration heuristics (k=1: try all preprocessed rows),\n"
7483  " # 'E' enumeration heuristics (k=2: try all combinations of up to two preprocessed rows),\n"
7484  " # 'g' Extended Gaussian elimination heuristics,\n", '\0', SCIP_MAXSTRLEN - 1);
7485 
7486  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7487 
7488  ncharsprinted += SCIPmemccpy(&(sepamethodsdescription[ncharsprinted - 1]),
7489  " # 's' auxiliary IP heuristics (i.e. number of solved nodes is limited)\n"
7490  " # 'S' auxiliary IP exact (i.e. unlimited number of nodes)\n"
7491  " #\n"
7492  " # '-' no processing\n"
7493  " #", '\0', (unsigned int) (SCIP_MAXSTRLEN - ncharsprinted - 1));
7494 
7495  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7496 
7497  ncharsprinted = SCIPmemccpy(subscipobjectivedescription,
7498  "auxiliary IP objective:\n"
7499  " # 'v' maximize cut violation,\n"
7500  " # 'u' minimize number of aggregated rows in cut,\n"
7501  " # 'w' minimize number of aggregated rows in cut\n"
7502  " # weighted by the number of rows in the aggregation,\n", '\0', SCIP_MAXSTRLEN - 1);
7503 
7504  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7505 
7506  ncharsprinted += SCIPmemccpy(&(subscipobjectivedescription[ncharsprinted - 1]),
7507  " # 'p' maximize cut violation and penalize a high number\n"
7508  " # of aggregated rows in the cut weighted by the number\n"
7509  " # of rows in the aggregation and the penalty factor p\n"
7510  " #", '\0', (unsigned int) (SCIP_MAXSTRLEN - ncharsprinted - 1));
7511 
7512  assert(ncharsprinted > 0 && ncharsprinted < SCIP_MAXSTRLEN);
7513 
7514  /* create zerohalf separator data */
7515  SCIP_CALL(SCIPallocMemory(scip, &sepadata));
7516 
7517  /* initialize statistics */
7518  sepadata->totalncutsfound = 0;
7519  sepadata->totalnsepacuts = 0;
7520  sepadata->pptimers = NULL;
7521  sepadata->dtimer = NULL;
7522  sepadata->sepatimers = NULL;
7523  sepadata->nsepacutsalgo = NULL;
7524  sepadata->nzerohalfcutsalgo = NULL;
7525 
7526  sepadata->ppmethods = NULL;
7527  sepadata->sepamethods = NULL;
7528  sepadata->nppmethods = -1;
7529  sepadata->nsepamethods = -1;
7530  sepadata->subscipsettings = NULL;
7531 
7532  sepadata->norigrows = 0;
7533  sepadata->origrows = NULL;
7534 
7535  /* include separator */
7538  sepaExeclpZerohalf, NULL,
7539  sepadata) );
7540 
7541  assert(sepa != NULL);
7542 
7543  /* set non-NULL pointers to callback methods */
7544  SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyZerohalf) );
7545  SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeZerohalf) );
7546 
7547  /* add zerohalf separator parameters */
7549  "separating/zerohalf/maxrounds",
7550  "maximal number of zerohalf separation rounds per node (-1: unlimited)",
7551  &(sepadata->maxrounds), FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL));
7553  "separating/zerohalf/maxroundsroot",
7554  "maximal number of zerohalf separation rounds in the root node (-1: unlimited)",
7555  &(sepadata->maxroundsroot), FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL));
7557  "separating/zerohalf/maxsepacuts",
7558  "maximal number of {0,1/2}-cuts separated per separation round",
7559  &(sepadata->maxsepacuts), FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL));
7561  "separating/zerohalf/maxsepacutsroot",
7562  "maximal number of {0,1/2}-cuts separated per separation round in the root node",
7563  &(sepadata->maxsepacutsroot), FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL));
7565  "separating/zerohalf/dynamiccuts",
7566  "should generated cuts be removed from the LP if they are no longer tight?",
7567  &(sepadata->dynamiccuts), FALSE, DEFAULT_DYNAMICCUTS, NULL, NULL));
7568 
7569 
7571  "separating/zerohalf/maxcutsfound",
7572  "maximal number of {0,1/2}-cuts determined per separation round\n\
7573  # (this includes separated but inefficacious cuts)",
7574  &(sepadata->maxcuts), TRUE, DEFAULT_MAXCUTS, 0, 1000000, NULL, NULL));
7576  "separating/zerohalf/maxcutsfoundroot",
7577  "maximal number of {0,1/2}-cuts determined per separation round in the root node\n\
7578  # (this includes separated but inefficacious cuts)",
7579  &(sepadata->maxcutsroot), TRUE, DEFAULT_MAXCUTSROOT, 0, 1000000, NULL, NULL));
7580 
7581 
7583  "separating/zerohalf/maxdepth",
7584  "separating cuts only if depth <= maxdepth (-1: unlimited)",
7585  &(sepadata->maxdepth), TRUE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL));
7587  "separating/zerohalf/maxncalls",
7588  "maximal number of calls (-1: unlimited)",
7589  &(sepadata->maxncalls), TRUE, DEFAULT_MAXNCALLS, -1LL, SCIP_LONGINT_MAX, NULL, NULL));
7591  "separating/zerohalf/relaxcontvars",
7592  "should continuous variables be relaxed by adding variable bounds?",
7593  &(sepadata->relaxcontvars), TRUE, DEFAULT_RELAXCONTVARS, NULL, NULL)); /**@todo support this */
7595  "separating/zerohalf/scalefraccoeffs",
7596  "should rows be scaled to make fractional coefficients integer?",
7597  &(sepadata->scalefraccoeffs), TRUE, DEFAULT_SCALEFRACCOEFFS, NULL, NULL));
7599  "separating/zerohalf/ignoreprevzhcuts",
7600  "should zerohalf cuts found in previous callbacks ignored?",
7601  &(sepadata->ignoreprevzhcuts), TRUE, DEFAULT_IGNOREPREVIOUSZHCUTS, NULL, NULL));
7603  "separating/zerohalf/onlyorigrows",
7604  "should only original LP rows be considered (i.e. ignore previously added LP rows)?",
7605  &(sepadata->onlyorigrows), TRUE, DEFAULT_ONLYORIGROWS, NULL, NULL));
7606 
7608  "separating/zerohalf/usezhcutpool",
7609  "should zerohalf cuts be filtered using a cutpool?",
7610  &(sepadata->usezhcutpool), TRUE, DEFAULT_USEZHCUTPOOL, NULL, NULL));
7612  "separating/zerohalf/delayedcuts",
7613  "should cuts be added to the delayed cut pool?",
7614  &sepadata->delayedcuts, TRUE, DEFAULT_DELAYEDCUTS, NULL, NULL) );
7615  SCIP_CALL( SCIPaddIntParam(scip,
7616  "separating/zerohalf/maxtestdelta",
7617  "maximal number of different deltas to try for cmir (-1: unlimited, 0: delta=1)",
7618  &sepadata->maxtestdelta, TRUE, DEFAULT_MAXTESTDELTA, -1, INT_MAX, NULL, NULL) );
7620  "separating/zerohalf/trynegscaling",
7621  "should negative values also be tested in scaling for cmir?",
7622  &sepadata->trynegscaling, TRUE, DEFAULT_TRYNEGSCALING, NULL, NULL) );
7623 
7624 
7626  "separating/zerohalf/preprocessing/decomposeproblem",
7627  "should problem be decomposed into subproblems (if possible) before applying preprocessing?",
7628  &(sepadata->decomposeproblem), FALSE, DEFAULT_DECOMPOSEPROBLEM, NULL, NULL));
7630  "separating/zerohalf/preprocessing/delta",
7631  "value of delta parameter used in preprocessing method 'd'",
7632  &(sepadata->ppdelta), FALSE, DEFAULT_PPDELTA, 0.0, 1.0, NULL, NULL));
7634  "separating/zerohalf/preprocessing/ppmethods",
7635  preprocessingmethodsdescription,
7636  &(sepadata->ppmethods), FALSE, DEFAULT_PPMETHODS, NULL, NULL));
7637 
7638 
7639 
7641  "separating/zerohalf/separating/forcecutstolp",
7642  "should the cuts be forced to enter the LP?",
7643  &(sepadata->forcecutstolp), FALSE, DEFAULT_FORCECUTSTOLP, NULL, NULL));
7645  "separating/zerohalf/separating/forcecutstosepastore",
7646  "should the cuts be forced to enter SCIP's sepastore?",
7647  &(sepadata->forcecutstosepastore), FALSE, DEFAULT_FORCECUTSTOSEPASTORE, NULL, NULL));
7649  "separating/zerohalf/separating/minviolation",
7650  "minimal violation of a {0,1/2}-cut to be separated",
7651  &(sepadata->minviolation), FALSE, DEFAULT_MINVIOLATION, 0.001, 0.5, NULL, NULL));
7653  "separating/zerohalf/separating/sepamethods",
7654  sepamethodsdescription,
7655  &(sepadata->sepamethods), FALSE, DEFAULT_SEPAMETHODS, NULL, NULL));
7656 
7657 
7658 
7660  "separating/zerohalf/separating/auxip/settingsfile",
7661  "optional settings file of the auxiliary IP (-: none)",
7662  &(sepadata->subscipsettings), FALSE, DEFAULT_SUBSCIPSETTINGS, NULL, NULL));
7664  "separating/zerohalf/separating/auxip/sollimit",
7665  "limits/solutions setting of the auxiliary IP",
7666  &(sepadata->subscipsollimit), FALSE, DEFAULT_SUBSCIPSOLLIMIT, -1, INT_MAX, NULL, NULL));
7668  "separating/zerohalf/separating/auxip/penaltyfactor",
7669  "penalty factor used with objective function 'p' of auxiliary IP",
7670  &(sepadata->subscipobjpen), FALSE, DEFAULT_SUBSCIPOBJPEN, 0.0, 1.0, NULL, NULL));
7672  "separating/zerohalf/separating/auxip/useallsols",
7673  "should all (proper) solutions of the auxiliary IP be used to generate cuts instead of using only the best?",
7674  &(sepadata->subscipuseallsols), FALSE, DEFAULT_SUBSCIPUSEALLSOLS, NULL, NULL));
7676  "separating/zerohalf/separating/auxip/objective",
7677  subscipobjectivedescription,
7678  &(sepadata->subscipobjective), FALSE, DEFAULT_SUBSCIPOBJECTIVE, "uvwp", NULL, NULL));
7679 
7680  return SCIP_OKAY;
7681 }
7682 
#define BOUNDSWITCH
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:33158
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
static SCIP_RETCODE ZerohalfMod2DataFree(SCIP *scip, ZEROHALF_MOD2DATA **mod2data)
#define DEFAULT_SCALEFRACCOEFFS
Definition: sepa_zerohalf.c:89
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:40329
static SCIP_RETCODE preprocessConsiderMinSlack(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, SCIP_Bool removelargeslackrows, SCIP_Bool removelargecolrows)
#define BITARRAYBASETYPE
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
static SCIP_RETCODE ZerohalfAuxGraphNodeCreate(SCIP *scip, ZEROHALF_AUXGRAPH_NODE **node)
#define DEFAULT_SUBSCIPSOLLIMIT
Definition: sepa_zerohalf.c:91
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:8086
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
static SCIP_RETCODE ZerohalfSubLPDataCreate(SCIP *scip, ZEROHALF_SUBLPDATA **subproblem)
#define IRRELEVANT
SCIP_RETCODE SCIPaddDelayedPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:31341
struct Zerohalf_Mod2Data ZEROHALF_MOD2DATA
SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, SCIP_Real maxweight, int *weightinds, int nweightinds, int rowlensum, int *sidetypes, SCIP_Real scale, SCIP_Real *mksetcoefs, SCIP_Bool *mksetcoefsvalid, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank)
Definition: scip.c:27058
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
static SCIP_RETCODE getBitarrayOfSelectedRows(SCIP *scip, ZEROHALF_MOD2DATA *mod2data, ZEROHALF_AUXIPDATA *auxipdata, SCIP_SOL *solution, BITARRAY *rrowsincut, int *nrrowsincut)
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
static SCIP_RETCODE preprocess(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result)
#define DEFAULT_FORCECUTSTOSEPASTORE
Definition: sepa_zerohalf.c:78
#define DEFAULT_MAXDEPTH
Definition: sepa_zerohalf.c:75
SCIP_Real SCIPgetRowMinCoef(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28045
#define ISEVEN(scip, value)
sepamethods
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:10378
#define ISODD(scip, value)
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:15737
#define DEFAULT_RELAXCONTVARS
Definition: sepa_zerohalf.c:88
#define SCIP_MAXSTRLEN
Definition: def.h:201
#define IDENT_TO_ROW_WITH_SMALLER_SLACK
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip.c:30877
#define DEFAULT_MAXCUTSROOT
Definition: sepa_zerohalf.c:84
#define DEFAULT_PPDELTA
Definition: sepa_zerohalf.c:95
#define ZERO_ROW
#define NULL
Definition: lpi_spx.cpp:130
#define MAXWEIGHTRANGE
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17323
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17261
#define DEFAULT_FORCECUTSTOLP
Definition: sepa_zerohalf.c:77
static SCIP_RETCODE preprocessTrivialZerohalfCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, int firstrowsind, int lastrowsind, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, CUTSEPARATEDBY cutseparatedby, SCIP_RESULT *result)
#define USEVBDS
static SCIP_RETCODE storeCutInArrays(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_Real *cutcoefs, SCIP_Real *varsolvals, char normtype, SCIP_VAR **cutvars, SCIP_Real *cutvals, int *cutlen, SCIP_Real *cutact, SCIP_Real *cutnorm)
#define CONTINUOUS_VARIABLE
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17291
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:18748
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:18850
static SCIP_RETCODE process(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result)
SCIP_RETCODE SCIPincludeSepaZerohalf(SCIP *scip)
#define BITARRAY
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:18984
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
#define DEFAULT_SEPAMETHODS
Definition: sepa_zerohalf.c:99
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:41009
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4046
#define ZERO_LP_SOL
#define MINFRAC
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SLACK_GREATER_THAN_MSL_MINUS_SODD
#define SCIP_CALL(x)
Definition: def.h:266
static SCIP_RETCODE preprocessRows(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, int firstrowsind, int lastrowsind, SCIP_Bool removezerorows, SCIP_Bool removelargeslackrows, SCIP_Bool removeidenticalrows)
static SCIP_RETCODE ZerohalfAuxGraphNodeFree(SCIP *scip, ZEROHALF_AUXGRAPH_NODE **node)
#define BRANCHPRIORITY__PREFER_BRANCHING
static SCIP_RETCODE getRelevantColumns(SCIP *scip, ZEROHALF_LPDATA *lpdata)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4109
static SCIP_RETCODE ZerohalfLPDataFree(SCIP *scip, ZEROHALF_LPDATA **lpdata)
static SCIP_RETCODE createSubscip(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, ZEROHALF_AUXIPDATA *auxipdata, SCIP_Bool setnodelimit)
#define DEFAULT_DELAYEDCUTS
static SCIP_RETCODE getZerohalfWeightvectorForSingleRow(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, int rowsindex, int rrowsindex, SCIP_Real **weights)
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:27888
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
#define BITARRAYBITMASKTYPE
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
static SCIP_DECL_SORTINDCOMP(compRealNonDecreasing)
static const unsigned int Zerohalf_bitarraybasetypesize_nbits
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
enum cutseparatedby CUTSEPARATEDBY
#define BITARRAYCLEAR(barray, barraysize)
#define DEFAULT_SUBSCIPSETTINGS
Definition: sepa_zerohalf.c:90
static SCIP_RETCODE preprocessColumns(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, int firstcolsind, int lastcolsind, SCIP_Bool removezerocols, SCIP_Bool removecolsingletons, SCIP_Bool checkresultingrows)
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
#define ALLOWLOCAL
#define DEFAULT_SUBSCIPOBJPEN
Definition: sepa_zerohalf.c:96
static void findClosestLb(SCIP *scip, ZEROHALF_LPDATA *lpdata, SCIP_COL *col, SCIP_Real *bestlbsol, int *bestlbtype, SCIP_VAR **bestzvlb, SCIP_Real *bestbvlb, SCIP_Real *bestdvlb)
#define SCIP_LONGINT_MAX
Definition: def.h:113
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_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28063
#define DEFAULT_MAXROUNDSROOT
Definition: sepa_zerohalf.c:70
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition: scip.c:26672
cutseparatedby
static SCIP_RETCODE createZerohalfCutFromZerohalfWeightvector(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, SCIP_Real *weights, char normtype, int nzerohalfcuts, SCIP_Real **varsolvals, ZEROHALF_CUTDATA *cutdata, SCIP_Bool *cutoff)
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:35668
#define MINORTHO
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_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
static SCIP_RETCODE ZerohalfCutDataCreate(SCIP *scip, ZEROHALF_CUTDATA **cutdata, ZEROHALF_SUBLPDATA *relatedsubproblem, ZEROHALF_MOD2DATA *relatedmod2data, int nrrowsincut, int nrowsincut, CUTSEPARATEDBY separatedby)
static SCIP_RETCODE ZerohalfLPDataCreate(SCIP *scip, ZEROHALF_LPDATA **lpdata)
struct Zerohalf_LPData ZEROHALF_LPDATA
#define BITARRAYSXOR(barray1, barray2, size)
static void findClosestUb(SCIP *scip, ZEROHALF_LPDATA *lpdata, SCIP_COL *col, SCIP_Real *bestubsol, int *bestubtype, SCIP_VAR **bestzvub, SCIP_Real *bestbvub, SCIP_Real *bestdvub)
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18726
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
#define ZERO_COLUMN
static void ZerohalfSubLPDataFree(SCIP *scip, ZEROHALF_SUBLPDATA **subproblem)
#define GETBITARRAYINDEX(pos)
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18784
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17303
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
static SCIP_DECL_SEPAEXECLP(sepaExeclpZerohalf)
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Longint SCIPsepaGetNCalls(SCIP_SEPA *sepa)
Definition: sepa.c:750
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
#define SCIPdebugPrintf
Definition: pub_message.h:80
#define DEFAULT_MAXCUTS
Definition: sepa_zerohalf.c:81
struct Zerohalf_AuxGraph_Node ZEROHALF_AUXGRAPH_NODE
#define SEPA_FREQ
Definition: sepa_zerohalf.c:64
static SCIP_RETCODE solveSubscip(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_MOD2DATA *mod2data, ZEROHALF_AUXIPDATA *auxipdata, SCIP_SOL ***sols, int *nsols)
static SCIP_RETCODE getRelevantRows(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata)
#define DEFAULT_DECOMPOSEPROBLEM
Definition: sepa_zerohalf.c:74
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18639
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41996
#define BOUNDSFORTRANS
#define DEFAULT_IGNOREPREVIOUSZHCUTS
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:41118
#define NNONZOFFSET
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:93
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41598
#define BITARRAYSAREEQUAL(barray1, barray2, size)
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:31062
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
static SCIP_RETCODE addEdgeToAuxGraph(SCIP *scip, ZEROHALF_AUXGRAPH *graph, int node1index, int node2index, SCIP_Bool isodd, SCIP_Real weight, int relatedrow)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41758
#define SEPA_NAME
Definition: sepa_zerohalf.c:61
static void markColAsRemovedAndClearCol(ZEROHALF_MOD2DATA *mod2data, int c, int flag)
static SCIP_RETCODE preprocessIdenticalColums(SCIP *scip, ZEROHALF_MOD2DATA *mod2data)
static SCIP_RETCODE preprocessColumnsWithSmallFracsol(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_MOD2DATA *mod2data, SCIP_Real delta)
#define BOUNDTYPESFORTRANS
static SCIP_RETCODE separateByEnumerationHeuristics(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result, int maxncombinedrows)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
#define SEPA_USESSUBSCIP
Definition: sepa_zerohalf.c:66
SCIP_RETCODE SCIPgetCharParam(SCIP *scip, const char *name, char *value)
Definition: scip.c:3816
static SCIP_RETCODE separateByAuxGraph(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result, SCIP_Bool *wrongstructure)
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9019
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26750
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:35020
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define BRANCHPRIORITY__AVOID_BRANCHING
static SCIP_Real calcObjWeight(BITARRAY rowaggregation, int nrrows)
#define MAXDNOM
#define BITARRAYBITSET(barray, pos)
#define DEFAULT_MAXSEPACUTS
Definition: sepa_zerohalf.c:71
#define DEFAULT_PPMETHODS
Definition: sepa_zerohalf.c:98
#define BITARRAYBITISSET(barray, pos)
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
static SCIP_RETCODE ZerohalfAuxGraphCreate(SCIP *scip, ZEROHALF_AUXGRAPH **auxgraph)
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:35717
#define SEPA_DELAY
Definition: sepa_zerohalf.c:67
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37435
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
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
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
#define NO_RELEVANT_COLUMNS
static SCIP_RETCODE ZerohalfAuxIPDataFree(SCIP *scip, ZEROHALF_AUXIPDATA **auxipdata)
static SCIP_RETCODE decomposeProblem(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata)
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3684
static SCIP_RETCODE separateByGaussHeuristics(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
#define SMALL_FRACSOL_HEUR
#define DEFAULT_MINVIOLATION
Definition: sepa_zerohalf.c:76
static SCIP_RETCODE ZerohalfAuxIPDataCreate(SCIP *scip, ZEROHALF_AUXIPDATA **auxipdata)
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_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4001
#define NONEXISTENT_ROW
static const unsigned int Zerohalf_bitarraybasetypesize
static void markRowAsRemoved(ZEROHALF_MOD2DATA *mod2data, int r, int flag)
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17313
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
Definition: scip.c:6702
static SCIP_RETCODE addZerohalfCutToLP(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_CUTDATA *cutdata, int *nsepacuts, SCIP_RESULT *result)
#define DEFAULT_SUBSCIPUSEALLSOLS
Definition: sepa_zerohalf.c:92
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE ZerohalfAuxGraphFree(SCIP *scip, ZEROHALF_AUXGRAPH **auxgraph)
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17281
struct Zerohalf_CutData ZEROHALF_CUTDATA
#define ORTHOFUNC
#define USEVARBOUNDS
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:41396
static SCIP_RETCODE dijkstra(SCIP *scip, ZEROHALF_AUXGRAPH *graph, ZEROHALF_AUXGRAPH_NODE *sourcenode, ZEROHALF_AUXGRAPH_NODE *targetnode, SCIP_Real maxdistance)
#define IDENT_TO_ANOTHER_COLUMN
#define SLACK_GREATER_THAN_MAXSLACK
#define ALL_MATRIX_ROWS_DELETED
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17249
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition: scip.c:22487
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18606
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:39265
#define MAXFRAC
Constraint handler for linear constraints in their most general form, .
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
static SCIP_RETCODE ZerohalfMod2DataCreate(SCIP *scip, ZEROHALF_MOD2DATA **mod2data)
{0,1/2}-cuts separator
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7435
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
Definition: scip.c:4254
#define SCIP_REAL_MIN
Definition: def.h:129
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14503
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define LP_SOL_EQUALS_ODD_LB
#define SINGLETON_COLUMN
#define XOR(bool1, bool2)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41770
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17271
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
#define DEFAULT_SUBSCIPOBJECTIVE
Definition: sepa_zerohalf.c:87
#define DEFAULT_DYNAMICCUTS
Definition: sepa_zerohalf.c:73
#define REALABS(x)
Definition: def.h:151
#define LP_SOL_EQUALS_ODD_UB
#define SEPA_PRIORITY
Definition: sepa_zerohalf.c:63
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
static SCIP_RETCODE getZerohalfWeightvectorFromSelectedRowsBitarray(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, BITARRAY rrowsincut, SCIP_Real **weights, int *nrowsincut)
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
#define SEPA_MAXBOUNDDIST
Definition: sepa_zerohalf.c:65
static SCIP_RETCODE calcInnerProductOfRowAndFracsol(SCIP *scip, ZEROHALF_MOD2DATA *mod2data, BITARRAY row, SCIP_Real maxinnerproduct, SCIP_Real *innerproduct)
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3657
enum SCIP_Stage SCIP_STAGE
Definition: type_set.h:48
#define GETBITARRAYMASK(pos)
#define DEFAULT_MAXROUNDS
Definition: sepa_zerohalf.c:69
#define MIN(x, y)
Definition: memory.c:67
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28334
#define DEFAULT_MAXNCALLS
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:41146
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:10194
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
#define DEFAULT_USEZHCUTPOOL
#define SCIP_Longint
Definition: def.h:112
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
Definition: sepa.c:760
SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: misc.c:7375
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:19104
SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:17628
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18616
SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28134
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:3938
#define LP_SOL_EQUALS_EVEN_LB
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
#define SEPA_DESC
Definition: sepa_zerohalf.c:62
SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:1510
preprocessingmethods
static SCIP_RETCODE storeMod2Data(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, int subproblemindex, ZEROHALF_MOD2DATA *mod2data)
#define FIXINTEGRALRHS
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3797
SCIP_RETCODE SCIPcutGenerationHeuristicCmir(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_Real *varsolvals, int maxtestdelta, SCIP_Real *rowweights, SCIP_Real maxweight, int *weightinds, int nweightinds, int rowlensum, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Bool trynegscaling, SCIP_Bool cutremovable, const char *cutclassname, SCIP_Bool *cutoff, int *ncuts, SCIP_Real *delta, SCIP_Bool *deltavalid)
Definition: sepa_cmir.c:429
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_TRYNEGSCALING
#define GETREQUIREDBITARRAYSIZE(nvalstostore)
static SCIP_RETCODE separateBySolvingAuxIP(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data, char normtype, int maxsepacuts, int maxcuts, SCIP_Bool setnodelimit, int *nsepacuts, int *nzerohalfcuts, ZEROHALF_CUTDATA **zerohalfcuts, SCIP_Real **varsolvals, SCIP_RESULT *result)
#define LP_SOL_EQUALS_EVEN_UB
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
#define DEFINES_VIOLATED_ZEROHALF_CUT
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition: lp.c:18903
#define DEFAULT_ONLYORIGROWS
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:18794
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
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:18759
static SCIP_RETCODE preprocessModGaussElim(SCIP *scip, SCIP_SEPADATA *sepadata, ZEROHALF_LPDATA *lpdata, ZEROHALF_MOD2DATA *mod2data)
static SCIP_RETCODE ZerohalfCutDataFree(SCIP *scip, ZEROHALF_CUTDATA **cutdata)
#define SCIPABORT()
Definition: def.h:238
#define MAXSCALE
default SCIP plugins
SCIP_RETCODE SCIPprintBestSol(SCIP *scip, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:35833
static SCIP_DECL_SEPAFREE(sepaFreeZerohalf)
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:38
#define DEFAULT_MAXSEPACUTSROOT
Definition: sepa_zerohalf.c:72
static SCIP_Bool hasMatrixMax2EntriesPerRow(ZEROHALF_MOD2DATA *mod2data)
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:41409
#define LARGE_COL_EXISTS
#define DEFAULT_MAXTESTDELTA
static SCIP_DECL_SEPACOPY(sepaCopyZerohalf)