Scippy

SCIP

Solving Constraint Integer Programs

cuts.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cuts.c
17  * @brief Methods used to generate and strengthen cuts
18  * @author Jakob Witzig
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include "scip/def.h"
24 #include "scip/retcode.h"
25 #include "scip/cuts.h"
26 #include "scip/debug.h"
27 #include "scip/pub_lp.h"
28 #include "scip/lp.h"
29 #include "scip/prob.h"
30 #include "scip/set.h"
31 #include "scip/sol.h"
32 #include "scip/var.h"
33 #include "scip/scip.h"
34 #include "scip/struct_scip.h"
35 
36 
37 #define MAXCMIRSCALE 1e+6 /**< maximal scaling (scale/(1-f0)) allowed in c-MIR calculations */
38 
39 /*
40  * debug messages
41  */
42 
43 #ifdef SCIP_DEBUG
44 /** method is to print in row in case SCIP_DEBUG is defined */
45 static
46 void debugRowPrint(
47  SCIP_ROW* row /**< LP row */
48  )
49 {
50  int i;
51 
52  assert(row != NULL);
53 
54  /* print row name */
55  if( row->name != NULL && row->name[0] != '\0' )
56  {
57  SCIPdebugPrintf("%s: ", row->name);
58  }
59 
60  /* print left hand side */
61  SCIPdebugPrintf("%.15g <= ", row->lhs);
62 
63  /* print coefficients */
64  if( row->len == 0 )
65  {
66  SCIPdebugPrintf("0 ");
67  }
68  for( i = 0; i < row->len; ++i )
69  {
70  assert(row->cols[i] != NULL);
71  assert(row->cols[i]->var != NULL);
72  assert(SCIPvarGetName(row->cols[i]->var) != NULL);
73  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
74  SCIPdebugPrintf("%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
75  }
76 
77  /* print constant */
79  {
80  SCIPdebugPrintf("%+.15g ", row->constant);
81  }
82 
83  /* print right hand side */
84  SCIPdebugPrintf("<= %.15g\n", row->rhs);
85 }
86 #else
87 #define debugRowPrint(x) /**/
88 #endif
89 
90 #ifdef SCIP_DEBUG
91 static
92 void printMIR(
93  SCIP_SET* set, /**< global SCIP settings */
94  SCIP_STAT* stat, /**< problem statistics */
95  SCIP_PROB* prob, /**< problem data */
96  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
97  SCIP_Real* mircoef, /**< MIR coefficients */
98  SCIP_Real mirrhs, /**< right hand side of the MIR row */
99  SCIP_Bool ignorsol,
100  SCIP_Bool islocal
101  )
102 {
103  SCIP_Real activity;
104  int i;
105 
106  assert(prob != NULL);
107 
108  SCIPdebugMessage("MIR:");
109  activity = 0.0;
110  for( i = 0; i < prob->nvars; ++i )
111  {
112  if( mircoef[i] != 0.0 )
113  {
114  SCIPdebugPrintf(" %+g<%s>", mircoef[i], SCIPvarGetName(prob->vars[i]));
115 
116  if( !ignorsol )
117  activity += mircoef[i] * (sol == NULL ? SCIPvarGetLPSol(prob->vars[i]) : SCIPsolGetVal(sol, set, stat, prob->vars[i]));
118  else
119  {
120  if( mircoef[i] > 0.0 )
121  {
122  activity += mircoef[i] * (islocal ? SCIPvarGetLbLocal(prob->vars[i]) : SCIPvarGetLbGlobal(prob->vars[i]));
123  }
124  else
125  {
126  activity += mircoef[i] * (islocal ? SCIPvarGetUbLocal(prob->vars[i]) : SCIPvarGetUbGlobal(prob->vars[i]));
127  }
128  }
129  }
130  }
131  SCIPdebugPrintf(" <= %.6f (activity: %g)\n", mirrhs, activity);
132 }
133 #endif
134 
135 
136 /** returns the maximum absolute row weight in the given weight vector, and calculates the sparsity pattern of the weights */
137 static
139  SCIP_SET* set, /**< global SCIP settings */
140  SCIP_LP* lp, /**< LP data */
141  SCIP_Real* weights, /**< row weights in row summation */
142  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
143  int* nrowinds, /**< pointer to store number of used rows */
144  int* rowlensum /**< pointer to store total number of non-zeros in used rows */
145  )
146 {
147  SCIP_Real maxabsweight;
148  int r;
149 
150  assert(set != NULL);
151  assert(lp != NULL);
152  assert(weights != NULL);
153  assert(rowinds != NULL);
154  assert(nrowinds != NULL);
155 
156  *nrowinds = 0;
157  *rowlensum = 0;
158 
159  maxabsweight = 0.0;
160  for( r = 0; r < lp->nrows; ++r )
161  {
162  SCIP_Real absweight;
163 
164  /* skip unused rows */
165  if( SCIPsetIsZero(set, weights[r]) )
166  continue;
167 
168  /* record the row in the sparsity pattern */
169  rowinds[*nrowinds] = r;
170  (*nrowinds)++;
171 
172  (*rowlensum) += SCIProwGetNNonz(lp->rows[r]);
173 
174  absweight = REALABS(weights[r]);
175  maxabsweight = MAX(maxabsweight, absweight);
176  }
177 
178  return maxabsweight;
179 }
180 
181 /** returns the maximum absolute row weight in the given weight vector using given sparsity pattern */
182 static
184  SCIP_SET* set, /**< global SCIP settings */
185  SCIP_LP* lp, /**< LP data */
186  SCIP_Real* weights, /**< row weights in row summation */
187  int* rowinds, /**< array of sparsity pattern of used rows; size lp->nrows */
188  int* nrowinds, /**< pointer to store number of used rows */
189  int* rowlensum /**< pointer to store total number of non-zeros in used rows */
190  )
191 {
192  SCIP_Real maxabsweight;
193  int r; /* index used for reading from the row*/
194  int w; /* auxiliary index to skip zeros in weights array */
195 
196  assert(set != NULL);
197  assert(lp != NULL);
198  assert(weights != NULL);
199  assert(rowinds != NULL);
200  assert(nrowinds != NULL);
201 
202  *rowlensum = 0;
203 
204  maxabsweight = 0.0;
205  w = 0;
206  for( r = 0; r < *nrowinds; ++r )
207  {
208  SCIP_Real absweight;
209 
210  /* remove zeros from the sparsity pattern */
211  if( SCIPsetIsZero(set, weights[rowinds[r]]) )
212  continue;
213 
214  rowinds[w] = rowinds[r];
215  ++w;
216 
217  (*rowlensum) += SCIProwGetNNonz(lp->rows[rowinds[r]]);
218 
219  absweight = REALABS(weights[rowinds[r]]);
220  maxabsweight = MAX(maxabsweight, absweight);
221  }
222  (*nrowinds) = w;
223 
224  return maxabsweight;
225 }
226 
227 /** finds the best lower bound of the variable to use for MIR transformation */
228 static
230  SCIP_SET* set, /**< global SCIP settings */
231  SCIP_STAT* stat, /**< problem statistics */
232  SCIP_VAR* var, /**< problem variable */
233  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
234  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
235  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
236  SCIP_Real* bestlb, /**< pointer to store best bound value */
237  int* bestlbtype /**< pointer to store best bound type */
238  )
239 {
240  assert(bestlb != NULL);
241  assert(bestlbtype != NULL);
242 
243  *bestlb = SCIPvarGetLbGlobal(var);
244  *bestlbtype = -1;
245 
246  if( allowlocal )
247  {
248  SCIP_Real loclb;
249 
250  loclb = SCIPvarGetLbLocal(var);
251  if( SCIPsetIsGT(set, loclb, *bestlb) )
252  {
253  *bestlb = loclb;
254  *bestlbtype = -2;
255  }
256  }
257 
258  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
259  {
260  SCIP_Real bestvlb;
261  int bestvlbidx;
262 
263  SCIPvarGetClosestVlb(var, sol, set, stat, &bestvlb, &bestvlbidx);
264  if( bestvlbidx >= 0
265  && (bestvlb > *bestlb || (*bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, *bestlb))) )
266  {
267  SCIP_VAR** vlbvars;
268 
269  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
270  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
271  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
272  */
273  vlbvars = SCIPvarGetVlbVars(var);
274  assert(vlbvars != NULL);
275  if( SCIPvarGetProbindex(vlbvars[bestvlbidx]) < SCIPvarGetProbindex(var) )
276  {
277  *bestlb = bestvlb;
278  *bestlbtype = bestvlbidx;
279  }
280  }
281  }
282 }
283 
284 /** finds the best upper bound of the variable to use for MIR transformation */
285 static
287  SCIP_SET* set, /**< global SCIP settings */
288  SCIP_STAT* stat, /**< problem statistics */
289  SCIP_VAR* var, /**< problem variable */
290  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
291  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
292  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
293  SCIP_Real* bestub, /**< pointer to store best bound value */
294  int* bestubtype /**< pointer to store best bound type */
295  )
296 {
297  assert(bestub != NULL);
298  assert(bestubtype != NULL);
299 
300  *bestub = SCIPvarGetUbGlobal(var);
301  *bestubtype = -1;
302 
303  if( allowlocal )
304  {
305  SCIP_Real locub;
306 
307  locub = SCIPvarGetUbLocal(var);
308  if( SCIPsetIsLT(set, locub, *bestub) )
309  {
310  *bestub = locub;
311  *bestubtype = -2;
312  }
313  }
314 
315  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
316  {
317  SCIP_Real bestvub;
318  int bestvubidx;
319 
320  SCIPvarGetClosestVub(var, sol, set, stat, &bestvub, &bestvubidx);
321  if( bestvubidx >= 0
322  && (bestvub < *bestub || (*bestubtype < 0 && SCIPsetIsLE(set, bestvub, *bestub))) )
323  {
324  SCIP_VAR** vubvars;
325 
326  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
327  /**@todo this check is not needed for continuous variables; but allowing all but binary variables
328  * to be replaced by variable bounds seems to be buggy (wrong result on gesa2)
329  */
330  vubvars = SCIPvarGetVubVars(var);
331  assert(vubvars != NULL);
332  if( SCIPvarGetProbindex(vubvars[bestvubidx]) < SCIPvarGetProbindex(var) )
333  {
334  *bestub = bestvub;
335  *bestubtype = bestvubidx;
336  }
337  }
338  }
339 }
340 
341 /** calculates the activity of the given MIR cut */
342 static
344  SCIP_SET* set, /**< global SCIP settings */
345  SCIP_STAT* stat, /**< problem statistics */
346  SCIP_PROB* prob, /**< problem data */
347  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
348  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
349  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
350  int nvarinds /**< number of non-zero MIR coefficients */
351  )
352 {
353  SCIP_Real act;
354  int i;
355 
356  act = 0.0;
357  for( i = 0; i < nvarinds; i++ )
358  {
359  int v;
360 
361  v = varinds[i];
362  assert(0 <= v && v < prob->nvars);
363  assert(mircoef[v] != 0.0);
364 
365  act += mircoef[v] * ( sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
366  }
367 
368  return act;
369 }
370 
371 /** calculates the minimal activity of the given MIR */
372 static
374  SCIP_PROB* prob, /**< problem data */
375  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
376  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
377  int nvarinds, /**< number of non-zero MIR coefficients */
378  SCIP_Bool islocal /**< whether local bounds should be used */
379  )
380 {
381  SCIP_Real act = 0.0;
382  int i;
383 
384  for( i = 0; i < nvarinds; i++ )
385  {
386  int v;
387 
388  v = varinds[i];
389  assert(0 <= v && v < prob->nvars);
390  assert(mircoef[v] != 0.0);
391 
392  if( mircoef[v] > 0.0 )
393  {
394  act += mircoef[v] * (islocal ? SCIPvarGetLbLocal(prob->vars[v]) : SCIPvarGetLbGlobal(prob->vars[v]));
395  }
396  else
397  {
398  act += mircoef[v] * (islocal ? SCIPvarGetUbLocal(prob->vars[v]) : SCIPvarGetUbGlobal(prob->vars[v]));
399  }
400  }
401 
402  return act;
403 }
404 
405 /** adds a single row to an aggregation */
406 static
408  SCIP_SET* set, /**< global SCIP settings */
409  SCIP_Real* mircoef, /**< array of aggregation coefficients: must be of size prob->nvars */
410  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
411  int* slacksign, /**< stores the sign of the row's slack variable in summation */
412  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
413  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
414  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
415  SCIP_ROW* row, /**< row to add to the aggregation */
416  SCIP_Real weight, /**< weight of row in aggregation */
417  SCIP_Bool uselhs /**< TRUE if lhs should be used, FALSE if rhs should be used */
418  )
419 {
420  SCIP_Real sideval;
421  int r;
422  int i;
423 
424  assert(mircoef != NULL);
425  assert(mirrhs != NULL);
426  assert(slacksign != NULL);
427  assert(varused != NULL);
428  assert(varinds != NULL);
429  assert(nvarinds != NULL);
430  assert(row != NULL);
431  assert(weight != 0.0);
432 
433  r = row->lppos;
434  assert(r >= 0);
435 
436  /* update the right hand side */
437  if( uselhs )
438  {
439  slacksign[r] = -1;
440  sideval = row->lhs - row->constant;
441  if( row->integral )
442  sideval = SCIPsetFeasCeil(set, sideval); /* row is integral: round left hand side up */
443  }
444  else
445  {
446  slacksign[r] = +1;
447  sideval = row->rhs - row->constant;
448  if( row->integral )
449  sideval = SCIPsetFeasFloor(set, sideval); /* row is integral: round right hand side up */
450  }
451  (*mirrhs) += weight * sideval;
452 
453  /* add the row coefficients to the sum */
454  for( i = 0; i < row->len; ++i )
455  {
456  int idx;
457 
458  assert(row->cols[i] != NULL);
459  assert(row->cols[i]->var != NULL);
460  assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
461  assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
462  assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
463  idx = row->cols[i]->var_probindex;
464  mircoef[idx] += weight * row->vals[i];
465 
466  /* record the variable in the sparsity pattern */
467  if( !varused[idx] )
468  {
469  varused[idx] = TRUE;
470  varinds[*nvarinds] = idx;
471  (*nvarinds)++;
472  }
473  }
474 }
475 
476 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
477 static
479  SCIP_SET* set, /**< global SCIP settings */
480  SCIP_PROB* prob, /**< problem data */
481  SCIP_LP* lp, /**< LP data */
482  SCIP_Real* weights, /**< row weights in row summation */
483  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
484  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
485  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
486  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
487  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size prob->nvars */
488  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
489  int* slacksign, /**< stores the sign of the row's slack variable in summation */
490  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
491  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
492  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
493  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
494  int* nrowinds, /**< pointer to store number of used rows */
495  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
496  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
497  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
498  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
499  )
500 {
501  SCIP_Real maxweight;
502  int rowlensum;
503  int maxrank = 0;
504  int i;
505 
506  assert(prob != NULL);
507  assert(lp != NULL);
508  assert(weights != NULL);
509  assert(!SCIPsetIsZero(set, scale));
510  assert(maxweightrange >= 1.0);
511  assert(strongcgcoef != NULL);
512  assert(strongcgrhs != NULL);
513  assert(slacksign != NULL);
514  assert(varused != NULL);
515  assert(varinds != NULL);
516  assert(nvarinds != NULL);
517  assert(rowinds != NULL);
518  assert(nrowinds != NULL);
519  assert(emptyrow != NULL);
520  assert(localrowsused != NULL);
521 
522  *nvarinds = 0;
523  *localrowsused = FALSE;
524  *strongcgrhs = 0.0;
525  *emptyrow = TRUE;
526  *rowtoolong = FALSE;
527 
528  /* initialize varused array */
529  BMSclearMemoryArray(varused, prob->nvars);
530 
531  /* search the maximal absolute weight and calculate the row sparsity pattern */
532  if( *nrowinds == -1 )
533  maxweight = getMaxAbsWeightCalcSparsity(set, lp, weights, rowinds, nrowinds, &rowlensum);
534  else
535  maxweight = getMaxAbsWeight(set, lp, weights, rowinds, nrowinds, &rowlensum);
536 
537 
538  maxweight *= ABS(scale);
539 
540  /* if the total number of non-zeros is way too large, we just skip this aggregation */
541  if( rowlensum/5 > maxmksetcoefs )
542  {
543  *rowtoolong = TRUE;
544  return;
545  }
546 
547  /* calculate the row summation */
548  BMSclearMemoryArray(strongcgcoef, prob->nvars);
549  i = 0;
550  while( i < *nrowinds )
551  {
552  SCIP_ROW* row;
553  SCIP_Real weight;
554  SCIP_Real absweight;
555  SCIP_Bool skiprow;
556  int r;
557 
558  r = rowinds[i];
559  assert(0 <= i && i < lp->nrows);
560  assert(weights[r] != 0.0);
561 
562  row = lp->rows[r];
563  assert(row != NULL);
564  assert(row->len == 0 || row->cols != NULL);
565  assert(row->len == 0 || row->cols_index != NULL);
566  assert(row->len == 0 || row->vals != NULL);
567 
568  /* modifiable rows cannot be part of a strong CG row summation;
569  * local rows are only included, if the allowlocal flag is set;
570  * close to zero weights or weights outside the maximal range are ignored
571  */
572  weight = scale * weights[r];
573  absweight = ABS(weight);
574  skiprow = FALSE;
575  if( !row->modifiable && (allowlocal || !row->local)
576  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
577  {
578  /*lint --e{644}*/
579  SCIP_Bool uselhs;
580 
581  if( row->integral )
582  {
583  /* Row is integral:
584  * Decide, if we want to use the left or the right hand side of the row in the summation.
585  * If possible, use the side that leads to a positive slack value in the summation.
586  */
587  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
588  uselhs = TRUE;
589  else
590  uselhs = FALSE;
591  }
592  else
593  {
594  /* Row is NOT integral:
595  * Decide, if we have to use the left or the right hand side of the row in the summation,
596  * in order to get a positive slack variable in the summation.
597  * If not possible, ignore row in summation.
598  */
599  if( weight < 0.0 && !SCIPsetIsInfinity(set, -row->lhs) )
600  uselhs = TRUE;
601  else if( weight > 0.0 && !SCIPsetIsInfinity(set, row->rhs) )
602  uselhs = FALSE;
603  else
604  skiprow = TRUE;
605  }
606 
607  if( !skiprow )
608  {
609  /* add the row to the aggregation */
610  addRowToAggregation(set, strongcgcoef, strongcgrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
611  *emptyrow = FALSE;
612  *localrowsused = *localrowsused || row->local;
613 
614  maxrank = MAX(maxrank, row->rank);
615 
616  SCIPdebugMessage("strong CG: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
617  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
618  scale, weights[r], slacksign[r], *strongcgrhs);
619  debugRowPrint(row);
620  }
621  }
622  else
623  skiprow = TRUE;
624 
625  if( skiprow )
626  {
627  /* remove row from sparsity pattern, do not increase i, since the i-th position is filled with the last element */
628  rowinds[i] = rowinds[(*nrowinds)-1];
629  (*nrowinds)--;
630 #ifndef NDEBUG
631  slacksign[r] = 0;
632 #endif
633  }
634  else
635  ++i;
636  }
637 
638  /* check if the total number of non-zeros is too large */
639  if( *nrowinds > maxmksetcoefs )
640  *rowtoolong = TRUE;
641 
642  /* set rank of the cut */
643  if( cutrank != NULL )
644  *cutrank = maxrank + 1;
645 }
646 
647 /** builds a weighted sum of rows, and decides whether to use the left or right hand side of the rows in summation */
648 static
650  SCIP_SET* set, /**< global SCIP settings */
651  SCIP_PROB* prob, /**< problem data */
652  SCIP_LP* lp, /**< LP data */
653  SCIP_Real* weights, /**< row weights in row summation */
654  SCIP_Real knownmaxweight, /**< largest magnitude of weights. Set to 0 if compress == TRUE */
655  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
656  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
657  SCIP_Bool allowlocal, /**< should local rows be included, resulting in a locally valid summation? */
658  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
659  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
660  SCIP_Bool compress, /**< if rowinds is unknown and weights should be compressed */
661  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size prob->nvars */
662  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
663  int* slacksign, /**< stores the sign of the row's slack variable in summation */
664  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint; size prob->nvars */
665  int* varinds, /**< array to store sparsity pattern of non-zero MIR coefficients; size prob->nvars */
666  int* nvarinds, /**< pointer to store number of non-zero MIR coefficients */
667  int* rowinds, /**< array to store sparsity pattern of used rows; size lp->nrows */
668  int* nrowinds, /**< pointer to store number of used rows */
669  SCIP_Bool* emptyrow, /**< pointer to store whether the returned row is empty */
670  SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
671  SCIP_Bool* rowtoolong, /**< pointer to store whether the aggregated row is too long and thus invalid */
672  int* cutrank /**< pointer to store the rank of the returned aggregation; or NULL */
673  )
674 {
675  SCIP_Real maxweight;
676  int maxrank = 0;
677  int rowlensum;
678  int i;
679 
680  assert(prob != NULL);
681  assert(lp != NULL);
682  assert(weights != NULL);
683  assert(!SCIPsetIsZero(set, scale));
684  assert(maxweightrange >= 1.0);
685  assert(mircoef != NULL);
686  assert(mirrhs != NULL);
687  assert(slacksign != NULL);
688  assert(varused != NULL);
689  assert(varinds != NULL);
690  assert(nvarinds != NULL);
691  assert(rowinds != NULL);
692  assert(nrowinds != NULL);
693  assert(emptyrow != NULL);
694  assert(localrowsused != NULL);
695  assert(rowtoolong != NULL);
696 
697  rowlensum = 0;
698  *nvarinds = 0;
699  *mirrhs = 0.0;
700  *emptyrow = TRUE;
701  *localrowsused = FALSE;
702  *rowtoolong = FALSE;
703 
704  /* initialize varused array */
705  BMSclearMemoryArray(varused, prob->nvars);
706 
707  /* if compression of the dense weight vector is required */
708  /* search the maximal absolute weight and calculate the row sparsity pattern */
709  if( compress )
710  {
711  maxweight = getMaxAbsWeightCalcSparsity(set, lp, weights, rowinds, nrowinds, &rowlensum);
712  }
713  else
714  {
715  /* search the maximal absolute weight using the given row sparsity pattern */
716  if( knownmaxweight == -1 )
717  {
718  assert(*nrowinds > -1);
719  maxweight = getMaxAbsWeight(set, lp, weights, rowinds, nrowinds, &rowlensum);
720  }
721  else
722  maxweight = knownmaxweight;
723  }
724 
725  /* if the total number of non-zeros is way too large, we just skip this aggregation */
726  if( rowlensum/5 > maxmksetcoefs )
727  {
728  *rowtoolong = TRUE;
729  return;
730  }
731 
732  maxweight *= ABS(scale);
733 
734  /* calculate the row summation */
735  BMSclearMemoryArray(mircoef, prob->nvars);
736  i = 0;
737  while( i < *nrowinds )
738  {
739  SCIP_ROW* row;
740  SCIP_Real weight;
741  SCIP_Real absweight;
742  int r;
743 
744  r = rowinds[i];
745  assert(0 <= r && r < lp->nrows);
746  assert(weights[r] != 0.0);
747 
748  row = lp->rows[r];
749  assert(row != NULL);
750  assert(row->len == 0 || row->cols != NULL);
751  assert(row->len == 0 || row->cols_index != NULL);
752  assert(row->len == 0 || row->vals != NULL);
753 
754  /* modifiable rows cannot be part of a MIR row summation;
755  * local rows are only included, if the allowlocal flag is set;
756  * close to zero weights or weights outside the maximal range are ignored
757  */
758  weight = scale * weights[r];
759  absweight = REALABS(weight);
760  if( !row->modifiable && (allowlocal || !row->local)
761  && absweight * maxweightrange >= maxweight && !SCIPsetIsSumZero(set, weight) )
762  {
763  SCIP_Bool uselhs;
764 
765  /* choose sides for lhs/rhs of row */
766  if ( sidetypes != NULL )
767  {
768  assert( sidetypes[r] == -1 || sidetypes[r] == 0 || sidetypes[r] == 1 );
769  if ( sidetypes[r] == -1 )
770  {
771  assert( ! SCIPsetIsInfinity(set, -row->lhs) );
772  uselhs = TRUE;
773  }
774  else if ( sidetypes[r] == 1 )
775  {
776  assert( ! SCIPsetIsInfinity(set, row->rhs) );
777  uselhs = FALSE;
778  }
779  else
780  {
781  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
782  * If possible, use the side that leads to a positive slack value in the summation.
783  */
784  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
785  uselhs = TRUE;
786  else
787  uselhs = FALSE;
788  }
789  }
790  else
791  {
792  /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
793  * If possible, use the side that leads to a positive slack value in the summation.
794  */
795  if( SCIPsetIsInfinity(set, row->rhs) || (!SCIPsetIsInfinity(set, -row->lhs) && weight < 0.0) )
796  uselhs = TRUE;
797  else
798  uselhs = FALSE;
799  }
800 
801  /* add the row to the aggregation */
802  addRowToAggregation(set, mircoef, mirrhs, slacksign, varused, varinds, nvarinds, row, weight, uselhs);
803  *emptyrow = FALSE;
804  *localrowsused = *localrowsused || row->local;
805 
806  SCIPdebugMessage("MIR: %d: row <%s>, lhs = %g, rhs = %g, scale = %g, weight = %g, slacksign = %d -> rhs = %g\n",
807  r, SCIProwGetName(row), row->lhs - row->constant, row->rhs - row->constant,
808  scale, weights[r], slacksign[r], *mirrhs);
809  debugRowPrint(row);
810 
811  /* update the rank of the aggregation */
812  maxrank = MAX(maxrank, row->rank);
813 
814  ++i; /* handle next row */
815  }
816  else
817  {
818  /* remove row from sparsity pattern, do not increase i (i-th position is filled with last entry) */
819  rowinds[i] = rowinds[(*nrowinds)-1];
820  (*nrowinds)--;
821 #ifndef NDEBUG
822  slacksign[r] = 0;
823 #endif
824  }
825  }
826 
827  /* check if the total number of non-zeros is too large */
828  if( *nvarinds > maxmksetcoefs )
829  *rowtoolong = TRUE;
830 
831  /* set rank of the aggregated cut */
832  if( cutrank != NULL )
833  *cutrank = maxrank + 1;
834 }
835 
836 /** removes all nearly-zero coefficients from MIR row and relaxes the right hand side correspondingly in order to
837  * prevent numerical rounding errors
838  */
839 static
841  SCIP_SET* set, /**< global SCIP settings */
842  SCIP_PROB* prob, /**< problem data */
843  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
844  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
845  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
846  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
847  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
848  SCIP_Bool cutislocal /**< is the cut only valid locally? */
849  )
850 {
851  SCIP_Bool rhsinf;
852  int i;
853 
854  assert(prob != NULL);
855  assert(mircoef != NULL);
856  assert(mirrhs != NULL);
857  assert(varused != NULL);
858  assert(varinds != NULL);
859  assert(nvarinds != NULL);
860 
861  rhsinf = SCIPsetIsInfinity(set, *mirrhs);
862  i = 0;
863  while( i < *nvarinds )
864  {
865  int v;
866 
867  v = varinds[i];
868  assert(0 <= v && v < prob->nvars);
869  assert(varused[v]);
870 
871  if( SCIPsetIsSumZero(set, mircoef[v]) )
872  {
873  SCIP_Real bd;
874 
875  SCIPdebugMessage("coefficient of <%s> in transformed MIR row is too small: %.12f\n",
876  SCIPvarGetName(prob->vars[v]), mircoef[v]);
877 
878  /* relax the constraint such that the coefficient becomes exactly 0.0 */
879  if( SCIPsetIsPositive(set, mircoef[v]) )
880  {
881  bd = cutislocal ? SCIPvarGetLbLocal(prob->vars[v]) : SCIPvarGetLbGlobal(prob->vars[v]);
882  rhsinf = SCIPsetIsInfinity(set, -bd);
883  }
884  else if( SCIPsetIsNegative(set, mircoef[v]) )
885  {
886  bd = cutislocal ? SCIPvarGetUbLocal(prob->vars[v]) : SCIPvarGetUbGlobal(prob->vars[v]);
887  rhsinf = SCIPsetIsInfinity(set, bd);
888  }
889  else
890  bd = 0.0;
891  *mirrhs -= bd * mircoef[v];
892  mircoef[v] = 0.0;
893 
894  /* remove variable from sparsity pattern, do not increase i (i-th position is filled with last entry) */
895  varused[v] = FALSE;
896  varinds[i] = varinds[(*nvarinds)-1];
897  (*nvarinds)--;
898  }
899  else
900  ++i;
901  }
902  if( rhsinf )
903  *mirrhs = SCIPsetInfinity(set);
904 }
905 
906 /** Transform equation \f$ a*x == b \f$, \f$ lb <= x <= ub \f$ into standard form \f$ a^\prime*x^\prime == b\f$, \f$ 0 <= x^\prime <= ub^\prime \f$.
907  *
908  * Transform variables (lb or ub):
909  * \f[
910  * \begin{array}{llll}
911  * x^\prime_j := x_j - lb_j,& x_j == x^\prime_j + lb_j,& a^\prime_j == a_j,& \mbox{if lb is used in transformation} \\
912  * x^\prime_j := ub_j - x_j,& x_j == ub_j - x^\prime_j,& a^\prime_j == -a_j,& \mbox{if ub is used in transformation}
913  * \end{array}
914  * \f]
915  * and move the constant terms \f$ a_j * lb_j \f$ or \f$ a_j * ub_j \f$ to the rhs.
916  *
917  * Transform variables (vlb or vub):
918  * \f[
919  * \begin{array}{llll}
920  * x^\prime_j := x_j - (bl_j * zl_j + dl_j),& x_j == x^\prime_j + (bl_j * zl_j + dl_j),& a^\prime_j == a_j,& \mbox{if vlb is used in transf.} \\
921  * x^\prime_j := (bu_j * zu_j + du_j) - x_j,& x_j == (bu_j * zu_j + du_j) - x^\prime_j,& a^\prime_j == -a_j,& \mbox{if vub is used in transf.}
922  * \end{array}
923  * \f]
924  * move the constant terms \f$ a_j * dl_j \f$ or \f$ a_j * du_j \f$ to the rhs, and update the coefficient of the VLB variable:
925  * \f[
926  * \begin{array}{ll}
927  * a_{zl_j} := a_{zl_j} + a_j * bl_j,& \mbox{or} \\
928  * a_{zu_j} := a_{zu_j} + a_j * bu_j&
929  * \end{array}
930  * \f]
931  */
932 static
934  SCIP_SET* set, /**< global SCIP settings */
935  SCIP_STAT* stat, /**< problem statistics */
936  SCIP_PROB* prob, /**< problem data */
937  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
938  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
939  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
940  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
941  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
942  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
943  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
944  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
945  int* varsign, /**< stores the sign of the transformed variable in summation */
946  int* boundtype, /**< stores the bound used for transformed variable:
947  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
948  SCIP_Bool* freevariable, /**< stores whether a free variable was found in strong CG row -> invalid summation */
949  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
950  )
951 {
952  int i;
953 
954  assert(prob != NULL);
955  assert(strongcgcoef != NULL);
956  assert(strongcgrhs != NULL);
957  assert(varused != NULL);
958  assert(varinds != NULL);
959  assert(nvarinds != NULL);
960  assert(varsign != NULL);
961  assert(boundtype != NULL);
962  assert(freevariable != NULL);
963  assert(localbdsused != NULL);
964 
965  *freevariable = FALSE;
966  *localbdsused = FALSE;
967 
968 #ifndef NDEBUG
969  /* in debug mode, make sure that the whole array is initialized with invalid values */
970  for( i = 0; i < prob->nvars; i++ )
971  {
972  varsign[i] = 0;
973  boundtype[i] = -1;
974  }
975 #endif
976 
977  /* start with continuous variables, because using variable bounds can affect the untransformed integral
978  * variables, and these changes have to be incorporated in the transformation of the integral variables
979  * (continuous variables have largest problem indices!)
980  */
981  SCIPsortDownInt(varinds, *nvarinds);
982 
983  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
984  * substitute integral variables with best standard bound (lb, ub)
985  */
986  i = 0;
987  while( i < *nvarinds )
988  {
989  SCIP_VAR* var;
990  SCIP_Real varsol;
991  SCIP_Real bestlb;
992  SCIP_Real bestub;
993  SCIP_Bool uselb;
994  int bestlbtype;
995  int bestubtype;
996  int v;
997 
998  v = varinds[i];
999  assert(0 <= v && v < prob->nvars);
1000  assert(varused[v]);
1001 
1002  var = prob->vars[v];
1003  assert(v == SCIPvarGetProbindex(var));
1004 
1005  /* due to variable bound usage cancellation may occur;
1006  * do not increase i, since last element is copied to the i-th position
1007  */
1008  if( SCIPsetIsZero(set, strongcgcoef[v]) )
1009  {
1010  varsign[v] = +1;
1011  boundtype[v] = -1;
1012  strongcgcoef[v] = 0.0;
1013  varused[v] = FALSE;
1014  varinds[i] = varinds[(*nvarinds)-1];
1015  (*nvarinds)--;
1016  continue;
1017  }
1018 
1019  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
1020  bestlb = SCIPvarGetLbGlobal(var);
1021  bestlbtype = -1;
1022  if( allowlocal )
1023  {
1024  SCIP_Real loclb;
1025 
1026  loclb = SCIPvarGetLbLocal(var);
1027  if( SCIPsetIsGT(set, loclb, bestlb) )
1028  {
1029  bestlb = loclb;
1030  bestlbtype = -2;
1031  }
1032  }
1033  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
1034  {
1035  SCIP_Real bestvlb;
1036  int bestvlbidx;
1037 
1038  SCIPvarGetClosestVlb(var, NULL, set, stat, &bestvlb, &bestvlbidx);
1039  if( bestvlbidx >= 0
1040  && (bestvlb > bestlb || (bestlbtype < 0 && SCIPsetIsGE(set, bestvlb, bestlb))) )
1041  {
1042  bestlb = bestvlb;
1043  bestlbtype = bestvlbidx;
1044  }
1045  }
1046 
1047  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
1048  bestub = SCIPvarGetUbGlobal(var);
1049  bestubtype = -1;
1050  if( allowlocal )
1051  {
1052  SCIP_Real locub;
1053 
1054  locub = SCIPvarGetUbLocal(var);
1055  if( SCIPsetIsLT(set, locub, bestub) )
1056  {
1057  bestub = locub;
1058  bestubtype = -2;
1059  }
1060  }
1061  if( usevbds && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
1062  {
1063  SCIP_Real bestvub;
1064  int bestvubidx;
1065 
1066  SCIPvarGetClosestVub(var, NULL, set, stat, &bestvub, &bestvubidx);
1067  if( bestvubidx >= 0
1068  && (bestvub < bestub || (bestubtype < 0 && SCIPsetIsLE(set, bestvub, bestub))) )
1069  {
1070  bestub = bestvub;
1071  bestubtype = bestvubidx;
1072  }
1073  }
1074 
1075  /* check, if variable is free variable
1076  * (for continuous variable use bound, so that coefficient will be nonnegative)
1077  */
1079  && SCIPsetIsInfinity(set, -bestlb)
1080  && SCIPsetIsInfinity(set, bestub))
1082  && ((strongcgcoef[v] > 0.0 && SCIPsetIsInfinity(set, -bestlb))
1083  || (strongcgcoef[v] < 0.0 && SCIPsetIsInfinity(set, bestub)))) )
1084  {
1085  /* we found a free variable in the row with non-zero coefficient
1086  * -> strong CG row can't be transformed in standard form
1087  */
1088  *freevariable = TRUE;
1089  return;
1090  }
1091 
1092  /* select transformation bound
1093  * (for continuous variable use bound, so that coefficient will be nonnegative)
1094  */
1095  varsol = SCIPvarGetLPSol(var);
1097  uselb = (strongcgcoef[v] > 0.0);
1098  else if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
1099  uselb = TRUE;
1100  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
1101  uselb = FALSE;
1102  else if( bestlbtype == -1 ) /* prefer global standard bounds */
1103  uselb = TRUE;
1104  else if( bestubtype == -1 ) /* prefer global standard bounds */
1105  uselb = FALSE;
1106  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
1107  uselb = TRUE;
1108  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
1109  uselb = FALSE;
1110  else
1111  uselb = TRUE; /* no decision yet? just use lower bound */
1112 
1113  /* perform bound substitution */
1114  if( uselb )
1115  {
1116  assert(!SCIPsetIsInfinity(set, -bestlb));
1117 
1118  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
1119  boundtype[v] = bestlbtype;
1120  varsign[v] = +1;
1121 
1122  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
1123  if( bestlbtype < 0 )
1124  {
1125  (*strongcgrhs) -= strongcgcoef[v] * bestlb;
1126  *localbdsused = *localbdsused || (bestlbtype == -2);
1127  }
1128  else
1129  {
1130  SCIP_VAR** vlbvars = SCIPvarGetVlbVars(var);
1131  SCIP_Real* vlbcoefs = SCIPvarGetVlbCoefs(var);
1132  SCIP_Real* vlbconsts = SCIPvarGetVlbConstants(var);
1133  int zidx;
1134 
1135  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
1136  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
1137  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
1138  assert(0 <= zidx && zidx < v);
1139 
1140  (*strongcgrhs) -= strongcgcoef[v] * vlbconsts[bestlbtype];
1141  strongcgcoef[zidx] += strongcgcoef[v] * vlbcoefs[bestlbtype];
1142 
1143  /* update sparsity pattern */
1144  if( !varused[zidx] )
1145  {
1146  assert(*nvarinds < prob->nvars);
1147  varused[zidx] = TRUE;
1148  varinds[*nvarinds] = zidx;
1149  (*nvarinds)++;
1150  }
1151  }
1152  }
1153  else
1154  {
1155  assert(!SCIPsetIsInfinity(set, bestub));
1156 
1157  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
1158  boundtype[v] = bestubtype;
1159  varsign[v] = -1;
1160 
1161  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
1162  if( bestubtype < 0 )
1163  {
1164  (*strongcgrhs) -= strongcgcoef[v] * bestub;
1165  *localbdsused = *localbdsused || (bestubtype == -2);
1166  }
1167  else
1168  {
1169  SCIP_VAR** vubvars = SCIPvarGetVubVars(var);
1170  SCIP_Real* vubcoefs = SCIPvarGetVubCoefs(var);
1171  SCIP_Real* vubconsts = SCIPvarGetVubConstants(var);
1172  int zidx;
1173 
1174  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
1175  assert(SCIPvarIsActive(vubvars[bestubtype]));
1176  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
1177  assert(zidx >= 0);
1178 
1179  (*strongcgrhs) -= strongcgcoef[v] * vubconsts[bestubtype];
1180  strongcgcoef[zidx] += strongcgcoef[v] * vubcoefs[bestubtype];
1181 
1182  /* update sparsity pattern */
1183  if( !varused[zidx] )
1184  {
1185  assert(*nvarinds < prob->nvars);
1186  varused[zidx] = TRUE;
1187  varinds[*nvarinds] = zidx;
1188  (*nvarinds)++;
1189  }
1190  }
1191  }
1192 
1193 #ifndef NDEBUG
1195  assert(strongcgcoef[v]*varsign[v] > 0.0);
1196 #endif
1197 
1198  SCIPdebugMessage("strong CG var <%s>: varsign=%d, boundtype=%d, strongcgcoef=%g, lb=%g, ub=%g -> rhs=%g\n",
1199  SCIPvarGetName(var), varsign[v], boundtype[v], strongcgcoef[v], bestlb, bestub, *strongcgrhs);
1200 
1201  ++i; /*increase iterator */
1202  }
1203 }
1204 
1205 /** Transform equation \f$ a \cdot x = b; lb \leq x \leq ub \f$ into standard form
1206  * \f$ a^\prime \cdot x^\prime = b,\; 0 \leq x^\prime \leq ub' \f$.
1207  *
1208  * Transform variables (lb or ub):
1209  * \f[
1210  * \begin{array}{llll}
1211  * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \mbox{if lb is used in transformation}\\
1212  * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if ub is used in transformation}
1213  * \end{array}
1214  * \f]
1215  * and move the constant terms \f$ a_j\, lb_j \f$ or \f$ a_j\, ub_j \f$ to the rhs.
1216  *
1217  * Transform variables (vlb or vub):
1218  * \f[
1219  * \begin{array}{llll}
1220  * x^\prime_j := x_j - (bl_j\, zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \mbox{if vlb is used in transf.} \\
1221  * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if vub is used in transf.}
1222  * \end{array}
1223  * \f]
1224  * move the constant terms \f$ a_j\, dl_j \f$ or \f$ a_j\, du_j \f$ to the rhs, and update the coefficient of the VLB variable:
1225  * \f[
1226  * \begin{array}{ll}
1227  * a_{zl_j} := a_{zl_j} + a_j\, bl_j,& \mbox{or} \\
1228  * a_{zu_j} := a_{zu_j} + a_j\, bu_j &
1229  * \end{array}
1230  * \f]
1231  */
1232 static
1234  SCIP_SET* set, /**< global SCIP settings */
1235  SCIP_STAT* stat, /**< problem statistics */
1236  SCIP_PROB* prob, /**< problem data */
1237  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
1238  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
1239  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
1240  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
1241  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
1242  SCIP_Bool ignoresol, /**< should the LP solution be ignored? (eg, apply MIR to dualray) */
1243  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
1244  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
1245  * NULL for using closest bound for all variables */
1246  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
1247  * NULL for using closest bound for all variables */
1248  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
1249  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
1250  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
1251  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
1252  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
1253  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
1254  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
1255  int* varsign, /**< stores the sign of the transformed variable in summation */
1256  int* boundtype, /**< stores the bound used for transformed variable:
1257  * vlb/vub_idx, or -1 for global lb/ub, or -2 for local lb/ub */
1258  SCIP_Bool* freevariable, /**< stores whether a free variable was found in MIR row -> invalid summation */
1259  SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
1260  )
1261 {
1262  SCIP_Real* bestlbs;
1263  SCIP_Real* bestubs;
1264  int* bestlbtypes;
1265  int* bestubtypes;
1266  int i;
1267 
1268  assert(prob != NULL);
1269  assert(mircoef != NULL);
1270  assert(mirrhs != NULL);
1271  assert(varused != NULL);
1272  assert(varinds != NULL);
1273  assert(nvarinds != NULL);
1274  assert(varsign != NULL);
1275  assert(boundtype != NULL);
1276  assert(freevariable != NULL);
1277  assert(localbdsused != NULL);
1278 
1279  *freevariable = FALSE;
1280  *localbdsused = FALSE;
1281 
1282 #ifndef NDEBUG
1283  /* in debug mode, make sure that the whole array is initialized with invalid values */
1284  for( i = 0; i < prob->nvars; i++ )
1285  {
1286  varsign[i] = 0;
1287  boundtype[i] = -1;
1288  }
1289 #endif
1290 
1291  /* allocate temporary memory to store best bounds and bound types */
1292  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbs, prob->nvars) );
1293  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubs, prob->nvars) );
1294  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestlbtypes, prob->nvars) );
1295  SCIP_CALL( SCIPsetAllocBufferArray(set, &bestubtypes, prob->nvars) );
1296 
1297  /* start with continuous variables, because using variable bounds can affect the untransformed integral
1298  * variables, and these changes have to be incorporated in the transformation of the integral variables
1299  * (continuous variables have largest problem indices!)
1300  */
1301  SCIPsortDownInt(varinds, *nvarinds);
1302 
1303  /* substitute continuous variables with best standard or variable bound (lb, ub, vlb or vub),
1304  * substitute integral variables with best standard bound (lb, ub)
1305  */
1306  i = 0;
1307  while( i < *nvarinds )
1308  {
1309  SCIP_VAR* var;
1310  SCIP_Real bestlb;
1311  SCIP_Real bestub;
1312  SCIP_Bool uselb;
1313  int bestlbtype;
1314  int bestubtype;
1315  int v;
1316 
1317  v = varinds[i];
1318  assert(0 <= v && v < prob->nvars);
1319  assert(varused[v]);
1320 
1321  var = prob->vars[v];
1322  assert(v == SCIPvarGetProbindex(var));
1323 
1324  /* due to variable bound usage cancellation may occur,
1325  * do not increase i, since last element is copied to the i-th position
1326  */
1327  if( SCIPsetIsZero(set, mircoef[v]) )
1328  {
1329  varsign[v] = +1;
1330  boundtype[v] = -1;
1331  mircoef[v] = 0.0;
1332  varused[v] = FALSE;
1333  varinds[i] = varinds[(*nvarinds)-1];
1334  (*nvarinds)--;
1335  continue;
1336  }
1337 
1338  /* check if the user specified a bound to be used */
1339  if( boundsfortrans != NULL && boundsfortrans[v] > -3 )
1340  {
1341  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || ( boundsfortrans[v] == -2 || boundsfortrans[v] == -1 ));
1342 
1343  /* user has explicitly specified a bound to be used */
1344  if( boundtypesfortrans[v] == SCIP_BOUNDTYPE_LOWER )
1345  {
1346  /* user wants to use lower bound */
1347  bestlbtype = boundsfortrans[v];
1348  if( bestlbtype == -1 )
1349  bestlb = SCIPvarGetLbGlobal(var); /* use global standard lower bound */
1350  else if( bestlbtype == -2 )
1351  bestlb = SCIPvarGetLbLocal(var); /* use local standard lower bound */
1352  else
1353  {
1354  SCIP_VAR** vlbvars;
1355  SCIP_Real* vlbcoefs;
1356  SCIP_Real* vlbconsts;
1357  int k;
1358 
1359  assert(!ignoresol);
1360 
1361  /* use the given variable lower bound */
1362  vlbvars = SCIPvarGetVlbVars(var);
1363  vlbcoefs = SCIPvarGetVlbCoefs(var);
1364  vlbconsts = SCIPvarGetVlbConstants(var);
1365  k = boundsfortrans[v];
1366  assert(k >= 0 && k < SCIPvarGetNVlbs(var));
1367  assert(vlbvars != NULL);
1368  assert(vlbcoefs != NULL);
1369  assert(vlbconsts != NULL);
1370 
1371  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
1372  if( SCIPvarGetProbindex(vlbvars[k]) < v )
1373  bestlb = vlbcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[k]) : SCIPsolGetVal(sol, set, stat, vlbvars[k])) + vlbconsts[k];
1374  else
1375  {
1376  bestlbtype = -1; /* fall back to global standard bound */
1377  bestlb = SCIPvarGetLbGlobal(var);
1378  }
1379  }
1380 
1381  assert(!SCIPsetIsInfinity(set, -bestlb));
1382  uselb = TRUE;
1383 
1384  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
1385  findBestUb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestub, &bestubtype);
1386  }
1387  else
1388  {
1389  assert(boundtypesfortrans[v] == SCIP_BOUNDTYPE_UPPER);
1390 
1391  /* user wants to use upper bound */
1392  bestubtype = boundsfortrans[v];
1393  if( bestubtype == -1 )
1394  bestub = SCIPvarGetUbGlobal(var); /* use global standard upper bound */
1395  else if( bestubtype == -2 )
1396  bestub = SCIPvarGetUbLocal(var); /* use local standard upper bound */
1397  else
1398  {
1399  SCIP_VAR** vubvars;
1400  SCIP_Real* vubcoefs;
1401  SCIP_Real* vubconsts;
1402  int k;
1403 
1404  assert(!ignoresol);
1405 
1406  /* use the given variable upper bound */
1407  vubvars = SCIPvarGetVubVars(var);
1408  vubcoefs = SCIPvarGetVubCoefs(var);
1409  vubconsts = SCIPvarGetVubConstants(var);
1410  k = boundsfortrans[v];
1411  assert(k >= 0 && k < SCIPvarGetNVubs(var));
1412  assert(vubvars != NULL);
1413  assert(vubcoefs != NULL);
1414  assert(vubconsts != NULL);
1415 
1416  /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
1417  if( SCIPvarGetProbindex(vubvars[k]) < v )
1418  bestub = vubcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vubvars[k]) : SCIPsolGetVal(sol, set, stat, vubvars[k])) + vubconsts[k];
1419  else
1420  {
1421  bestubtype = -1; /* fall back to global standard bound */
1422  bestub = SCIPvarGetUbGlobal(var);
1423  }
1424  }
1425 
1426  assert(!SCIPsetIsInfinity(set, bestub));
1427  uselb = FALSE;
1428 
1429  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
1430  findBestLb(set, stat, var, sol, usevbds && fixintegralrhs, allowlocal && fixintegralrhs, &bestlb, &bestlbtype);
1431  }
1432  }
1433  else
1434  {
1435  SCIP_Real varsol;
1436 
1437  /* bound selection should be done automatically */
1438 
1439  /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
1440  findBestLb(set, stat, var, sol, usevbds, allowlocal, &bestlb, &bestlbtype);
1441 
1442  /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
1443  findBestUb(set, stat, var, sol, usevbds, allowlocal, &bestub, &bestubtype);
1444 
1445  /* check, if variable is free variable */
1446  if( SCIPsetIsInfinity(set, -bestlb) && SCIPsetIsInfinity(set, bestub) )
1447  {
1448  /* we found a free variable in the row with non-zero coefficient
1449  * -> MIR row can't be transformed in standard form
1450  */
1451  *freevariable = TRUE;
1452  goto TERMINATE;
1453  }
1454 
1455  if( !ignoresol )
1456  {
1457  /* select transformation bound */
1458  varsol = (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var));
1459 
1460  if( SCIPsetIsInfinity(set, bestub) ) /* if there is no ub, use lb */
1461  uselb = TRUE;
1462  else if( SCIPsetIsInfinity(set, -bestlb) ) /* if there is no lb, use ub */
1463  uselb = FALSE;
1464  else if( SCIPsetIsLT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
1465  uselb = TRUE;
1466  else if( SCIPsetIsGT(set, varsol, (1.0 - boundswitch) * bestlb + boundswitch * bestub) )
1467  uselb = FALSE;
1468  else if( bestlbtype == -1 ) /* prefer global standard bounds */
1469  uselb = TRUE;
1470  else if( bestubtype == -1 ) /* prefer global standard bounds */
1471  uselb = FALSE;
1472  else if( bestlbtype >= 0 ) /* prefer variable bounds over local bounds */
1473  uselb = TRUE;
1474  else if( bestubtype >= 0 ) /* prefer variable bounds over local bounds */
1475  uselb = FALSE;
1476  else
1477  uselb = TRUE; /* no decision yet? just use lower bound */
1478  }
1479  else
1480  {
1481  SCIP_Real glbub = SCIPvarGetUbGlobal(var);
1482  SCIP_Real glblb = SCIPvarGetLbGlobal(var);
1483  SCIP_Real distlb = REALABS(glblb - bestlb);
1484  SCIP_Real distub = REALABS(glbub - bestub);
1485 
1486  assert(!SCIPsetIsInfinity(set, -bestlb) || !SCIPsetIsInfinity(set, bestub));
1487 
1488  if( SCIPsetIsInfinity(set, -bestlb) )
1489  uselb = FALSE;
1490  else if( !SCIPsetIsNegative(set, bestlb) )
1491  {
1492  if( SCIPsetIsInfinity(set, bestub) )
1493  uselb = TRUE;
1494  else if( SCIPsetIsZero(set, glblb) )
1495  uselb = TRUE;
1496  else if( SCIPsetIsLE(set, distlb, distub) )
1497  uselb = TRUE;
1498  else
1499  uselb = FALSE;
1500  }
1501  else
1502  {
1503  assert(!SCIPsetIsInfinity(set, -bestlb));
1504  uselb = TRUE;
1505  }
1506  }
1507  }
1508 
1509  /* remember given/best bounds and types */
1510  bestlbs[v] = bestlb;
1511  bestubs[v] = bestub;
1512  bestlbtypes[v] = bestlbtype;
1513  bestubtypes[v] = bestubtype;
1514 
1515  /* perform bound substitution */
1516  if( uselb )
1517  {
1518  assert(!SCIPsetIsInfinity(set, -bestlb));
1519 
1520  /* use lower bound as transformation bound: x'_j := x_j - lb_j */
1521  boundtype[v] = bestlbtype;
1522  varsign[v] = +1;
1523 
1524  /* standard (bestlbtype < 0) or variable (bestlbtype >= 0) lower bound? */
1525  if( bestlbtype < 0 )
1526  {
1527  (*mirrhs) -= mircoef[v] * bestlb;
1528  *localbdsused = *localbdsused || (bestlbtype == -2);
1529  }
1530  else
1531  {
1532  SCIP_VAR** vlbvars;
1533  SCIP_Real* vlbcoefs;
1534  SCIP_Real* vlbconsts;
1535  int zidx;
1536 
1537  vlbvars = SCIPvarGetVlbVars(var);
1538  vlbcoefs = SCIPvarGetVlbCoefs(var);
1539  vlbconsts = SCIPvarGetVlbConstants(var);
1540  assert(vlbvars != NULL);
1541  assert(vlbcoefs != NULL);
1542  assert(vlbconsts != NULL);
1543 
1544  assert(0 <= bestlbtype && bestlbtype < SCIPvarGetNVlbs(var));
1545  assert(SCIPvarIsActive(vlbvars[bestlbtype]));
1546  zidx = SCIPvarGetProbindex(vlbvars[bestlbtype]);
1547  assert(0 <= zidx && zidx < v);
1548 
1549  (*mirrhs) -= mircoef[v] * vlbconsts[bestlbtype];
1550  mircoef[zidx] += mircoef[v] * vlbcoefs[bestlbtype];
1551 
1552  /* update sparsity pattern */
1553  if( !varused[zidx] )
1554  {
1555  assert(*nvarinds < prob->nvars);
1556  varused[zidx] = TRUE;
1557  varinds[*nvarinds] = zidx;
1558  (*nvarinds)++;
1559  }
1560  }
1561  }
1562  else
1563  {
1564  assert(!SCIPsetIsInfinity(set, bestub));
1565 
1566  /* use upper bound as transformation bound: x'_j := ub_j - x_j */
1567  boundtype[v] = bestubtype;
1568  varsign[v] = -1;
1569 
1570  /* standard (bestubtype < 0) or variable (bestubtype >= 0) upper bound? */
1571  if( bestubtype < 0 )
1572  {
1573  (*mirrhs) -= mircoef[v] * bestub;
1574  *localbdsused = *localbdsused || (bestubtype == -2);
1575  }
1576  else
1577  {
1578  SCIP_VAR** vubvars;
1579  SCIP_Real* vubcoefs;
1580  SCIP_Real* vubconsts;
1581  int zidx;
1582 
1583  vubvars = SCIPvarGetVubVars(var);
1584  vubcoefs = SCIPvarGetVubCoefs(var);
1585  vubconsts = SCIPvarGetVubConstants(var);
1586  assert(vubvars != NULL);
1587  assert(vubcoefs != NULL);
1588  assert(vubconsts != NULL);
1589 
1590  assert(0 <= bestubtype && bestubtype < SCIPvarGetNVubs(var));
1591  assert(SCIPvarIsActive(vubvars[bestubtype]));
1592  zidx = SCIPvarGetProbindex(vubvars[bestubtype]);
1593  assert(zidx >= 0);
1594 
1595  (*mirrhs) -= mircoef[v] * vubconsts[bestubtype];
1596  mircoef[zidx] += mircoef[v] * vubcoefs[bestubtype];
1597 
1598  /* update sparsity pattern */
1599  if( !varused[zidx] )
1600  {
1601  assert(*nvarinds < prob->nvars);
1602  varused[zidx] = TRUE;
1603  varinds[*nvarinds] = zidx;
1604  (*nvarinds)++;
1605  }
1606  }
1607  }
1608  ++i; /* increase iterator */
1609 
1610 #ifdef SCIP_DEBUG
1611  if( bestlbtype >= 0 )
1612  {
1613  assert(bestlbtype < SCIPvarGetNVlbs(var));
1614  assert(SCIPvarGetVlbVars(var) != NULL);
1615  assert(SCIPvarGetVlbCoefs(var) != NULL);
1616  assert(SCIPvarGetVlbConstants(var) != NULL);
1617  }
1618  if( bestubtype >= 0 )
1619  {
1620  assert(bestubtype < SCIPvarGetNVubs(var));
1621  assert(SCIPvarGetVubVars(var) != NULL);
1622  assert(SCIPvarGetVubCoefs(var) != NULL);
1623  assert(SCIPvarGetVubConstants(var) != NULL);
1624  }
1625 
1626  if( !ignoresol )
1627  {
1628  SCIPdebugMessage("MIR var <%s>: varsign=%d, boundtype=%d, mircoef=%g, base=%d, sol=%g, lb=%g, ub=%g, vlb=%g<%s>%+g, vub=%g<%s>%+g -> rhs=%g\n",
1629  SCIPvarGetName(var), varsign[v], boundtype[v], mircoef[v],
1631  (sol == NULL ? SCIPvarGetLPSol(var) : SCIPsolGetVal(sol, set, stat, var)), bestlb, bestub,
1632  bestlbtype >= 0 ? SCIPvarGetVlbCoefs(var)[bestlbtype] : 0.0,
1633  bestlbtype >= 0 ? SCIPvarGetName(SCIPvarGetVlbVars(var)[bestlbtype]) : "-",
1634  bestlbtype >= 0 ? SCIPvarGetVlbConstants(var)[bestlbtype] : bestlb,
1635  bestubtype >= 0 ? SCIPvarGetVubCoefs(var)[bestubtype] : 0.0,
1636  bestubtype >= 0 ? SCIPvarGetName(SCIPvarGetVubVars(var)[bestubtype]) : "-",
1637  bestubtype >= 0 ? SCIPvarGetVubConstants(var)[bestubtype] : bestub,
1638  *mirrhs);
1639  }
1640  else
1641  {
1642  SCIPdebugMessage("MIR var <%s>: varsign=%d, boundtype=%d, mircoef=%g, base=%d, lb=%g, ub=%g, vlb=%g<%s>%+g, vub=%g<%s>%+g -> rhs=%g\n",
1643  SCIPvarGetName(var), varsign[v], boundtype[v], mircoef[v],
1645  bestlb, bestub,
1646  bestlbtype >= 0 ? SCIPvarGetVlbCoefs(var)[bestlbtype] : 0.0,
1647  bestlbtype >= 0 ? SCIPvarGetName(SCIPvarGetVlbVars(var)[bestlbtype]) : "-",
1648  bestlbtype >= 0 ? SCIPvarGetVlbConstants(var)[bestlbtype] : bestlb,
1649  bestubtype >= 0 ? SCIPvarGetVubCoefs(var)[bestubtype] : 0.0,
1650  bestubtype >= 0 ? SCIPvarGetName(SCIPvarGetVubVars(var)[bestubtype]) : "-",
1651  bestubtype >= 0 ? SCIPvarGetVubConstants(var)[bestubtype] : bestub,
1652  *mirrhs);
1653  }
1654 #endif
1655  }
1656 
1657  if( fixintegralrhs )
1658  {
1659  SCIP_Real f0;
1660 
1661  /* check if rhs is fractional */
1662  f0 = SCIPsetSumFrac(set, *mirrhs);
1663  if( f0 < minfrac || f0 > maxfrac )
1664  {
1665  SCIP_Real bestviolgain;
1666  SCIP_Real bestnewf0;
1667  int bestv;
1668 
1669  /* choose complementation of one variable differently such that f0 is in correct range */
1670  bestv = -1;
1671  bestviolgain = -1e+100;
1672  bestnewf0 = 1.0;
1673  for( i = 0; i < *nvarinds; i++ )
1674  {
1675  int v;
1676 
1677  v = varinds[i];
1678  assert(0 <= v && v < prob->nvars);
1679  assert(varused[v]);
1680  assert(!SCIPsetIsZero(set, mircoef[v]));
1681 
1682  if( boundtype[v] < 0
1683  && ((varsign[v] == +1 && !SCIPsetIsInfinity(set, bestubs[v]) && bestubtypes[v] < 0)
1684  || (varsign[v] == -1 && !SCIPsetIsInfinity(set, -bestlbs[v]) && bestlbtypes[v] < 0)) )
1685  {
1686  SCIP_Real fj;
1687  SCIP_Real newfj;
1688  SCIP_Real newrhs;
1689  SCIP_Real newf0;
1690  SCIP_Real solval;
1691  SCIP_Real viol;
1692  SCIP_Real newviol;
1693  SCIP_Real violgain;
1694 
1695  /* currently: a'_j = varsign * a_j -> f'_j = a'_j - floor(a'_j)
1696  * after complementation: a''_j = -varsign * a_j -> f''_j = a''_j - floor(a''_j) = 1 - f'_j
1697  * rhs'' = rhs' + varsign * a_j * (lb_j - ub_j)
1698  * cut violation from f0 and fj: f'_0 - f'_j * x'_j
1699  * after complementation: f''_0 - f''_j * x''_j
1700  *
1701  * for continuous variables, we just set f'_j = f''_j = |a'_j|
1702  */
1703  newrhs = *mirrhs + varsign[v] * mircoef[v] * (bestlbs[v] - bestubs[v]);
1704  newf0 = SCIPsetSumFrac(set, newrhs);
1705  if( newf0 < minfrac || newf0 > maxfrac )
1706  continue;
1707  if( SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
1708  {
1709  fj = REALABS(mircoef[v]);
1710  newfj = fj;
1711  }
1712  else
1713  {
1714  fj = SCIPsetFrac(set, varsign[v] * mircoef[v]);
1715  newfj = SCIPsetFrac(set, -varsign[v] * mircoef[v]);
1716  }
1717 
1718  if( !ignoresol )
1719  {
1720  solval = (sol == NULL ? SCIPvarGetLPSol(prob->vars[v]) : SCIPsolGetVal(sol, set, stat, prob->vars[v]));
1721  viol = f0 - fj * (varsign[v] == +1 ? solval - bestlbs[v] : bestubs[v] - solval);
1722  newviol = newf0 - newfj * (varsign[v] == -1 ? solval - bestlbs[v] : bestubs[v] - solval);
1723  violgain = newviol - viol;
1724  }
1725  else
1726  {
1727  /* todo: this should be done, this can improve the dualray significantly */
1728  SCIPerrorMessage("Cannot handle closest bounds with ignoring the LP solution.\n");
1729  return SCIP_INVALIDCALL;
1730  }
1731 
1732  /* prefer larger violations; for equal violations, prefer smaller f0 values since then the possibility that
1733  * we f_j > f_0 is larger and we may improve some coefficients in rounding
1734  */
1735  if( SCIPsetIsGT(set, violgain, bestviolgain)
1736  || (SCIPsetIsGE(set, violgain, bestviolgain) && newf0 < bestnewf0) )
1737  {
1738  bestv = v;
1739  bestviolgain = violgain;
1740  bestnewf0 = newf0;
1741  }
1742  }
1743  }
1744 
1745  if( bestv >= 0 )
1746  {
1747  assert(bestv < prob->nvars);
1748  assert(boundtype[bestv] < 0);
1749  assert(!SCIPsetIsInfinity(set, -bestlbs[bestv]));
1750  assert(!SCIPsetIsInfinity(set, bestubs[bestv]));
1751 
1752  /* switch the complementation of this variable */
1753  (*mirrhs) += varsign[bestv] * mircoef[bestv] * (bestlbs[bestv] - bestubs[bestv]);
1754  if( varsign[bestv] == +1 )
1755  {
1756  /* switch to upper bound */
1757  assert(bestubtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
1758  boundtype[bestv] = bestubtypes[bestv];
1759  varsign[bestv] = -1;
1760  }
1761  else
1762  {
1763  /* switch to lower bound */
1764  assert(bestlbtypes[bestv] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
1765  boundtype[bestv] = bestlbtypes[bestv];
1766  varsign[bestv] = +1;
1767  }
1768  *localbdsused = *localbdsused || (boundtype[bestv] == -2);
1769  }
1770  }
1771  }
1772 
1773  TERMINATE:
1774 
1775  /*free temporary memory */
1776  SCIPsetFreeBufferArray(set, &bestubtypes);
1777  SCIPsetFreeBufferArray(set, &bestlbtypes);
1778  SCIPsetFreeBufferArray(set, &bestubs);
1779  SCIPsetFreeBufferArray(set, &bestlbs);
1780 
1781  return SCIP_OKAY;
1782 }
1783 
1784 /** Calculate fractionalities \f$ f_0 := b - down(b) \f$, \f$ f_j := a^\prime_j - down(a^\prime_j) \f$ and
1785  * integer \f$ k >= 1 \f$ with \f$ 1/(k + 1) <= f_0 < 1/k \f$ and \f$ (=> k = up(1/f_0) + 1) \f$
1786  * integer \f$ 1 <= p_j <= k \f$ with \f$ f_0 + ((p_j - 1) * (1 - f_0)/k) < f_j <= f_0 + (p_j * (1 - f_0)/k)\f$ \f$ (=> p_j = up( k*(f_j - f_0)/(1 - f_0) )) \f$
1787  * and derive strong CG cut \f$ \tilde{a}*x^\prime <= down(b) \f$
1788  * \f[
1789  * \begin{array}{rll}
1790  * integers : & \tilde{a}_j = down(a^\prime_j) &, if \qquad f_j <= f_0 \\
1791  * & \tilde{a}_j = down(a^\prime_j) + p_j/(k + 1) &, if \qquad f_j > f_0 \\
1792  * continuous:& \tilde{a}_j = 0 &, if \qquad a^\prime_j >= 0 \\
1793  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_j < 0
1794  * \end{array}
1795  * \f]
1796  *
1797  * Transform inequality back to \f$ \hat{a}*x <= rhs \f$:
1798  *
1799  * (lb or ub):
1800  * \f[
1801  * \begin{array}{lllll}
1802  * x^\prime_j := x_j - lb_j,& x_j == x^\prime_j + lb_j,& a^\prime_j == a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{if lb was used in transformation} \\
1803  * x^\prime_j := ub_j - x_j,& x_j == ub_j - x^\prime_j,& a^\prime_j == -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{if ub was used in transformation}
1804  * \end{array}
1805  * \f]
1806  * \f[
1807  * and move the constant terms
1808  * \begin{array}{rl}
1809  * -\tilde{a}_j * lb_j == -\hat{a}_j * lb_j, & \mbox{or} \\
1810  * \tilde{a}_j * ub_j == -\hat{a}_j * ub_j &
1811  * \end{array}
1812  * \f]
1813  * to the rhs.
1814  *
1815  * (vlb or vub):
1816  * \f[
1817  * \begin{array}{lllll}
1818  * x^\prime_j := x_j - (bl_j * zl_j + dl_j),& x_j == x^\prime_j + (bl_j * zl_j + dl_j),& a^\prime_j == a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{(vlb)} \\
1819  * x^\prime_j := (bu_j * zu_j + du_j) - x_j,& x_j == (bu_j * zu_j + du_j) - x^\prime_j,& a^\prime_j == -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{(vub)}
1820  * \end{array}
1821  * \f]
1822  * move the constant terms
1823  * \f[
1824  * \begin{array}{rl}
1825  * -\tilde{a}_j * dl_j == -\hat{a}_j * dl_j,& \mbox{or} \\
1826  * \tilde{a}_j * du_j == -\hat{a}_j * du_j &
1827  * \end{array}
1828  * \f]
1829  * to the rhs, and update the VB variable coefficients:
1830  * \f[
1831  * \begin{array}{ll}
1832  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j * bl_j == \hat{a}_{zl_j} - \hat{a}_j * bl_j,& \mbox{or} \\
1833  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j * bu_j == \hat{a}_{zu_j} - \hat{a}_j * bu_j &
1834  * \end{array}
1835  * \f]
1836  */
1837 static
1839  SCIP_SET* set, /**< global SCIP settings */
1840  SCIP_PROB* prob, /**< problem data */
1841  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
1842  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
1843  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
1844  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
1845  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
1846  int* varsign, /**< stores the sign of the transformed variable in summation */
1847  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub)*/
1848  SCIP_Real f0, /**< fractional value of rhs */
1849  SCIP_Real k /**< factor to strengthen strongcg cut */
1850  )
1851 {
1852  SCIP_Real onedivoneminusf0;
1853  int nintvars;
1854  int i;
1855 
1856  assert(prob != NULL);
1857  assert(strongcgcoef != NULL);
1858  assert(strongcgrhs != NULL);
1859  assert(varused != NULL);
1860  assert(varinds != NULL);
1861  assert(nvarinds != NULL);
1862  assert(varsign != NULL);
1863  assert(0.0 < f0 && f0 < 1.0);
1864 
1865  onedivoneminusf0 = 1.0 / (1.0 - f0);
1866  nintvars = prob->nvars - prob->ncontvars;
1867 
1868  /* start with integer variables, since the variable bound substitutions can add up to the integer cut coefficients;
1869  * loop backwards to be able to delete coefficients from the sparsity pattern
1870  */
1871  SCIPsortDownInt(varinds, *nvarinds);
1872 
1873  /* integer variables */
1874  for( i = *nvarinds-1; i >= 0; i-- )
1875  {
1876  SCIP_VAR* var;
1877  SCIP_Real aj;
1878  SCIP_Real downaj;
1879  SCIP_Real cutaj;
1880  SCIP_Real fj;
1881  int v;
1882 
1883  v = varinds[i];
1884  assert(0 <= v && v < prob->nvars);
1885  assert(varused[v]);
1886 
1887  /* stop this loop if we reached the continuous variables */
1888  if( v >= nintvars )
1889  {
1890  assert(!SCIPvarIsIntegral(prob->vars[v]));
1891  assert(SCIPvarGetType(prob->vars[v]) == SCIP_VARTYPE_CONTINUOUS);
1892  break;
1893  }
1894 
1895  var = prob->vars[v];
1896  assert(var != NULL);
1897  assert(SCIPvarIsIntegral(var));
1898  assert(SCIPvarGetProbindex(var) == v);
1899  assert(boundtype[v] == -1 || boundtype[v] == -2);
1900  assert(varsign[v] == +1 || varsign[v] == -1);
1901 
1902  /* calculate the coefficient in the retransformed cut */
1903  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
1904  downaj = SCIPsetFloor(set, aj);
1905  fj = aj - downaj;
1906 
1907  if( SCIPsetIsSumLE(set, fj, f0) )
1908  cutaj = varsign[v] * downaj; /* a^_j */
1909  else
1910  {
1911  SCIP_Real pj;
1912 
1913  pj = SCIPsetCeil(set, k * (fj - f0) * onedivoneminusf0);
1914  assert(pj >= 0); /* should be >= 1, but due to rounding bias can be 0 if fj almost equal to f0 */
1915  assert(pj <= k);
1916  cutaj = varsign[v] * (downaj + pj / (k + 1)); /* a^_j */
1917  }
1918 
1919 
1920  /* remove zero cut coefficients from sparsity pattern */
1921  if( SCIPsetIsZero(set, cutaj) )
1922  {
1923  strongcgcoef[v] = 0.0;
1924  varused[v] = FALSE;
1925  varinds[i] = varinds[(*nvarinds)-1];
1926  (*nvarinds)--;
1927  continue;
1928  }
1929 
1930  strongcgcoef[v] = cutaj;
1931 
1932  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
1933  if( varsign[v] == +1 )
1934  {
1935  /* lower bound was used */
1936  if( boundtype[v] == -1 )
1937  {
1938  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
1939  (*strongcgrhs) += cutaj * SCIPvarGetLbGlobal(var);
1940  }
1941  else
1942  {
1943  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
1944  (*strongcgrhs) += cutaj * SCIPvarGetLbLocal(var);
1945  }
1946  }
1947  else
1948  {
1949  /* upper bound was used */
1950  if( boundtype[v] == -1 )
1951  {
1952  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
1953  (*strongcgrhs) += cutaj * SCIPvarGetUbGlobal(var);
1954  }
1955  else
1956  {
1957  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
1958  (*strongcgrhs) += cutaj * SCIPvarGetUbLocal(var);
1959  }
1960  }
1961  }
1962 
1963  /* continuous variables */
1964  for( ; i >= 0; i-- )
1965  {
1966  int v;
1967 
1968  v = varinds[i];
1969  assert(0 <= v && v < prob->nvars);
1970  assert(varused[v]);
1971 
1972 #ifndef NDEBUG
1973  /* in a strong CG cut, cut coefficients of continuous variables are always zero; check this in debug mode */
1974  {
1975  SCIP_VAR* var;
1976  SCIP_Real aj;
1977 
1978  var = prob->vars[v];
1979  assert(var != NULL);
1980  assert(!SCIPvarIsIntegral(var));
1981  assert(SCIPvarGetProbindex(var) == v);
1982  assert(varsign[v] == +1 || varsign[v] == -1);
1983 
1984  /* calculate the coefficient in the retransformed cut */
1985  aj = varsign[v] * strongcgcoef[v]; /* a'_j */
1986  assert(aj >= 0.0);
1987  }
1988 #endif
1989 
1990  strongcgcoef[v] = 0.0;
1991 
1992  /* remove zero cut coefficients from sparsity pattern */
1993  varused[v] = FALSE;
1994  varinds[i] = varinds[(*nvarinds)-1];
1995  (*nvarinds)--;
1996  }
1997 }
1998 
1999 /** Calculate fractionalities \f$ f_0 := b - down(b), f_j := a^\prime_j - down(a^\prime_j) \f$, and derive MIR cut \f$ \tilde{a} \cdot x' \leq down(b) \f$
2000  * \f[
2001  * \begin{array}{rll}
2002  * integers :& \tilde{a}_j = down(a^\prime_j), & if \qquad f_j \leq f_0 \\
2003  * & \tilde{a}_j = down(a^\prime_j) + (f_j - f_0)/(1 - f_0),& if \qquad f_j > f_0 \\
2004  * continuous:& \tilde{a}_j = 0, & if \qquad a^\prime_j \geq 0 \\
2005  * & \tilde{a}_j = a^\prime_j/(1 - f_0), & if \qquad a^\prime_j < 0
2006  * \end{array}
2007  * \f]
2008  *
2009  * Transform inequality back to \f$ \hat{a} \cdot x \leq rhs \f$:
2010  *
2011  * (lb or ub):
2012  * \f[
2013  * \begin{array}{lllll}
2014  * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{if lb was used in transformation} \\
2015  * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{if ub was used in transformation}
2016  * \end{array}
2017  * \f]
2018  * and move the constant terms
2019  * \f[
2020  * \begin{array}{cl}
2021  * -\tilde{a}_j \cdot lb_j = -\hat{a}_j \cdot lb_j,& \mbox{or} \\
2022  * \tilde{a}_j \cdot ub_j = -\hat{a}_j \cdot ub_j &
2023  * \end{array}
2024  * \f]
2025  * to the rhs.
2026  *
2027  * (vlb or vub):
2028  * \f[
2029  * \begin{array}{lllll}
2030  * x^\prime_j := x_j - (bl_j \cdot zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{(vlb)} \\
2031  * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{(vub)}
2032  * \end{array}
2033  * \f]
2034  * move the constant terms
2035  * \f[
2036  * \begin{array}{cl}
2037  * -\tilde{a}_j\, dl_j = -\hat{a}_j\, dl_j,& \mbox{or} \\
2038  * \tilde{a}_j\, du_j = -\hat{a}_j\, du_j &
2039  * \end{array}
2040  * \f]
2041  * to the rhs, and update the VB variable coefficients:
2042  * \f[
2043  * \begin{array}{ll}
2044  * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j\, bl_j = \hat{a}_{zl_j} - \hat{a}_j\, bl_j,& \mbox{or} \\
2045  * \hat{a}_{zu_j} := \hat{a}_{zu_j} + \tilde{a}_j\, bu_j = \hat{a}_{zu_j} - \hat{a}_j\, bu_j &
2046  * \end{array}
2047  * \f]
2048  */
2049 static
2051  SCIP_SET* set, /**< global SCIP settings */
2052  SCIP_PROB* prob, /**< problem data */
2053  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
2054  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
2055  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
2056  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
2057  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
2058  int* varsign, /**< stores the sign of the transformed variable in summation */
2059  int* boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub) */
2060  SCIP_Real f0 /**< fractional value of rhs */
2061  )
2062 {
2063  SCIP_Real onedivoneminusf0;
2064  int i;
2065 
2066  assert(prob != NULL);
2067  assert(mircoef != NULL);
2068  assert(mirrhs != NULL);
2069  assert(varused != NULL);
2070  assert(varinds != NULL);
2071  assert(nvarinds != NULL);
2072  assert(varsign != NULL);
2073  assert(0.0 < f0 && f0 < 1.0);
2074 
2075  onedivoneminusf0 = 1.0 / (1.0 - f0);
2076 
2077  /* Loop backwards to be able to delete coefficients from the sparsity pattern. Additionally, the variable bound
2078  * substitutions are only used in such a way that a variable of higher index is substituted by a variable of a
2079  * lower index. Therefore, we must loop backwards.
2080  */
2081  SCIPsortDownInt(varinds, *nvarinds);
2082 
2083  for( i = *nvarinds-1; i >= 0; i-- )
2084  {
2085  SCIP_VAR* var;
2086  SCIP_Real cutaj;
2087  int v;
2088 
2089  v = varinds[i];
2090  assert(0 <= v && v < prob->nvars);
2091  assert(varused[v]);
2092 
2093  var = prob->vars[v];
2094  assert(var != NULL);
2095  assert(SCIPvarGetProbindex(var) == v);
2096  assert(varsign[v] == +1 || varsign[v] == -1);
2097 
2098  /* calculate the coefficient in the retransformed cut */
2099  if( SCIPvarIsIntegral(var) )
2100  {
2101  SCIP_Real aj;
2102  SCIP_Real downaj;
2103  SCIP_Real fj;
2104 
2105  aj = varsign[v] * mircoef[v]; /* a'_j */
2106  downaj = SCIPsetFloor(set, aj);
2107  fj = aj - downaj;
2108 
2109  if( SCIPsetIsSumLE(set, fj, f0) )
2110  cutaj = varsign[v] * downaj; /* a^_j */
2111  else
2112  cutaj = varsign[v] * (downaj + (fj - f0) * onedivoneminusf0); /* a^_j */
2113  }
2114  else
2115  {
2116  SCIP_Real aj;
2117 
2118  aj = varsign[v] * mircoef[v]; /* a'_j */
2119  if( aj >= 0.0 )
2120  cutaj = 0.0;
2121  else
2122  cutaj = varsign[v] * aj * onedivoneminusf0; /* a^_j */
2123  }
2124 
2125  /* remove zero cut coefficients from sparsity pattern */
2126  if( SCIPsetIsZero(set, cutaj) )
2127  {
2128  mircoef[v] = 0.0;
2129  varused[v] = FALSE;
2130  varinds[i] = varinds[(*nvarinds)-1];
2131  (*nvarinds)--;
2132  continue;
2133  }
2134 
2135  mircoef[v] = cutaj;
2136 
2137  /* check for variable bound use */
2138  if( boundtype[v] < 0 )
2139  {
2140  /* standard bound */
2141 
2142  /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
2143  if( varsign[v] == +1 )
2144  {
2145  /* lower bound was used */
2146  if( boundtype[v] == -1 )
2147  {
2148  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(var)));
2149  (*mirrhs) += cutaj * SCIPvarGetLbGlobal(var);
2150  }
2151  else
2152  {
2153  assert(!SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
2154  (*mirrhs) += cutaj * SCIPvarGetLbLocal(var);
2155  }
2156  }
2157  else
2158  {
2159  /* upper bound was used */
2160  if( boundtype[v] == -1 )
2161  {
2162  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(var)));
2163  (*mirrhs) += cutaj * SCIPvarGetUbGlobal(var);
2164  }
2165  else
2166  {
2167  assert(!SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
2168  (*mirrhs) += cutaj * SCIPvarGetUbLocal(var);
2169  }
2170  }
2171  }
2172  else
2173  {
2174  SCIP_VAR** vbz;
2175  SCIP_Real* vbb;
2176  SCIP_Real* vbd;
2177  int vbidx;
2178  int zidx;
2179 
2180  /* variable bound */
2181  vbidx = boundtype[v];
2182 
2183  /* change mirrhs and cutaj of integer variable z_j of variable bound */
2184  if( varsign[v] == +1 )
2185  {
2186  /* variable lower bound was used */
2187  assert(0 <= vbidx && vbidx < SCIPvarGetNVlbs(var));
2188  vbz = SCIPvarGetVlbVars(var);
2189  vbb = SCIPvarGetVlbCoefs(var);
2190  vbd = SCIPvarGetVlbConstants(var);
2191  }
2192  else
2193  {
2194  /* variable upper bound was used */
2195  assert(0 <= vbidx && vbidx < SCIPvarGetNVubs(var));
2196  vbz = SCIPvarGetVubVars(var);
2197  vbb = SCIPvarGetVubCoefs(var);
2198  vbd = SCIPvarGetVubConstants(var);
2199  }
2200  assert(SCIPvarIsActive(vbz[vbidx]));
2201  zidx = SCIPvarGetProbindex(vbz[vbidx]);
2202  assert(0 <= zidx && zidx < v);
2203 
2204  (*mirrhs) += cutaj * vbd[vbidx];
2205  mircoef[zidx] -= cutaj * vbb[vbidx];
2206 
2207  /* add variable to sparsity pattern */
2208  if( !varused[zidx] )
2209  {
2210  assert(*nvarinds < prob->nvars);
2211  varused[zidx] = TRUE;
2212  varinds[*nvarinds] = zidx;
2213  (*nvarinds)++;
2214  }
2215  }
2216  }
2217 }
2218 
2219 /** substitute aggregated slack variables:
2220  *
2221  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
2222  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r] \f$.
2223  *
2224  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
2225  * \f[
2226  * \begin{array}{rll}
2227  * integers: & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) &, if \qquad f_r <= f0 \\
2228  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + p_r/(k + 1) &, if \qquad f_r > f0 \\
2229  * continuous:& \hat{a}_r = \tilde{a}_r = 0 &, if \qquad a^\prime_r >= 0 \\
2230  * & \mbox{no strong CG cut found} &, if \qquad a^\prime_r < 0
2231  * \end{array}
2232  * \f]
2233  *
2234  * Substitute \f$ \hat{a}_r * s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
2235  */
2236 static
2238  SCIP_SET* set, /**< global SCIP settings */
2239  SCIP_STAT* stat, /**< problem statistics */
2240  SCIP_LP* lp, /**< LP data */
2241  SCIP_Real* weights, /**< row weights in row summation */
2242  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
2243  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
2244  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
2245  int* slacksign, /**< stores the sign of the row's slack variable in summation */
2246  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
2247  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
2248  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
2249  int* rowinds, /**< sparsity pattern of used rows */
2250  int nrowinds, /**< number of used rows */
2251  SCIP_Real f0, /**< fractional value of rhs */
2252  SCIP_Real k /**< factor to strengthen strongcg cut */
2253  )
2254 { /*lint --e{715}*/
2255  SCIP_Real onedivoneminusf0;
2256  int i;
2257 
2258  assert(lp != NULL);
2259  assert(weights != NULL);
2260  assert(!SCIPsetIsZero(set, scale));
2261  assert(strongcgcoef != NULL);
2262  assert(strongcgrhs != NULL);
2263  assert(slacksign != NULL);
2264  assert(varused != NULL);
2265  assert(varinds != NULL);
2266  assert(nvarinds != NULL);
2267  assert(rowinds != NULL);
2268  assert(0.0 < f0 && f0 < 1.0);
2269 
2270  onedivoneminusf0 = 1.0 / (1.0 - f0);
2271 
2272  for( i = 0; i < nrowinds; i++ )
2273  {
2274  SCIP_ROW* row;
2275  SCIP_Real pr;
2276  SCIP_Real ar;
2277  SCIP_Real downar;
2278  SCIP_Real cutar;
2279  SCIP_Real fr;
2280  SCIP_Real mul;
2281  int idx;
2282  int r;
2283  int j;
2284 
2285  r = rowinds[i];
2286  assert(0 <= r && r < lp->nrows);
2287  assert(slacksign[r] == -1 || slacksign[r] == +1);
2288  assert(!SCIPsetIsZero(set, weights[r]));
2289 
2290  row = lp->rows[r];
2291  assert(row != NULL);
2292  assert(row->len == 0 || row->cols != NULL);
2293  assert(row->len == 0 || row->cols_index != NULL);
2294  assert(row->len == 0 || row->vals != NULL);
2295 
2296  /* get the slack's coefficient a'_r in the aggregated row */
2297  ar = slacksign[r] * scale * weights[r];
2298 
2299  /* calculate slack variable's coefficient a^_r in the cut */
2300  if( row->integral )
2301  {
2302  /* slack variable is always integral: */
2303  downar = SCIPsetFloor(set, ar);
2304  fr = ar - downar;
2305 
2306  if( SCIPsetIsLE(set, fr, f0) )
2307  cutar = downar;
2308  else
2309  {
2310  pr = SCIPsetCeil(set, k * (fr - f0) * onedivoneminusf0);
2311  assert(pr >= 0); /* should be >= 1, but due to rounding bias can be 0 if fr almost equal to f0 */
2312  assert(pr <= k);
2313  cutar = downar + pr / (k + 1);
2314  }
2315  }
2316  else
2317  {
2318  /* slack variable is continuous: */
2319  assert(ar >= 0.0);
2320  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
2321  }
2322 
2323  /* if the coefficient was reduced to zero, ignore the slack variable */
2324  if( SCIPsetIsZero(set, cutar) )
2325  continue;
2326 
2327  /* depending on the slack's sign, we have
2328  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
2329  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
2330  */
2331  mul = -slacksign[r] * cutar;
2332 
2333  /* add the slack's definition multiplied with a^_j to the cut */
2334  for( j = 0; j < row->len; ++j )
2335  {
2336  assert(row->cols[j] != NULL);
2337  assert(row->cols[j]->var != NULL);
2338  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
2339  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
2340  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
2341  idx = row->cols[j]->var_probindex;
2342  strongcgcoef[idx] += mul * row->vals[j];
2343 
2344  /* update sparsity pattern */
2345  if( !varused[idx] )
2346  {
2347  varused[idx] = TRUE;
2348  varinds[*nvarinds] = idx;
2349  (*nvarinds)++;
2350  }
2351  }
2352 
2353  /* move slack's constant to the right hand side */
2354  if( slacksign[r] == +1 )
2355  {
2356  SCIP_Real rhs;
2357 
2358  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
2359  assert(!SCIPsetIsInfinity(set, row->rhs));
2360  rhs = row->rhs - row->constant;
2361  if( row->integral )
2362  {
2363  /* the right hand side was implicitly rounded down in row aggregation */
2364  rhs = SCIPsetFeasFloor(set, rhs);
2365  }
2366  *strongcgrhs -= cutar * rhs;
2367  }
2368  else
2369  {
2370  SCIP_Real lhs;
2371 
2372  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
2373  assert(!SCIPsetIsInfinity(set, -row->lhs));
2374  lhs = row->lhs - row->constant;
2375  if( row->integral )
2376  {
2377  /* the left hand side was implicitly rounded up in row aggregation */
2378  lhs = SCIPsetFeasCeil(set, lhs);
2379  }
2380  *strongcgrhs += cutar * lhs;
2381  }
2382  }
2383 
2384  /* set rhs to zero, if it's very close to */
2385  if( SCIPsetIsZero(set, *strongcgrhs) )
2386  *strongcgrhs = 0.0;
2387 }
2388 
2389 /** substitute aggregated slack variables:
2390  *
2391  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
2392  * variable only appears in its own row: \f$ a^\prime_r = scale * weight[r] * slacksign[r]. \f$
2393  *
2394  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
2395  * \f[
2396  * \begin{array}{rll}
2397  * integers : & \hat{a}_r = \tilde{a}_r = down(a^\prime_r), & \mbox{if}\qquad f_r <= f0 \\
2398  * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + (f_r - f0)/(1 - f0),& \mbox{if}\qquad f_r > f0 \\
2399  * continuous:& \hat{a}_r = \tilde{a}_r = 0, & \mbox{if}\qquad a^\prime_r >= 0 \\
2400  * & \hat{a}_r = \tilde{a}_r = a^\prime_r/(1 - f0), & \mbox{if}\qquad a^\prime_r < 0
2401  * \end{array}
2402  * \f]
2403  *
2404  * Substitute \f$ \hat{a}_r \cdot s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
2405  */
2406 static
2408  SCIP_SET* set, /**< global SCIP settings */
2409  SCIP_STAT* stat, /**< problem statistics */
2410  SCIP_LP* lp, /**< LP data */
2411  SCIP_Real* weights, /**< row weights in row summation */
2412  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
2413  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
2414  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
2415  int* slacksign, /**< stores the sign of the row's slack variable in summation */
2416  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
2417  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
2418  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
2419  int* rowinds, /**< sparsity pattern of used rows */
2420  int nrowinds, /**< number of used rows */
2421  SCIP_Real f0 /**< fractional value of rhs */
2422  )
2423 { /*lint --e{715}*/
2424  SCIP_Real onedivoneminusf0;
2425  int i;
2426 
2427  assert(lp != NULL);
2428  assert(weights != NULL);
2429  assert(!SCIPsetIsZero(set, scale));
2430  assert(mircoef != NULL);
2431  assert(mirrhs != NULL);
2432  assert(slacksign != NULL);
2433  assert(varused != NULL);
2434  assert(varinds != NULL);
2435  assert(nvarinds != NULL);
2436  assert(rowinds != NULL);
2437  assert(0.0 < f0 && f0 < 1.0);
2438 
2439  onedivoneminusf0 = 1.0 / (1.0 - f0);
2440  for( i = 0; i < nrowinds; i++ )
2441  {
2442  SCIP_ROW* row;
2443  SCIP_Real ar;
2444  SCIP_Real downar;
2445  SCIP_Real cutar;
2446  SCIP_Real fr;
2447  SCIP_Real mul;
2448  int idx;
2449  int r;
2450  int j;
2451 
2452  r = rowinds[i];
2453  assert(0 <= r && r < lp->nrows);
2454  assert(slacksign[r] == -1 || slacksign[r] == +1);
2455  assert(!SCIPsetIsZero(set, weights[r]));
2456 
2457  row = lp->rows[r];
2458  assert(row != NULL);
2459  assert(row->len == 0 || row->cols != NULL);
2460  assert(row->len == 0 || row->cols_index != NULL);
2461  assert(row->len == 0 || row->vals != NULL);
2462 
2463  /* get the slack's coefficient a'_r in the aggregated row */
2464  ar = slacksign[r] * scale * weights[r];
2465 
2466  /* calculate slack variable's coefficient a^_r in the cut */
2467  if( row->integral
2468  && ((slacksign[r] == +1 && SCIPsetIsFeasIntegral(set, row->rhs - row->constant))
2469  || (slacksign[r] == -1 && SCIPsetIsFeasIntegral(set, row->lhs - row->constant))) )
2470  {
2471  /* slack variable is always integral:
2472  * a^_r = a~_r = down(a'_r) , if f_r <= f0
2473  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
2474  */
2475  downar = SCIPsetFloor(set, ar);
2476  fr = ar - downar;
2477  if( SCIPsetIsLE(set, fr, f0) )
2478  cutar = downar;
2479  else
2480  cutar = downar + (fr - f0) * onedivoneminusf0;
2481  }
2482  else
2483  {
2484  /* slack variable is continuous:
2485  * a^_r = a~_r = 0 , if a'_r >= 0
2486  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
2487  */
2488  if( ar >= 0.0 )
2489  continue; /* slack can be ignored, because its coefficient is reduced to 0.0 */
2490  else
2491  cutar = ar * onedivoneminusf0;
2492  }
2493 
2494  /* if the coefficient was reduced to zero, ignore the slack variable */
2495  if( SCIPsetIsZero(set, cutar) )
2496  continue;
2497 
2498  /* depending on the slack's sign, we have
2499  * a*x + c + s == rhs => s == - a*x - c + rhs, or a*x + c - s == lhs => s == a*x + c - lhs
2500  * substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
2501  */
2502  mul = -slacksign[r] * cutar;
2503 
2504  /* add the slack's definition multiplied with a^_j to the cut */
2505  for( j = 0; j < row->len; ++j )
2506  {
2507  assert(row->cols[j] != NULL);
2508  assert(row->cols[j]->var != NULL);
2509  assert(SCIPvarGetStatus(row->cols[j]->var) == SCIP_VARSTATUS_COLUMN);
2510  assert(SCIPvarGetCol(row->cols[j]->var) == row->cols[j]);
2511  assert(SCIPvarGetProbindex(row->cols[j]->var) == row->cols[j]->var_probindex);
2512  idx = row->cols[j]->var_probindex;
2513  mircoef[idx] += mul * row->vals[j];
2514 
2515  /* update sparsity pattern */
2516  if( !varused[idx] )
2517  {
2518  varused[idx] = TRUE;
2519  varinds[*nvarinds] = idx;
2520  (*nvarinds)++;
2521  }
2522  }
2523 
2524  /* move slack's constant to the right hand side */
2525  if( slacksign[r] == +1 )
2526  {
2527  SCIP_Real rhs;
2528 
2529  /* a*x + c + s == rhs => s == - a*x - c + rhs: move a^_r * (rhs - c) to the right hand side */
2530  assert(!SCIPsetIsInfinity(set, row->rhs));
2531  rhs = row->rhs - row->constant;
2532  if( row->integral )
2533  {
2534  /* the right hand side was implicitly rounded down in row aggregation */
2535  rhs = SCIPsetFeasFloor(set, rhs);
2536  }
2537  *mirrhs -= cutar * rhs;
2538  }
2539  else
2540  {
2541  SCIP_Real lhs;
2542 
2543  /* a*x + c - s == lhs => s == a*x + c - lhs: move a^_r * (c - lhs) to the right hand side */
2544  assert(!SCIPsetIsInfinity(set, -row->lhs));
2545  lhs = row->lhs - row->constant;
2546  if( row->integral )
2547  {
2548  /* the left hand side was implicitly rounded up in row aggregation */
2549  lhs = SCIPsetFeasCeil(set, lhs);
2550  }
2551  *mirrhs += cutar * lhs;
2552  }
2553  }
2554 
2555  /* set rhs to zero, if it's very close to */
2556  if( SCIPsetIsZero(set, *mirrhs) )
2557  *mirrhs = 0.0;
2558 }
2559 
2560 /* calculates a strong CG cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because
2561  * these rows cannot participate in a strong CG cut.
2562  */
2563 static
2565  SCIP_LP* lp, /**< LP data */
2566  SCIP_SET* set, /**< global SCIP settings */
2567  SCIP_STAT* stat, /**< problem statistics */
2568  SCIP_PROB* prob, /**< problem data */
2569  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
2570  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
2571  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2572  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
2573  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
2574  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce strong CG cut for */
2575  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce strong CG cut for */
2576  SCIP_Real* weights, /**< row weights in row summation */
2577  int* rowinds, /**< array to store indices of non-zero entries of the weights array, or
2578  * NULL */
2579  int nrowinds, /**< number of non-zero entries in weights array, -1 if rowinds is NULL */
2580  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
2581  SCIP_Real* strongcgcoef, /**< array to store strong CG coefficients: must be of size nvars */
2582  SCIP_Real* strongcgrhs, /**< pointer to store the right hand side of the strong CG row */
2583  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
2584  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid strong CG cut */
2585  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
2586  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
2587  )
2588 {
2589  int* slacksign;
2590  int* varsign;
2591  int* boundtype;
2592  SCIP_Bool* varused;
2593  int* varinds;
2594  int nvarinds;
2595  SCIP_Real rhs;
2596  SCIP_Real downrhs;
2597  SCIP_Real f0;
2598  SCIP_Real k;
2599  SCIP_Bool emptyrow;
2600  SCIP_Bool freevariable;
2601  SCIP_Bool localrowsused;
2602  SCIP_Bool localbdsused;
2603  SCIP_Bool rowtoolong;
2604  SCIP_Bool cleanuprowinds;
2605 
2606  assert(lp != NULL);
2607  assert(lp->solved);
2608  assert(prob != NULL);
2609  assert(weights != NULL);
2610  assert(!SCIPsetIsZero(set, scale));
2611  assert(strongcgcoef != NULL);
2612  assert(strongcgrhs != NULL);
2613  assert(cutactivity != NULL);
2614  assert(success != NULL);
2615  assert(cutislocal != NULL);
2616  assert(rowinds != NULL || nrowinds == -1);
2617 
2618  SCIPdebugMessage("calculating strong CG cut (scale: %g)\n", scale);
2619 
2620  /**@todo test, if a column based summation is faster */
2621 
2622  *success = FALSE;
2623  *cutislocal = FALSE;
2624 
2625  /* allocate temporary memory */
2626  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
2627  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
2628  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
2629  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
2630  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
2631 
2632  /* allocate memory for sparsity structure in case it has not been provided already */
2633  cleanuprowinds = FALSE;
2634  if( rowinds == NULL )
2635  {
2636  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
2637  cleanuprowinds = TRUE;
2638  }
2639 
2640  /* calculate the row summation */
2641  cutsSumStrongCGRow(set, prob, lp, weights, scale, allowlocal,
2642  maxmksetcoefs, maxweightrange, strongcgcoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
2643  &emptyrow, &localrowsused, &rowtoolong, cutrank);
2644  assert(allowlocal || !localrowsused);
2645  *cutislocal = *cutislocal || localrowsused;
2646  if( emptyrow || rowtoolong )
2647  goto TERMINATE;
2648  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs, FALSE, FALSE));
2649 
2650  /* remove all nearly-zero coefficients from strong CG row and relaxes the right hand side correspondingly in order to
2651  * prevent numerical rounding errors
2652  */
2653  cutsCleanupMIRRow(set, prob, strongcgcoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
2654  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs, FALSE, FALSE));
2655 
2656  /* Transform equation a*x == b, lb <= x <= ub into standard form
2657  * a'*x' == b, 0 <= x' <= ub'.
2658  *
2659  * Transform variables (lb or ub):
2660  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
2661  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
2662  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
2663  *
2664  * Transform variables (vlb or vub):
2665  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
2666  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
2667  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
2668  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
2669  * a_{zu_j} := a_{zu_j} + a_j * bu_j
2670  */
2671  cutsTransformStrongCGRow(set, stat, prob, boundswitch, usevbds, allowlocal,
2672  strongcgcoef, &rhs, varused, varinds, &nvarinds, varsign, boundtype, &freevariable, &localbdsused);
2673  assert(allowlocal || !localbdsused);
2674  *cutislocal = *cutislocal || localbdsused;
2675  if( freevariable )
2676  goto TERMINATE;
2677  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs, FALSE, FALSE));
2678 
2679  /* Calculate
2680  * - fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j)
2681  * - integer k >= 1 with 1/(k + 1) <= f_0 < 1/k
2682  * (=> k = up(1/f_0) + 1)
2683  * - integer 1 <= p_j <= k with f_0 + ((p_j - 1) * (1 - f_0)/k) < f_j <= f_0 + (p_j * (1 - f_0)/k)
2684  * (=> p_j = up( (f_j - f_0)/((1 - f_0)/k) ))
2685  * and derive strong CG cut
2686  * a~*x' <= (k+1) * down(b)
2687  * integers : a~_j = down(a'_j) , if f_j <= f_0
2688  * a~_j = down(a'_j) + p_j/(k + 1) , if f_j > f_0
2689  * continuous: a~_j = 0 , if a'_j >= 0
2690  * no strong CG cut found , if a'_j < 0
2691  *
2692  * Transform inequality back to a^*x <= rhs:
2693  *
2694  * (lb or ub):
2695  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
2696  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
2697  * and move the constant terms
2698  * -a~_j * lb_j == -a^_j * lb_j, or
2699  * a~_j * ub_j == -a^_j * ub_j
2700  * to the rhs.
2701  *
2702  * (vlb or vub):
2703  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
2704  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
2705  * move the constant terms
2706  * -a~_j * dl_j == -a^_j * dl_j, or
2707  * a~_j * du_j == -a^_j * du_j
2708  * to the rhs, and update the VB variable coefficients:
2709  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
2710  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
2711  */
2712  downrhs = SCIPsetSumFloor(set, rhs);
2713  f0 = rhs - downrhs;
2714  if( f0 < minfrac || f0 > maxfrac )
2715  goto TERMINATE;
2716  k = SCIPsetCeil(set, 1.0 / f0) - 1;
2717 
2718  *strongcgrhs = downrhs;
2719  cutsRoundStrongCGRow(set, prob, strongcgcoef, strongcgrhs, varused, varinds, &nvarinds, varsign, boundtype, f0, k);
2720  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs, FALSE, FALSE));
2721 
2722  /* substitute aggregated slack variables:
2723  *
2724  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
2725  * variable only appears in its own row:
2726  * a'_r = scale * weight[r] * slacksign[r].
2727  *
2728  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
2729  * integers : a^_r = a~_r = (k + 1) * down(a'_r) , if f_r <= f0
2730  * a^_r = a~_r = (k + 1) * down(a'_r) + p_r , if f_r > f0
2731  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
2732  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
2733  *
2734  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
2735  */
2736  cutsSubstituteStrongCGRow(set, stat, lp, weights, scale, strongcgcoef, strongcgrhs, slacksign,
2737  varused, varinds, &nvarinds, rowinds, nrowinds, f0, k);
2738  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, *strongcgrhs, FALSE, FALSE));
2739 
2740  /* remove again all nearly-zero coefficients from strong CG row and relax the right hand side correspondingly in order to
2741  * prevent numerical rounding errors
2742  */
2743  cutsCleanupMIRRow(set, prob, strongcgcoef, strongcgrhs, varused, varinds, &nvarinds, *cutislocal);
2744  SCIPdebug(printMIR(set, stat, prob, NULL, strongcgcoef, rhs, FALSE, FALSE));
2745 
2746  /* calculate cut activity */
2747  *cutactivity = getMIRRowActivity(set, stat, prob, NULL, strongcgcoef, varinds, nvarinds);
2748  *success = TRUE;
2749 
2750  TERMINATE:
2751  /* free temporary memory */
2752  if( cleanuprowinds )
2753  {
2754  SCIPsetFreeBufferArray(set, &rowinds);
2755  }
2756 
2757  SCIPsetFreeBufferArray(set, &varinds);
2758  SCIPsetFreeBufferArray(set, &varused);
2759  SCIPsetFreeBufferArray(set, &boundtype);
2760  SCIPsetFreeBufferArray(set, &varsign);
2761  SCIPsetFreeBufferArray(set, &slacksign);
2762 
2763  return SCIP_OKAY;
2764 }
2765 
2766 /* calculates an MIR cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0 because these
2767  * rows cannot participate in an MIR cut.
2768  */
2769 static
2771  SCIP_LP* lp, /**< LP data */
2772  SCIP_SET* set, /**< global SCIP settings */
2773  SCIP_STAT* stat, /**< problem statistics */
2774  SCIP_PROB* prob, /**< problem data */
2775  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
2776  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
2777  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
2778  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2779  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
2780  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
2781  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
2782  * NULL for using closest bound for all variables */
2783  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
2784  * NULL for using closest bound for all variables */
2785  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
2786  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
2787  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
2788  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
2789  SCIP_Real* weights, /**< row weights in row summation */
2790  SCIP_Real maxweight, /**< largest magnitude of weights; set to -1 if sparsity information is unknown */
2791  int* weightinds, /**< sparsity pattern of weights; size nrowinds; NULL if sparsity info is unknown */
2792  int nweightinds, /**< number of nonzeros in weights; -1 if rowinds is NULL */
2793  int rowlensum, /**< total number of non-zeros in used rows (row associated with nonzero weight coefficient); -1 if unknown */
2794  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
2795  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
2796  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
2797  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
2798  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size nvars */
2799  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
2800  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
2801  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
2802  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
2803  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
2804  )
2805 {
2806  int* slacksign;
2807  int* varsign;
2808  int* boundtype;
2809  SCIP_Bool* varused;
2810  int* varinds;
2811  int* rowinds;
2812  int nvarinds;
2813  int nrowinds;
2814  SCIP_Real rhs;
2815  SCIP_Real downrhs;
2816  SCIP_Real f0;
2817  SCIP_Bool emptyrow;
2818  SCIP_Bool freevariable;
2819  SCIP_Bool localrowsused;
2820  SCIP_Bool localbdsused;
2821  SCIP_Bool rowtoolong;
2822  SCIP_Bool compress;
2823 
2824  assert(lp != NULL);
2825  assert(lp->solved || sol != NULL);
2826  assert(prob != NULL);
2827  assert(weights != NULL);
2828  assert(!SCIPsetIsZero(set, scale));
2829  assert(mircoef != NULL);
2830  assert(mirrhs != NULL);
2831  assert(cutactivity != NULL);
2832  assert(success != NULL);
2833  assert(cutislocal != NULL);
2834 
2835  SCIPdebugMessage("calculating MIR cut (scale: %g)\n", scale);
2836 
2837  /**@todo test, if a column based summation is faster */
2838 
2839  *success = FALSE;
2840  if( mksetcoefsvalid != NULL )
2841  *mksetcoefsvalid = FALSE;
2842 
2843  /* allocate temporary memory */
2844  SCIP_CALL( SCIPsetAllocBufferArray(set, &slacksign, lp->nrows) );
2845  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
2846  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
2847  SCIP_CALL( SCIPsetAllocBufferArray(set, &varused, prob->nvars) );
2848  SCIP_CALL( SCIPsetAllocBufferArray(set, &varinds, prob->nvars) );
2849 
2850  /* if sparse information of weights is known, there is no need
2851  * to compute rowinds */
2852  if( weightinds == NULL )
2853  {
2854  SCIP_CALL( SCIPsetAllocBufferArray(set, &rowinds, lp->nrows) );
2855  compress = TRUE;
2856  }
2857  else
2858  {
2859  compress = FALSE;
2860 
2861  /* weightinds is the indices of the weights vector.
2862  * rowinds is the indices of the weights vector that is modified in the cutsSumMIRRow function.
2863  * duplication of weightinds is necessary to ensure weightinds is not modified. */
2864  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &rowinds, weightinds, nweightinds) );
2865  nrowinds = nweightinds;
2866 
2867  if( rowlensum/5 > maxmksetcoefs )
2868  {
2869  *cutislocal = FALSE;
2870  goto TERMINATE;
2871  }
2872  }
2873 
2874  /* calculate the row summation */
2875  cutsSumMIRRow(set, prob, lp, weights, maxweight, sidetypes, scale, allowlocal,
2876  maxmksetcoefs, maxweightrange, compress, mircoef, &rhs, slacksign, varused, varinds, &nvarinds, rowinds, &nrowinds,
2877  &emptyrow, &localrowsused, &rowtoolong, cutrank);
2878  assert(allowlocal || !localrowsused);
2879  *cutislocal = localrowsused;
2880  if( emptyrow || rowtoolong )
2881  goto TERMINATE;
2882  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs, FALSE, FALSE));
2883 
2884  /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
2885  * prevent numerical rounding errors
2886  */
2887  cutsCleanupMIRRow(set, prob, mircoef, &rhs, varused, varinds, &nvarinds, *cutislocal);
2888  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs, FALSE, FALSE));
2889 
2890  /* Transform equation a*x == b, lb <= x <= ub into standard form
2891  * a'*x' == b, 0 <= x' <= ub'.
2892  *
2893  * Transform variables (lb or ub):
2894  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
2895  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
2896  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
2897  *
2898  * Transform variables (vlb or vub):
2899  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
2900  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
2901  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
2902  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
2903  * a_{zu_j} := a_{zu_j} + a_j * bu_j
2904  */
2905  SCIP_CALL( cutsTransformMIRRow(set, stat, prob, sol, boundswitch, usevbds, allowlocal, fixintegralrhs, FALSE,
2906  boundsfortrans, boundtypesfortrans, minfrac, maxfrac, mircoef, &rhs, varused, varinds, &nvarinds,
2907  varsign, boundtype, &freevariable, &localbdsused) );
2908  assert(allowlocal || !localbdsused);
2909  *cutislocal = *cutislocal || localbdsused;
2910 
2911  /* store the coefficients of the variables in the constructed mixed knapsack set */
2912  if( mksetcoefs != NULL )
2913  BMScopyMemoryArray(mksetcoefs, mircoef, prob->nvars);
2914  if( mksetcoefsvalid != NULL )
2915  *mksetcoefsvalid = TRUE;
2916 
2917  if( freevariable )
2918  goto TERMINATE;
2919  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, rhs, FALSE, FALSE));
2920 
2921  /* Calculate fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j) , and derive MIR cut
2922  * a~*x' <= down(b)
2923  * integers : a~_j = down(a'_j) , if f_j <= f_0
2924  * a~_j = down(a'_j) + (f_j - f0)/(1 - f0), if f_j > f_0
2925  * continuous: a~_j = 0 , if a'_j >= 0
2926  * a~_j = a'_j/(1 - f0) , if a'_j < 0
2927  *
2928  * Transform inequality back to a^*x <= rhs:
2929  *
2930  * (lb or ub):
2931  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
2932  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
2933  * and move the constant terms
2934  * -a~_j * lb_j == -a^_j * lb_j, or
2935  * a~_j * ub_j == -a^_j * ub_j
2936  * to the rhs.
2937  *
2938  * (vlb or vub):
2939  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
2940  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
2941  * move the constant terms
2942  * -a~_j * dl_j == -a^_j * dl_j, or
2943  * a~_j * du_j == -a^_j * du_j
2944  * to the rhs, and update the VB variable coefficients:
2945  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
2946  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
2947  */
2948  downrhs = SCIPsetSumFloor(set, rhs);
2949  f0 = rhs - downrhs;
2950  if( f0 < minfrac || f0 > maxfrac )
2951  goto TERMINATE;
2952 
2953  /* We multiply the coefficients of the base inequality roughly by scale/(1-f0).
2954  * If this gives a scalar that is very big, we better do not generate this cut.
2955  */
2956  if( REALABS(scale)/(1.0 - f0) > MAXCMIRSCALE )
2957  goto TERMINATE;
2958 
2959  *mirrhs = downrhs;
2960  cutsRoundMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, varsign, boundtype, f0);
2961  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs, FALSE, FALSE));
2962 
2963  /* substitute aggregated slack variables:
2964  *
2965  * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
2966  * variable only appears in its own row:
2967  * a'_r = scale * weight[r] * slacksign[r].
2968  *
2969  * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
2970  * integers : a^_r = a~_r = down(a'_r) , if f_r <= f0
2971  * a^_r = a~_r = down(a'_r) + (f_r - f0)/(1 - f0), if f_r > f0
2972  * continuous: a^_r = a~_r = 0 , if a'_r >= 0
2973  * a^_r = a~_r = a'_r/(1 - f0) , if a'_r < 0
2974  *
2975  * Substitute a^_r * s_r by adding a^_r times the slack's definition to the cut.
2976  */
2977  cutsSubstituteMIRRow(set, stat, lp, weights, scale, mircoef, mirrhs, slacksign, varused, varinds, &nvarinds,
2978  rowinds, nrowinds, f0);
2979  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs, FALSE, FALSE));
2980 
2981  /* remove again all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
2982  * prevent numerical rounding errors
2983  */
2984  cutsCleanupMIRRow(set, prob, mircoef, mirrhs, varused, varinds, &nvarinds, *cutislocal);
2985  SCIPdebug(printMIR(set, stat, prob, sol, mircoef, *mirrhs, FALSE, FALSE));
2986 
2987  /* calculate cut activity */
2988  *cutactivity = getMIRRowActivity(set, stat, prob, sol, mircoef, varinds, nvarinds);
2989  *success = TRUE;
2990 
2991  TERMINATE:
2992  /* free temporary memory */
2993  SCIPsetFreeBufferArray(set, &rowinds);
2994  SCIPsetFreeBufferArray(set, &varinds);
2995  SCIPsetFreeBufferArray(set, &varused);
2996  SCIPsetFreeBufferArray(set, &boundtype);
2997  SCIPsetFreeBufferArray(set, &varsign);
2998  SCIPsetFreeBufferArray(set, &slacksign);
2999 
3000  /**@todo pass the sparsity pattern to the calling method in order to speed up the calling method's loops */
3001 
3002  return SCIP_OKAY;
3003 }
3004 
3005 /** applies the MIR function on a constraint; the constraint is given by pairs of variables and coefficients and a rhs */
3006 static
3008  SCIP_SET* set, /**< global SCIP settings */
3009  SCIP_STAT* stat, /**< dynamic SCIP statistics */
3010  SCIP_PROB* prob, /**< transformed problem */
3011  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
3012  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
3013  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
3014  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
3015  int* boundsfortrans, /**< bounds that should be used for transformed variables: 0 vlb_idx/vub_idx,
3016  * -1 for global lb/ub or -2 for local lb/ub
3017  */
3018  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
3019  * NULL for using closest bound for all variables */
3020  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
3021  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
3022  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
3023  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
3024  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
3025  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size SCIPgetNVars() */
3026  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
3027  int* varinds, /**< array of variable indeces with a mircoef != 0 */
3028  int* nvarinds, /**< number of variables indeces in varinds array */
3029  SCIP_Real* minact, /**< pointer to store the minimal activity */
3030  SCIP_Bool* varused, /**< array to store whether a variable has a mircoef != 0 */
3031  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
3032  SCIP_Bool* islocal /**< pointer to store whether the returned constraint is only valid locally */
3033  )
3034 {
3035  int* varsign;
3036  int* boundtype;
3037  SCIP_Real rhs;
3038  SCIP_Real downrhs;
3039  SCIP_Real f0;
3040  SCIP_Bool freevariable;
3041  SCIP_Bool localbdsused;
3042  int v;
3043 
3044  assert(prob != NULL);
3045  assert(SCIPsetIsPositive(set, scale));
3046  assert(mircoef != NULL);
3047  assert(mirrhs != NULL);
3048  assert(success != NULL);
3049  assert(islocal != NULL);
3050  assert(*nvarinds >= 1);
3051  assert(varinds != NULL);
3052  assert(varused != NULL);
3053 
3054  /* only temporary */
3055  assert(mksetcoefs == NULL);
3056  assert(mksetcoefsvalid == NULL);
3057 
3058  SCIPdebugMessage("applying MIR function (scale: %g)\n", scale);
3059 
3060  *success = FALSE;
3061 
3062  /* allocate temporary memory */
3063  SCIP_CALL( SCIPsetAllocBufferArray(set, &varsign, prob->nvars) );
3064  SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtype, prob->nvars) );
3065 
3066  if( !SCIPsetIsEQ(set, scale, 1.0) )
3067  {
3068  (*mirrhs) *= scale;
3069  for( v = 0; v < *nvarinds; v++ )
3070  mircoef[varinds[v]] *= scale;
3071  }
3072 
3073  /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
3074  * prevent numerical rounding errors
3075  */
3076  rhs = *mirrhs;
3077  cutsCleanupMIRRow(set, prob, mircoef, &rhs, varused, varinds, nvarinds, *islocal);
3078  SCIPdebug(printMIR(set, stat, prob, NULL, mircoef, *mirrhs, TRUE, *islocal));
3079 
3080  /* Transform equation a*x == b, lb <= x <= ub into standard form
3081  * a'*x' == b, 0 <= x' <= ub'.
3082  *
3083  * Transform variables (lb or ub):
3084  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, if lb is used in transformation
3085  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, if ub is used in transformation
3086  * and move the constant terms "a_j * lb_j" or "a_j * ub_j" to the rhs.
3087  *
3088  * Transform variables (vlb or vub):
3089  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
3090  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
3091  * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
3092  * a_{zl_j} := a_{zl_j} + a_j * bl_j, or
3093  * a_{zu_j} := a_{zu_j} + a_j * bu_j
3094  */
3095  SCIP_CALL( cutsTransformMIRRow(set, stat, prob, NULL, boundswitch, usevbds, allowlocal, fixintegralrhs, TRUE,
3096  boundsfortrans, boundtypesfortrans, minfrac, maxfrac, mircoef, &rhs, varused, varinds,
3097  nvarinds, varsign, boundtype, &freevariable, &localbdsused) );
3098  assert(allowlocal || !localbdsused);
3099  *islocal = *islocal || localbdsused;
3100 
3101  if( freevariable )
3102  goto TERMINATE;
3103  SCIPdebug(printMIR(set, stat, prob, NULL, mircoef, *mirrhs, TRUE, *islocal));
3104 
3105  /* Calculate fractionalities f_0 := b - down(b), f_j := a'_j - down(a'_j) , and derive MIR cut
3106  * a~*x' <= down(b)
3107  * integers : a~_j = down(a'_j) , if f_j <= f_0
3108  * a~_j = down(a'_j) + (f_j - f0)/(1 - f0), if f_j > f_0
3109  * continuous: a~_j = 0 , if a'_j >= 0
3110  * a~_j = a'_j/(1 - f0) , if a'_j < 0
3111  *
3112  * Transform inequality back to a^*x <= rhs:
3113  *
3114  * (lb or ub):
3115  * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
3116  * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
3117  * and move the constant terms
3118  * -a~_j * lb_j == -a^_j * lb_j, or
3119  * a~_j * ub_j == -a^_j * ub_j
3120  * to the rhs.
3121  *
3122  * (vlb or vub):
3123  * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
3124  * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
3125  * move the constant terms
3126  * -a~_j * dl_j == -a^_j * dl_j, or
3127  * a~_j * du_j == -a^_j * du_j
3128  * to the rhs, and update the VB variable coefficients:
3129  * a^_{zl_j} := a^_{zl_j} - a~_j * bl_j == a^_{zl_j} - a^_j * bl_j, or
3130  * a^_{zu_j} := a^_{zu_j} + a~_j * bu_j == a^_{zu_j} - a^_j * bu_j
3131  */
3132  downrhs = SCIPsetSumFloor(set, rhs);
3133  f0 = rhs - downrhs;
3134  if( f0 < minfrac || f0 > maxfrac )
3135  goto TERMINATE;
3136 
3137  /* We multiply the coefficients of the base inequality roughly by scale/(1-f0).
3138  * If this gives a scalar that is very big, we better do not generate this cut.
3139  */
3140  if( REALABS(scale)/(1.0 - f0) > MAXCMIRSCALE )
3141  goto TERMINATE;
3142 
3143  *mirrhs = downrhs;
3144  cutsRoundMIRRow(set, prob, mircoef, mirrhs, varused, varinds, nvarinds, varsign, boundtype, f0);
3145  SCIPdebug(printMIR(set, stat, prob, NULL, mircoef, *mirrhs, TRUE, *islocal));
3146 
3147  /* remove again all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
3148  * prevent numerical rounding errors
3149  */
3150  cutsCleanupMIRRow(set, prob, mircoef, mirrhs, varused, varinds, nvarinds, *islocal);
3151  SCIPdebug(printMIR(set, stat, prob, NULL, mircoef, rhs, TRUE, *islocal));
3152 
3153  /* calculate cut activity */
3154  *minact = getMIRMinActivity(prob, mircoef, varinds, *nvarinds, *islocal);
3155  *success = TRUE;
3156 
3157  TERMINATE:
3158  /* free temporary memory */
3159  SCIPsetFreeBufferArray(set, &boundtype);
3160  SCIPsetFreeBufferArray(set, &varsign);
3161 
3162  return SCIP_OKAY;
3163 }
3164 
3165 /** calculates a strong CG cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0 because
3166  * these rows cannot participate in an MIR cut.
3167  *
3168  * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3169  * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3170  *
3171  * @pre This method can be called if @p scip is in one of the following stages:
3172  * - \ref SCIP_STAGE_SOLVING
3173  *
3174  * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3175  */
3177  SCIP* scip, /**< SCIP data structure */
3178  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
3179  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
3180  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
3181  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
3182  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
3183  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce strong CG cut for */
3184  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce strong CG cut for */
3185  SCIP_Real* weights, /**< row weights in row summation; some weights might be set to zero */
3186  int* inds, /**< indices of non-zero entries in weights array, or NULL */
3187  int ninds, /**< number of indices of non-zero entries in weights array, -1 if inds is
3188  * NULL */
3189  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
3190  SCIP_Real* mircoef, /**< array to store strong CG coefficients: must be of size SCIPgetNVars() */
3191  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the strong CG row */
3192  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
3193  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid strong CG cut */
3194  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
3195  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
3196  )
3197 {
3198  SCIP_CALL( cutsLpCalcStrongCG(scip->lp, scip->set, scip->stat, scip->transprob,
3199  boundswitch, usevbds, allowlocal, maxmksetcoefs, maxweightrange, minfrac, maxfrac, weights, inds, ninds, scale,
3200  mircoef, mirrhs, cutactivity, success, cutislocal, cutrank) );
3201 
3202  return SCIP_OKAY;
3203 }
3204 
3205 /** calculates an MIR cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0 because
3206  * these rows cannot participate in an MIR cut.
3207  *
3208  * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3209  * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3210  *
3211  * @pre This method can be called if @p scip is in one of the following stages:
3212  * - \ref SCIP_STAGE_SOLVING
3213  *
3214  * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3215  */
3217  SCIP* scip, /**< SCIP data structure */
3218  SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */
3219  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
3220  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
3221  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
3222  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
3223  int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
3224  * -1 for global lb/ub, -2 for local lb/ub, or -3 for using closest bound;
3225  * NULL for using closest bound for all variables */
3226  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
3227  * NULL for using closest bound for all variables */
3228  int maxmksetcoefs, /**< maximal number of nonzeros allowed in aggregated base inequality */
3229  SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
3230  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
3231  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
3232  SCIP_Real* weights, /**< row weights in row summation; some weights might be set to zero */
3233  SCIP_Real maxweight, /**< largest magnitude of weights; set to -1.0 if sparsity information is
3234  * unknown */
3235  int* weightinds, /**< sparsity pattern of weights; size nrowinds; NULL if sparsity info is
3236  * unknown */
3237  int nweightinds, /**< number of nonzeros in weights; -1 if rowinds is NULL */
3238  int rowlensum, /**< total number of nonzeros in used rows (row associated with nonzero weight coefficient); -1 if unknown */
3239  int* sidetypes, /**< specify row side type (-1 = lhs, 0 = unkown, 1 = rhs) or NULL for automatic choices */
3240  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
3241  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
3242  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
3243  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size SCIPgetNVars() */
3244  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
3245  SCIP_Real* cutactivity, /**< pointer to store the activity of the resulting cut */
3246  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
3247  SCIP_Bool* cutislocal, /**< pointer to store whether the returned cut is only valid locally */
3248  int* cutrank /**< pointer to store the rank of the returned cut; or NULL */
3249  )
3250 {
3251  SCIP_CALL( cutsLpCalcMIR(scip->lp, scip->set, scip->stat, scip->transprob, sol,
3252  boundswitch, usevbds, allowlocal, fixintegralrhs, boundsfortrans, boundtypesfortrans, maxmksetcoefs,
3253  maxweightrange, minfrac, maxfrac, weights, maxweight, weightinds, nweightinds, rowlensum, sidetypes,
3254  scale, mksetcoefs, mksetcoefsvalid, mircoef, mirrhs, cutactivity, success, cutislocal, cutrank) );
3255 
3256  return SCIP_OKAY;
3257 }
3258 
3259 /** applies the MIR function on a constraint; the constraint is given by pairs of variables and coefficients and a rhs.
3260  *
3261  * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3262  * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
3263  *
3264  * @pre This method can be called if @p scip is in one of the following stages:
3265  * - \ref SCIP_STAGE_SOLVING
3266  *
3267  * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
3268  */
3270  SCIP* scip, /**< SCIP data structure */
3271  SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
3272  SCIP_Bool usevbds, /**< should variable bounds be used in bound transformation? */
3273  SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
3274  SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
3275  int* boundsfortrans, /**< bounds that should be used for transformed variables: 0 vlb_idx/vub_idx,
3276  * -1 for global lb/ub or -2 for local lb/ub
3277  */
3278  SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
3279  * NULL for using closest bound for all variables */
3280  SCIP_Real minfrac, /**< minimal fractionality of rhs to produce MIR cut for */
3281  SCIP_Real maxfrac, /**< maximal fractionality of rhs to produce MIR cut for */
3282  SCIP_Real scale, /**< additional scaling factor multiplied to all rows */
3283  SCIP_Real* mksetcoefs, /**< array to store mixed knapsack set coefficients: size nvars; or NULL */
3284  SCIP_Bool* mksetcoefsvalid, /**< pointer to store whether mixed knapsack set coefficients are valid; or NULL */
3285  SCIP_Real* mircoef, /**< array to store MIR coefficients: must be of size SCIPgetNVars() */
3286  SCIP_Real* mirrhs, /**< pointer to store the right hand side of the MIR row */
3287  int* varinds, /**< array of variable indices with a mircoef != 0 */
3288  int* nvarinds, /**< number of variables indices in varinds array */
3289  SCIP_Real* minact, /**< pointer to store the minimal activity */
3290  SCIP_Bool* varused, /**< array to store whether a variable has a mircoef != 0 */
3291  SCIP_Bool* success, /**< pointer to store whether the returned coefficients are a valid MIR cut */
3292  SCIP_Bool* islocal /**< pointer to store whether the returned constraint is only valid locally */
3293  )
3294 {
3295  SCIP_CALL( cutsApplyMIR(scip->set, scip->stat, scip->transprob, boundswitch, usevbds, allowlocal, fixintegralrhs,
3296  boundsfortrans, boundtypesfortrans, minfrac, maxfrac, scale, mksetcoefs, mksetcoefsvalid, mircoef, mirrhs,
3297  varinds, nvarinds, minact, varused, success, islocal) );
3298 
3299  return SCIP_OKAY;
3300 }
3301 
3302 /** removes all nearly-zero coefficients from MIR row and relaxes the right hand side accordingly in order to prevent
3303  * numerical rounding errors
3304  */
3306  SCIP* scip, /**< SCIP data structure */
3307  SCIP_Real* coefs, /**< array to store MIR coefficients: must be of size nvars */
3308  SCIP_Real* rhs, /**< pointer to store the right hand side of the MIR row */
3309  SCIP_Bool* varused, /**< array to flag variables that appear in the MIR constraint */
3310  int* varinds, /**< sparsity pattern of non-zero MIR coefficients */
3311  int* nvarinds, /**< pointer to number of non-zero MIR coefficients */
3312  SCIP_Bool islocal /**< is the row only valid locally? */
3313  )
3314 {
3315  cutsCleanupMIRRow(scip->set, scip->transprob, coefs, rhs, varused, varinds, nvarinds, islocal);
3316 }
SCIP_STAT * stat
Definition: struct_scip.h:69
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPcutsCalcStrongCG(SCIP *scip, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, int *inds, int ninds, SCIP_Real scale, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank)
Definition: cuts.c:3176
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5522
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17380
static SCIP_RETCODE cutsLpCalcMIR(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, 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: cuts.c:2770
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13424
SCIP_RETCODE SCIPcutsCalcLpMIR(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: cuts.c:3216
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5580
internal methods for storing primal CIP solutions
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5843
static void cutsSumMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real knownmaxweight, int *sidetypes, SCIP_Real scale, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Bool compress, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int *nrowinds, SCIP_Bool *emptyrow, SCIP_Bool *localrowsused, SCIP_Bool *rowtoolong, int *cutrank)
Definition: cuts.c:649
int * cols_index
Definition: struct_lp.h:217
char * name
Definition: struct_lp.h:215
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5709
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17358
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1836
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16070
static SCIP_Real getMaxAbsWeight(SCIP_SET *set, SCIP_LP *lp, SCIP_Real *weights, int *rowinds, int *nrowinds, int *rowlensum)
Definition: cuts.c:183
static void cutsRoundMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Real f0)
Definition: cuts.c:2050
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5645
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:16232
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:16370
int rank
Definition: struct_lp.h:236
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5384
#define FALSE
Definition: def.h:64
common methods used to generate and strengthen cuts
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6063
SCIP_Bool solved
Definition: struct_lp.h:343
static void cutsSumStrongCGRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int *nrowinds, SCIP_Bool *emptyrow, SCIP_Bool *localrowsused, SCIP_Bool *rowtoolong, int *cutrank)
Definition: cuts.c:478
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5634
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17400
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1834
#define MAXCMIRSCALE
Definition: cuts.c:37
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16859
static SCIP_RETCODE cutsApplyMIR(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_Real *mksetcoefs, SCIP_Bool *mksetcoefsvalid, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *varinds, int *nvarinds, SCIP_Real *minact, SCIP_Bool *varused, SCIP_Bool *success, SCIP_Bool *islocal)
Definition: cuts.c:3007
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17370
unsigned int integral
Definition: struct_lp.h:245
SCIP_PROB * transprob
Definition: struct_scip.h:87
static void cutsTransformStrongCGRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Bool *freevariable, SCIP_Bool *localbdsused)
Definition: cuts.c:933
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5656
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1841
SCIP_Real SCIPsetSumFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5876
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5720
internal methods for LP management
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1286
static void cutsSubstituteStrongCGRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int nrowinds, SCIP_Real f0, SCIP_Real k)
Definition: cuts.c:2237
#define SCIP_DEFAULT_EPSILON
Definition: def.h:141
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5616
SCIP_Real * vals
Definition: struct_lp.h:218
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
int lppos
Definition: struct_lp.h:228
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5562
SCIP_Bool SCIPsetIsSumLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5789
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPdebugPrintf
Definition: pub_message.h:80
SCIP_COL ** cols
Definition: struct_lp.h:216
static SCIP_RETCODE cutsTransformMIRRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, SCIP_Bool ignoresol, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Bool *freevariable, SCIP_Bool *localbdsused)
Definition: cuts.c:1233
SCIP_Real lhs
Definition: struct_lp.h:193
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17432
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6098
#define NULL
Definition: lpi_spx1.cpp:137
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13499
SCIP_Real SCIPsetFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5742
#define REALABS(x)
Definition: def.h:159
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17540
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:306
SCIP main data structure.
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17390
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17422
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5544
int var_probindex
Definition: struct_lp.h:167
static void findBestLb(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_SOL *sol, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *bestlb, int *bestlbtype)
Definition: cuts.c:229
internal methods for problem variables
#define SCIP_Bool
Definition: def.h:61
static void cutsSubstituteMIRRow(SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real *weights, SCIP_Real scale, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, int *rowinds, int nrowinds, SCIP_Real f0)
Definition: cuts.c:2407
unsigned int modifiable
Definition: struct_lp.h:247
int ncontvars
Definition: struct_prob.h:65
#define MAX(x, y)
Definition: tclique_def.h:75
methods for debugging
public methods for LP management
static void findBestUb(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_SOL *sol, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Real *bestub, int *bestubtype)
Definition: cuts.c:286
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16880
SCIP_ROW ** rows
Definition: struct_lp.h:286
SCIP_Real rhs
Definition: struct_lp.h:194
static void addRowToAggregation(SCIP_SET *set, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *slacksign, SCIP_Bool *varused, int *varinds, int *nvarinds, SCIP_ROW *row, SCIP_Real weight, SCIP_Bool uselhs)
Definition: cuts.c:407
SCIP_Real constant
Definition: struct_lp.h:192
internal methods for return codes for SCIP methods
SCIP_RETCODE SCIPcutsApplyMIR(SCIP *scip, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_Real *mksetcoefs, SCIP_Bool *mksetcoefsvalid, SCIP_Real *mircoef, SCIP_Real *mirrhs, int *varinds, int *nvarinds, SCIP_Real *minact, SCIP_Bool *varused, SCIP_Bool *success, SCIP_Bool *islocal)
Definition: cuts.c:3269
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6087
#define debugRowPrint(x)
Definition: cuts.c:87
void SCIPcutsCleanupRow(SCIP *scip, SCIP_Real *coefs, SCIP_Real *rhs, SCIP_Bool *varused, int *varinds, int *nvarinds, SCIP_Bool islocal)
Definition: cuts.c:3305
static SCIP_Real getMaxAbsWeightCalcSparsity(SCIP_SET *set, SCIP_LP *lp, SCIP_Real *weights, int *rowinds, int *nrowinds, int *rowlensum)
Definition: cuts.c:138
SCIP_SET * set
Definition: struct_scip.h:62
int nrows
Definition: struct_lp.h:311
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5598
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16671
void SCIPsortDownInt(int *intarray, int len)
static SCIP_Real getMIRMinActivity(SCIP_PROB *prob, SCIP_Real *mircoef, int *varinds, int nvarinds, SCIP_Bool islocal)
Definition: cuts.c:373
#define SCIP_Real
Definition: def.h:135
SCIP_VAR ** vars
Definition: struct_prob.h:55
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17412
static void cutsCleanupMIRRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, SCIP_Bool cutislocal)
Definition: cuts.c:840
SCIP_VAR * var
Definition: struct_lp.h:149
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16717
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
static SCIP_Real getMIRRowActivity(SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Real *mircoef, int *varinds, int nvarinds)
Definition: cuts.c:343
SCIP_Real SCIPsetSumFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5909
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
common defines and data types used in all packages of SCIP
static SCIP_RETCODE cutsLpCalcStrongCG(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, int *rowinds, int nrowinds, SCIP_Real scale, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank)
Definition: cuts.c:2564
SCIP_LP * lp
Definition: struct_scip.h:80
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16743
static void cutsRoundStrongCGRow(SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *strongcgcoef, SCIP_Real *strongcgrhs, SCIP_Bool *varused, int *varinds, int *nvarinds, int *varsign, int *boundtype, SCIP_Real f0, SCIP_Real k)
Definition: cuts.c:1838
unsigned int local
Definition: struct_lp.h:246
int len
Definition: struct_lp.h:224
SCIP callable library.
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16839