Scippy

SCIP

Solving Constraint Integer Programs

presol_stuffing.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file presol_stuffing.c
17  * @brief fix singleton continuous variables
18  * @author Dieter Weninger
19  *
20  * Investigate singleton continuous variables if one can be fixed at a bound.
21  *
22  */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <stdio.h>
27 #include <assert.h>
28 #include <string.h>
29 
30 
31 #include "scip/pub_matrix.h"
32 #include "presol_stuffing.h"
33 
34 #define PRESOL_NAME "stuffing"
35 #define PRESOL_DESC "fix redundant singleton continuous variables"
36 #define PRESOL_PRIORITY -100 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
37 #define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
38 #define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
39 
40 /** type of fixing direction */
42 {
43  FIXATLB = -1, /**< fix variable at lower bound */
44  NOFIX = 0, /**< do not fix variable */
45  FIXATUB = 1 /**< fix variable at upper bound */
46 };
48 
49 /*
50  * Local methods
51  */
52 
53 /** try to fix singleton continuous variables */
54 static
56  SCIP* scip, /**< SCIP main data structure */
57  SCIPMILPMATRIX* matrix, /**< matrix containing the constraints */
58  FIXINGDIRECTION* varstofix, /**< array holding fixing information */
59  int* nfixings /**< number of possible fixings */
60  )
61 {
62  SCIP_Real* valpnt;
63  SCIP_Real* colratios;
64  SCIP_Real* colcoeffs;
65  SCIP_Bool* rowprocessed;
66  int* rowpnt;
67  int* rowend;
68  int* colindices;
69  int* dummy;
70  SCIP_Bool* swapped;
71  SCIP_Real upperconst;
72  SCIP_Real lowerconst;
73  SCIP_Real coef;
74  SCIP_Real value;
75  SCIP_Real boundoffset;
76  SCIP_Bool tryfixing;
77  int idx;
78  int col;
79  int row;
80  int fillcnt;
81  int k;
82  int nrows;
83  int ncols;
84 
85  assert(scip != NULL);
86  assert(matrix != NULL);
87  assert(varstofix != NULL);
88  assert(nfixings != NULL);
89 
90  nrows = SCIPmatrixGetNRows(matrix);
91  ncols = SCIPmatrixGetNColumns(matrix);
92 
93  SCIP_CALL( SCIPallocBufferArray(scip, &colindices, ncols) );
94  SCIP_CALL( SCIPallocBufferArray(scip, &colratios, ncols) );
95  SCIP_CALL( SCIPallocBufferArray(scip, &colcoeffs, ncols) );
96  SCIP_CALL( SCIPallocBufferArray(scip, &dummy, ncols) );
97 
98  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, ncols) );
99  BMSclearMemoryArray(swapped, ncols);
100 
101  SCIP_CALL( SCIPallocBufferArray(scip, &rowprocessed, nrows) );
102  BMSclearMemoryArray(rowprocessed, nrows);
103 
104  for( col = 0; col < ncols; col++ )
105  {
106  /* consider only rows with minimal one continuous singleton column */
107  if( SCIPmatrixGetColNNonzs(matrix, col) == 1 &&
109  {
110  row = *(SCIPmatrixGetColIdxPtr(matrix, col));
111  if( rowprocessed[row] )
112  continue;
113 
114  rowprocessed[row] = TRUE;
115 
116  /* claim >= relation */
117  if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
118  {
119  fillcnt = 0;
120  tryfixing = TRUE;
121  upperconst = 0.0;
122  lowerconst = 0.0;
123 
124  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
125  rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
126  valpnt = SCIPmatrixGetRowValPtr(matrix, row);
127 
128  for( ; (rowpnt < rowend); rowpnt++, valpnt++ )
129  {
130  SCIP_VAR* var;
131  SCIP_Real lb;
132  SCIP_Real ub;
133 
134  coef = *valpnt;
135  idx = *rowpnt;
136  var = SCIPmatrixGetVar(matrix, idx);
137  lb = SCIPvarGetLbGlobal(var);
138  ub = SCIPvarGetUbGlobal(var);
139 
140  if( SCIPmatrixGetColNNonzs(matrix, idx) == 1 && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
141  {
142  /* need obj > 0 and coef > 0 */
143  if( SCIPvarGetObj(var) > 0 && coef > 0 )
144  {
145  if( SCIPisInfinity(scip, -lb) )
146  {
147  tryfixing = FALSE;
148  break;
149  }
150 
151  upperconst += coef * lb;
152  lowerconst += coef * lb;
153  colratios[fillcnt] = SCIPvarGetObj(var) / coef;
154  colindices[fillcnt] = idx;
155  colcoeffs[fillcnt] = coef;
156  fillcnt++;
157  }
158  else if( SCIPvarGetObj(var) < 0 && coef < 0 )
159  {
160  if( SCIPisInfinity(scip, ub) )
161  {
162  tryfixing = FALSE;
163  break;
164  }
165 
166  /* swap column and bounds */
167  swapped[idx] = TRUE;
168  upperconst += coef * ub;
169  lowerconst += coef * ub;
170  colratios[fillcnt] = SCIPvarGetObj(var) / coef;
171  colindices[fillcnt] = idx;
172  colcoeffs[fillcnt] = coef;
173  fillcnt++;
174  }
175  else if( SCIPvarGetObj(var) > 0 && coef < 0 )
176  {
177  if( SCIPisInfinity(scip, -lb) )
178  {
179  /* unbounded */
180  tryfixing = FALSE;
181  break;
182  }
183 
184  upperconst += coef * lb;
185  lowerconst += coef * lb;
186  }
187  else
188  {
189  /* obj < 0 and coef > 0 */
190  if( SCIPisInfinity(scip, ub) )
191  {
192  /* unbounded */
193  tryfixing = FALSE;
194  break;
195  }
196 
197  upperconst += coef * ub;
198  lowerconst += coef * ub;
199  }
200  }
201  else
202  {
203  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
204  {
205  tryfixing = FALSE;
206  break;
207  }
208 
209  /* discrete variables and non-singleton continuous variables */
210  if( coef > 0 )
211  {
212  upperconst += coef * ub;
213  lowerconst += coef * lb;
214  }
215  else
216  {
217  upperconst += coef * lb;
218  lowerconst += coef * ub;
219  }
220  }
221  }
222 
223  if( tryfixing )
224  {
225  SCIPsortRealRealIntInt(colratios, colcoeffs, colindices, dummy, fillcnt);
226 
227  /* verify which variable can be fixed */
228  for( k = 0; k < fillcnt; k++ )
229  {
230  SCIP_VAR* var;
231  SCIP_Real lb;
232  SCIP_Real ub;
233 
234  idx = colindices[k];
235  var = SCIPmatrixGetVar(matrix, idx);
236  lb = SCIPvarGetLbGlobal(var);
237  ub = SCIPvarGetUbGlobal(var);
238 
239  /* stop fixing if variable bounds are not finite */
240  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
241  break;
242 
243  assert(SCIPmatrixGetColNNonzs(matrix, idx) == 1 && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
244 
245  if( swapped[idx] )
246  {
247  value = colcoeffs[k] * lb;
248  boundoffset = colcoeffs[k] * ub;
249  }
250  else
251  {
252  value = colcoeffs[k] * ub;
253  boundoffset = colcoeffs[k] * lb;
254  }
255 
256  if( SCIPisLE(scip, value, SCIPmatrixGetRowLhs(matrix, row) - upperconst + boundoffset) )
257  {
258  if( swapped[idx] )
259  varstofix[idx] = FIXATLB;
260  else
261  varstofix[idx] = FIXATUB;
262 
263  (*nfixings)++;
264  }
265  else if( SCIPisLE(scip, SCIPmatrixGetRowLhs(matrix, row), lowerconst) )
266  {
267  if( swapped[idx] )
268  varstofix[idx] = FIXATUB;
269  else
270  varstofix[idx] = FIXATLB;
271 
272  (*nfixings)++;
273  }
274 
275  upperconst += value;
276  upperconst -= boundoffset;
277 
278  lowerconst += value;
279  lowerconst -= boundoffset;
280  }
281  }
282  }
283  }
284  }
285 
286  SCIPfreeBufferArray(scip, &rowprocessed);
287  SCIPfreeBufferArray(scip, &swapped);
288  SCIPfreeBufferArray(scip, &dummy);
289  SCIPfreeBufferArray(scip, &colcoeffs);
290  SCIPfreeBufferArray(scip, &colratios);
291  SCIPfreeBufferArray(scip, &colindices);
292 
293  return SCIP_OKAY;
294 }
295 
296 /*
297  * Callback methods of presolver
298  */
299 
300 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
301 static
302 SCIP_DECL_PRESOLCOPY(presolCopyStuffing)
303 { /*lint --e{715}*/
304  assert(scip != NULL);
305  assert(presol != NULL);
306  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
307 
308  /* call inclusion method of presolver */
310 
311  return SCIP_OKAY;
312 }
313 
314 /** execution method of presolver */
315 static
316 SCIP_DECL_PRESOLEXEC(presolExecStuffing)
317 { /*lint --e{715}*/
318  SCIPMILPMATRIX* matrix;
319  SCIP_Bool initialized;
320  SCIP_Bool complete;
321 
322  assert(result != NULL);
323  *result = SCIP_DIDNOTRUN;
324 
325  if( (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING) || SCIPinProbing(scip) || SCIPisNLPEnabled(scip) )
326  return SCIP_OKAY;
327 
328  if( SCIPgetNContVars(scip) == 0 || SCIPisStopped(scip) || SCIPgetNActivePricers(scip) > 0 )
329  return SCIP_OKAY;
330 
331  if( !SCIPallowDualReds(scip) )
332  return SCIP_OKAY;
333 
334  *result = SCIP_DIDNOTFIND;
335 
336  matrix = NULL;
337  SCIP_CALL( SCIPmatrixCreate(scip, &matrix, &initialized, &complete) );
338 
339  if( initialized )
340  {
341  FIXINGDIRECTION* varstofix;
342  int nfixings;
343  int ncols;
344 
345  nfixings = 0;
346  ncols = SCIPmatrixGetNColumns(matrix);
347 
348  SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
349  BMSclearMemoryArray(varstofix, ncols);
350 
351  SCIP_CALL( singletonColumnStuffing(scip, matrix, varstofix, &nfixings) );
352 
353  if( nfixings > 0 )
354  {
355  int v;
356  int oldnfixedvars;
357 
358  oldnfixedvars = *nfixedvars;
359 
360  /* look for fixable variables */
361  for( v = ncols - 1; v >= 0; --v )
362  {
363  SCIP_Bool infeasible;
364  SCIP_Bool fixed;
365  SCIP_VAR* var;
366 
367  var = SCIPmatrixGetVar(matrix, v);
368 
369  if( SCIPvarGetNLocksUp(var) != SCIPmatrixGetColNUplocks(matrix, v) ||
371  {
372  /* no fixing, locks not consistent */
373  continue;
374  }
375 
376  if( varstofix[v] == FIXATLB )
377  {
378  SCIP_Real lb;
379 
380  lb = SCIPvarGetLbGlobal(var);
381  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
382 
383  /* avoid fixings to infinite values */
384  assert(!SCIPisInfinity(scip, -lb));
385 
386  SCIPdebugMessage("Fix variable %s at lower bound %.15g\n", SCIPvarGetName(var), lb);
387 
388  /* fix at lower bound */
389  SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
390  if( infeasible )
391  {
392  SCIPdebugMessage(" -> infeasible fixing\n");
393  *result = SCIP_CUTOFF;
394 
395  break;
396  }
397  assert(fixed);
398  (*nfixedvars)++;
399  }
400  else if( varstofix[v] == FIXATUB )
401  {
402  SCIP_Real ub;
403 
404  ub = SCIPvarGetUbGlobal(var);
405  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
406 
407  /* avoid fixings to infinite values */
408  assert(!SCIPisInfinity(scip, ub));
409 
410  SCIPdebugMessage("Fix variable %s at upper bound %.15g\n", SCIPvarGetName(var), ub);
411 
412  /* fix at upper bound */
413  SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
414  if( infeasible )
415  {
416  SCIPdebugMessage(" -> infeasible fixing\n");
417  *result = SCIP_CUTOFF;
418 
419  break;
420  }
421  assert(fixed);
422 
423  (*nfixedvars)++;
424  }
425  }
426 
427  if( *result != SCIP_CUTOFF && *nfixedvars > oldnfixedvars )
428  *result = SCIP_SUCCESS;
429  }
430 
431  SCIPfreeBufferArray(scip, &varstofix);
432  }
433 
434  SCIPmatrixFree(scip, &matrix);
435 
436  return SCIP_OKAY;
437 }
438 
439 /*
440  * presolver specific interface methods
441  */
442 
443 /** creates the stuffing presolver and includes it in SCIP */
445  SCIP* scip /**< SCIP data structure */
446  )
447 {
448  SCIP_PRESOL* presol;
449 
450  /* include presolver */
452  PRESOL_TIMING, presolExecStuffing, NULL) );
453  SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyStuffing) );
454 
455  return SCIP_OKAY;
456 }
457 
458 /*lint --e{749}*/
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:22764
SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIPMILPMATRIX *matrix, int row)
Definition: matrix.c:1420
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
int SCIPmatrixGetColNDownlocks(SCIPMILPMATRIX *matrix, int col)
Definition: matrix.c:1312
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41256
static SCIP_DECL_PRESOLEXEC(presolExecStuffing)
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
Definition: scip.c:6195
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16965
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition: presol.c:553
fix singleton continuous variables
#define FALSE
Definition: def.h:53
#define TRUE
Definition: def.h:52
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:23070
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip.c:4986
#define SCIPdebugMessage
Definition: pub_message.h:77
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16803
int * SCIPmatrixGetColIdxPtr(SCIPMILPMATRIX *matrix, int col)
Definition: matrix.c:1250
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10915
SCIP_RETCODE SCIPincludePresolStuffing(SCIP *scip)
static SCIP_DECL_PRESOLCOPY(presolCopyStuffing)
void SCIPsortRealRealIntInt(SCIP_Real *realarray1, SCIP_Real *realarray2, int *intarray1, int *intarray2, int len)
enum Fixingdirection FIXINGDIRECTION
Definition: presol_domcol.c:77
Fixingdirection
Definition: presol_domcol.c:71
int SCIPmatrixGetNRows(SCIPMILPMATRIX *matrix)
Definition: matrix.c:1389
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
int SCIPmatrixGetColNUplocks(SCIPMILPMATRIX *matrix, int col)
Definition: matrix.c:1301
SCIP_Real * SCIPmatrixGetRowValPtr(SCIPMILPMATRIX *matrix, int row)
Definition: matrix.c:1345
int SCIPmatrixGetNColumns(SCIPMILPMATRIX *matrix)
Definition: matrix.c:1272
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41206
#define PRESOL_PRIORITY
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIPMILPMATRIX **matrixptr, SCIP_Bool *initialized, SCIP_Bool *complete)
Definition: matrix.c:429
#define PRESOL_NAME
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:31741
int * SCIPmatrixGetRowIdxPtr(SCIPMILPMATRIX *matrix, int row)
Definition: matrix.c:1356
void SCIPmatrixFree(SCIP *scip, SCIPMILPMATRIX **matrix)
Definition: matrix.c:787
SCIP_VAR * SCIPmatrixGetVar(SCIPMILPMATRIX *matrix, int col)
Definition: matrix.c:1323
#define SCIP_Bool
Definition: def.h:50
#define PRESOL_DESC
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
Definition: scip.c:28356
#define PRESOL_MAXROUNDS
int SCIPmatrixGetColNNonzs(SCIPMILPMATRIX *matrix, int col)
Definition: matrix.c:1261
public methods for MILP matrix
static SCIP_RETCODE singletonColumnStuffing(SCIP *scip, SCIPMILPMATRIX *matrix, FIXINGDIRECTION *varstofix, int *nfixings)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
#define SCIP_Real
Definition: def.h:124
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
int SCIPmatrixGetRowNNonzs(SCIPMILPMATRIX *matrix, int row)
Definition: matrix.c:1367
#define PRESOL_TIMING
enum Fixingdirection FIXINGDIRECTION
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
Definition: scip.c:6160
SCIP_Real SCIPmatrixGetRowLhs(SCIPMILPMATRIX *matrix, int row)
Definition: matrix.c:1398