Scippy

SCIP

Solving Constraint Integer Programs

presol_milp.cpp
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-2022 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 visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file presol_milp.cpp
17  * @brief MILP presolver
18  * @author Leona Gottwald
19  *
20  * Calls the presolve library and communicates (multi-)aggregations, fixings, and bound
21  * changes to SCIP by utilizing the postsolve information. Constraint changes can currently
22  * only be communicated by deleting all constraints and adding new ones.
23  *
24  * @todo add infrastructure to SCIP for handling parallel columns
25  * @todo better communication of constraint changes by adding more information to the postsolve structure
26  * @todo allow to pass additional external locks to the presolve library that are considered when doing reductions
27  *
28  */
29 
30 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
31 
32 #include "scip/presol_milp.h"
33 
34 #ifndef SCIP_WITH_PAPILO
35 
36 /** creates the MILP presolver and includes it in SCIP */
38  SCIP* scip /**< SCIP data structure */
39  )
40 {
41  assert(scip != NULL);
42  return SCIP_OKAY;
43 }
44 
45 #else
46 
47 /* disable some warnings that come up in header files of PAPILOs dependencies */
48 #ifdef __GNUC__
49 #pragma GCC diagnostic ignored "-Wshadow"
50 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
51 #pragma GCC diagnostic ignored "-Wredundant-decls"
52 #endif
53 
54 #include <assert.h>
55 #include "scip/cons_linear.h"
56 #include "scip/pub_matrix.h"
57 #include "scip/pub_presol.h"
58 #include "scip/pub_var.h"
59 #include "scip/pub_cons.h"
60 #include "scip/pub_message.h"
61 #include "scip/scip_general.h"
62 #include "scip/scip_presol.h"
63 #include "scip/scip_var.h"
64 #include "scip/scip_mem.h"
65 #include "scip/scip_prob.h"
66 #include "scip/scip_param.h"
67 #include "scip/scip_cons.h"
68 #include "scip/scip_numerics.h"
69 #include "scip/scip_timing.h"
70 #include "scip/scip_message.h"
71 #include "scip/scip_randnumgen.h"
72 #include "papilo/core/Presolve.hpp"
73 #include "papilo/core/ProblemBuilder.hpp"
74 #include "papilo/Config.hpp"
75 
76 #define PRESOL_NAME "milp"
77 #define PRESOL_DESC "MILP specific presolving methods"
78 #define PRESOL_PRIORITY 9999999 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers); combined with propagators */
79 #define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
80 #define PRESOL_TIMING SCIP_PRESOLTIMING_MEDIUM /* timing of the presolver (fast, medium, or exhaustive) */
81 
82 /* default parameter values */
83 #define DEFAULT_THREADS 1 /**< maximum number of threads presolving may use (0: automatic) */
84 #define DEFAULT_MAXFILLINPERSUBST 3 /**< maximal possible fillin for substitutions to be considered */
85 #define DEFAULT_MAXSHIFTPERROW 10 /**< maximal amount of nonzeros allowed to be shifted to make space for substitutions */
86 #define DEFAULT_DETECTLINDEP 0 /**< should linear dependent equations and free columns be removed? (0: never, 1: for LPs, 2: always) */
87 #define DEFAULT_MAXBADGESIZE_SEQ 15000 /**< the max badge size in Probing if PaPILO is executed in sequential mode*/
88 #define DEFAULT_MAXBADGESIZE_PAR -1 /**< the max badge size in Probing if PaPILO is executed in parallel mode*/
89 #define DEFAULT_RANDOMSEED 0 /**< the random seed used for randomization of tie breaking */
90 #define DEFAULT_MODIFYCONSFAC 0.8 /**< modify SCIP constraints when the number of nonzeros or rows is at most this
91  * factor times the number of nonzeros or rows before presolving */
92 #define DEFAULT_MARKOWITZTOLERANCE 0.01 /**< the markowitz tolerance used for substitutions */
93 #define DEFAULT_HUGEBOUND 1e8 /**< absolute bound value that is considered too huge for activitity based calculations */
94 #define DEFAULT_ENABLEPARALLELROWS TRUE /**< should the parallel rows presolver be enabled within the presolve library? */
95 #define DEFAULT_ENABLEDOMCOL TRUE /**< should the dominated column presolver be enabled within the presolve library? */
96 #define DEFAULT_ENABLEDUALINFER TRUE /**< should the dualinfer presolver be enabled within the presolve library? */
97 #define DEFAULT_ENABLEMULTIAGGR TRUE /**< should the multi-aggregation presolver be enabled within the presolve library? */
98 #define DEFAULT_ENABLEPROBING TRUE /**< should the probing presolver be enabled within the presolve library? */
99 #define DEFAULT_ENABLESPARSIFY FALSE /**< should the sparsify presolver be enabled within the presolve library? */
100 #define DEFAULT_FILENAME_PROBLEM "-" /**< default filename to store the instance before presolving */
101 
102 /*
103  * Data structures
104  */
105 
106 /** presolver data */
107 struct SCIP_PresolData
108 {
109  int lastncols; /**< the number of columns from the last call */
110  int lastnrows; /**< the number of rows from the last call */
111  int threads; /**< maximum number of threads presolving may use (0: automatic) */
112  int maxfillinpersubstitution; /**< maximal possible fillin for substitutions to be considered */
113  int maxbadgesizeseq; /**< the max badge size in Probing if PaPILO is called in sequential mode*/
114  int maxbadgesizepar; /**< the max badge size in Probing if PaPILO is called in parallel mode */
115  int maxshiftperrow; /**< maximal amount of nonzeros allowed to be shifted to make space for substitutions */
116  int detectlineardependency; /**< should linear dependent equations and free columns be removed? (0: never, 1: for LPs, 2: always) */
117  int randomseed; /**< the random seed used for randomization of tie breaking */
118  SCIP_Bool enablesparsify; /**< should the sparsify presolver be enabled within the presolve library? */
119  SCIP_Bool enabledomcol; /**< should the dominated column presolver be enabled within the presolve library? */
120  SCIP_Bool enableprobing; /**< should the probing presolver be enabled within the presolve library? */
121  SCIP_Bool enabledualinfer; /**< should the dualinfer presolver be enabled within the presolve library? */
122  SCIP_Bool enablemultiaggr; /**< should the multi-aggregation presolver be enabled within the presolve library? */
123  SCIP_Bool enableparallelrows; /**< should the parallel rows presolver be enabled within the presolve library? */
124  SCIP_Real modifyconsfac; /**< modify SCIP constraints when the number of nonzeros or rows is at most this
125  * factor times the number of nonzeros or rows before presolving */
126  SCIP_Real markowitztolerance; /**< the markowitz tolerance used for substitutions */
127  SCIP_Real hugebound; /**< absolute bound value that is considered too huge for activitity based calculations */
128 
129  char* filename = NULL; /**< filename to store the instance before presolving */
130 
131 };
132 
133 using namespace papilo;
134 
135 /*
136  * Local methods
137  */
138 
139 /** builds the presolvelib problem datastructure from the matrix */
140 static
141 Problem<SCIP_Real> buildProblem(
142  SCIP* scip, /**< SCIP data structure */
143  SCIP_MATRIX* matrix /**< initialized SCIP_MATRIX data structure */
144  )
145 {
146  ProblemBuilder<SCIP_Real> builder;
147 
148  /* build problem from matrix */
149  int nnz = SCIPmatrixGetNNonzs(matrix);
150  int ncols = SCIPmatrixGetNColumns(matrix);
151  int nrows = SCIPmatrixGetNRows(matrix);
152  builder.reserve(nnz, nrows, ncols);
153 
154  /* set up columns */
155  builder.setNumCols(ncols);
156  for(int i = 0; i != ncols; ++i)
157  {
158  SCIP_VAR* var = SCIPmatrixGetVar(matrix, i);
159  SCIP_Real lb = SCIPvarGetLbGlobal(var);
160  SCIP_Real ub = SCIPvarGetUbGlobal(var);
161  builder.setColLb(i, lb);
162  builder.setColUb(i, ub);
163  builder.setColLbInf(i, SCIPisInfinity(scip, -lb));
164  builder.setColUbInf(i, SCIPisInfinity(scip, ub));
165 
166  if ( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT )
167  builder.setColImplInt(i, TRUE);
168  else
169  builder.setColIntegral(i, SCIPvarIsIntegral(var));
170  builder.setObj(i, SCIPvarGetObj(var));
171  }
172 
173  /* set up rows */
174  builder.setNumRows(nrows);
175  for(int i = 0; i != nrows; ++i)
176  {
177  int* rowcols = SCIPmatrixGetRowIdxPtr(matrix, i);
178  SCIP_Real* rowvals = SCIPmatrixGetRowValPtr(matrix, i);
179  int rowlen = SCIPmatrixGetRowNNonzs(matrix, i);
180  builder.addRowEntries(i, rowlen, rowcols, rowvals);
181 
182  SCIP_Real lhs = SCIPmatrixGetRowLhs(matrix, i);
183  SCIP_Real rhs = SCIPmatrixGetRowRhs(matrix, i);
184  builder.setRowLhs(i, lhs);
185  builder.setRowRhs(i, rhs);
186  builder.setRowLhsInf(i, SCIPisInfinity(scip, -lhs));
187  builder.setRowRhsInf(i, SCIPisInfinity(scip, rhs));
188  }
189 
190  /* init objective offset - the value itself is irrelevant */
191  builder.setObjOffset(0);
192 
193  return builder.build();
194 }
195 
196 /*
197  * Callback methods of presolver
198  */
199 
200 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
201 static
202 SCIP_DECL_PRESOLCOPY(presolCopyMILP)
203 { /*lint --e{715}*/
205 
206  return SCIP_OKAY;
207 }
208 
209 /** destructor of presolver to free user data (called when SCIP is exiting) */
210 static
211 SCIP_DECL_PRESOLFREE(presolFreeMILP)
212 { /*lint --e{715}*/
213  SCIP_PRESOLDATA* data = SCIPpresolGetData(presol);
214  assert(data != NULL);
215 
216  SCIPpresolSetData(presol, NULL);
217  SCIPfreeBlockMemory(scip, &data);
218  return SCIP_OKAY;
219 }
220 
221 /** initialization method of presolver (called after problem was transformed) */
222 static
223 SCIP_DECL_PRESOLINIT(presolInitMILP)
224 { /*lint --e{715}*/
225  SCIP_PRESOLDATA* data = SCIPpresolGetData(presol);
226  assert(data != NULL);
227 
228  data->lastncols = -1;
229  data->lastnrows = -1;
230 
231  return SCIP_OKAY;
232 }
233 
234 /** execution method of presolver */
235 static
236 SCIP_DECL_PRESOLEXEC(presolExecMILP)
237 { /*lint --e{715}*/
238  SCIP_MATRIX* matrix;
239  SCIP_PRESOLDATA* data;
240  SCIP_Bool initialized;
241  SCIP_Bool complete;
242  SCIP_Bool infeasible;
243  SCIP_Real timelimit;
244 
245  *result = SCIP_DIDNOTRUN;
246 
247  data = SCIPpresolGetData(presol);
248 
249  int nvars = SCIPgetNVars(scip);
250  int nconss = SCIPgetNConss(scip);
251 
252  /* run only if the problem size reduced by some amount since the last call or if it is the first call */
253  if( data->lastncols != -1 && data->lastnrows != -1 &&
254  nvars > data->lastncols * 0.85 &&
255  nconss > data->lastnrows * 0.85 )
256  return SCIP_OKAY;
257 
258  SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
259  naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
260 
261  /* if infeasibility was detected during matrix creation, return here */
262  if( infeasible )
263  {
264  if( initialized )
265  SCIPmatrixFree(scip, &matrix);
266 
267  *result = SCIP_CUTOFF;
268  return SCIP_OKAY;
269  }
270 
271  /* we only work on pure MIPs, also disable to try building the matrix again if it failed once */
272  if( !initialized || !complete )
273  {
274  data->lastncols = 0;
275  data->lastnrows = 0;
276 
277  if( initialized )
278  SCIPmatrixFree(scip, &matrix);
279 
280  return SCIP_OKAY;
281  }
282 
283  /* only allow communication of constraint modifications by deleting all constraints when they have not been upgraded yet */
284  SCIP_CONSHDLR* linconshdlr = SCIPfindConshdlr(scip, "linear");
285  assert(linconshdlr != NULL);
286  bool allowconsmodification = (SCIPconshdlrGetNCheckConss(linconshdlr) == SCIPmatrixGetNRows(matrix));
287 
288  Problem<SCIP_Real> problem = buildProblem(scip, matrix);
289  Presolve<SCIP_Real> presolve;
290 
291  /* store current numbers of aggregations, fixings, and changed bounds for statistics */
292  int oldnaggrvars = *naggrvars;
293  int oldnfixedvars = *nfixedvars;
294  int oldnchgbds = *nchgbds;
295 
296  /* important so that SCIP does not throw an error, e.g. when an integer variable is substituted
297  * into a knapsack constraint */
298  presolve.getPresolveOptions().substitutebinarieswithints = false;
299 
300  /* currently these changes cannot be communicated to SCIP correctly since a constraint needs
301  * to be modified in the cases where slackvariables are removed from constraints but for the
302  * presolve library those look like normal substitution on the postsolve stack */
303  presolve.getPresolveOptions().removeslackvars = false;
304 
305  /* communicate the SCIP parameters to the presolve libary */
306  presolve.getPresolveOptions().maxfillinpersubstitution = data->maxfillinpersubstitution;
307  presolve.getPresolveOptions().markowitz_tolerance = data->markowitztolerance;
308  presolve.getPresolveOptions().maxshiftperrow = data->maxshiftperrow;
309  presolve.getPresolveOptions().hugeval = data->hugebound;
310 
311  /* removal of linear dependent equations has only an effect when constraint modifications are communicated */
312  presolve.getPresolveOptions().detectlindep = allowconsmodification ? data->detectlineardependency : 0;
313 
314  /* communicate the random seed */
315  presolve.getPresolveOptions().randomseed = SCIPinitializeRandomSeed(scip, (unsigned int)data->randomseed);
316 
317  /* set number of threads to be used for presolve */
318  presolve.getPresolveOptions().threads = data->threads;
319 
320  /* disable dual reductions that are not permitted */
321  if( !complete )
322  presolve.getPresolveOptions().dualreds = 0;
323  else if( SCIPallowStrongDualReds(scip) )
324  presolve.getPresolveOptions().dualreds = 2;
325  else if( SCIPallowWeakDualReds(scip) )
326  presolve.getPresolveOptions().dualreds = 1;
327  else
328  presolve.getPresolveOptions().dualreds = 0;
329 
330  /* set up the presolvers that shall participate */
331  using uptr = std::unique_ptr<PresolveMethod<SCIP_Real>>;
332 
333  /* fast presolvers*/
334  presolve.addPresolveMethod( uptr( new SingletonCols<SCIP_Real>() ) );
335  presolve.addPresolveMethod( uptr( new CoefficientStrengthening<SCIP_Real>() ) );
336  presolve.addPresolveMethod( uptr( new ConstraintPropagation<SCIP_Real>() ) );
337 
338  /* medium presolver */
339  presolve.addPresolveMethod( uptr( new SimpleProbing<SCIP_Real>() ) );
340  if( data->enableparallelrows )
341  presolve.addPresolveMethod( uptr( new ParallelRowDetection<SCIP_Real>() ) );
342  /* todo: parallel cols cannot be handled by SCIP currently
343  * addPresolveMethod( uptr( new ParallelColDetection<SCIP_Real>() ) ); */
344  presolve.addPresolveMethod( uptr( new SingletonStuffing<SCIP_Real>() ) );
345 #if PAPILO_VERSION_MAJOR > 2 || (PAPILO_VERSION_MAJOR == 2 && PAPILO_VERSION_MINOR >= 1)
346  DualFix<SCIP_Real> *dualfix = new DualFix<SCIP_Real>();
347  dualfix->set_fix_to_infinity_allowed(false);
348  presolve.addPresolveMethod( uptr( dualfix ) );
349 #else
350  presolve.addPresolveMethod( uptr( new DualFix<SCIP_Real>() ) );
351 #endif
352  presolve.addPresolveMethod( uptr( new FixContinuous<SCIP_Real>() ) );
353  presolve.addPresolveMethod( uptr( new SimplifyInequalities<SCIP_Real>() ) );
354  presolve.addPresolveMethod( uptr( new SimpleSubstitution<SCIP_Real>() ) );
355 
356  /* exhaustive presolvers*/
357  presolve.addPresolveMethod( uptr( new ImplIntDetection<SCIP_Real>() ) );
358  if( data->enabledualinfer )
359  presolve.addPresolveMethod( uptr( new DualInfer<SCIP_Real>() ) );
360  if( data->enableprobing )
361  {
362 #if PAPILO_VERSION_MAJOR > 2 || (PAPILO_VERSION_MAJOR == 2 && PAPILO_VERSION_MINOR >= 1)
363  Probing<SCIP_Real> *probing = new Probing<SCIP_Real>();
364  if( presolve.getPresolveOptions().runs_sequential() )
365  {
366  probing->set_max_badge_size( data->maxbadgesizeseq );
367  }
368  else
369  {
370  probing->set_max_badge_size( data->maxbadgesizepar );
371  }
372  presolve.addPresolveMethod( uptr( probing ) );
373 
374 #else
375  presolve.addPresolveMethod( uptr( new Probing<SCIP_Real>() ) );
376  if( data->maxbadgesizeseq != DEFAULT_MAXBADGESIZE_SEQ )
378  " The parameter 'presolving/milp/maxbadgesizeseq' can only be used with PaPILO 2.1.0 or later versions.\n");
379 
380  if( data->maxbadgesizepar != DEFAULT_MAXBADGESIZE_PAR )
382  " The parameter 'presolving/milp/maxbadgesizepar' can only be used with PaPILO 2.1.0 or later versions.\n");
383 
384 #endif
385  }
386  if( data->enabledomcol )
387  presolve.addPresolveMethod( uptr( new DominatedCols<SCIP_Real>() ) );
388  if( data->enablemultiaggr )
389  presolve.addPresolveMethod( uptr( new Substitution<SCIP_Real>() ) );
390  if( data->enablesparsify )
391  presolve.addPresolveMethod( uptr( new Sparsify<SCIP_Real>() ) );
392 
393 
394  /* set tolerances */
395  presolve.getPresolveOptions().feastol = SCIPfeastol(scip);
396  presolve.getPresolveOptions().epsilon = SCIPepsilon(scip);
397 
398  /* adjust output settings of presolve library */
399 #ifdef SCIP_PRESOLLIB_ENABLE_OUTPUT
400  problem.setName(SCIPgetProbName(scip));
401 #else
402  presolve.setVerbosityLevel(VerbosityLevel::kQuiet);
403 #endif
404 
405  /* communicate the time limit */
406  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
407  if( !SCIPisInfinity(scip, timelimit) )
408  presolve.getPresolveOptions().tlim = timelimit - SCIPgetSolvingTime(scip);
409 
410  if( 0 != strncmp(data->filename, DEFAULT_FILENAME_PROBLEM, strlen(DEFAULT_FILENAME_PROBLEM)) )
411  {
412  SCIP_CALL(SCIPwriteTransProblem(scip, data->filename, NULL, FALSE));
413  }
414 
415  /* call the presolving */
417  " (%.1fs) running MILP presolver\n", SCIPgetSolvingTime(scip));
418  int oldnnz = problem.getConstraintMatrix().getNnz();
419 
420  /*call presolving without storing information for dual postsolve*/
421 #if (PAPILO_VERSION_MAJOR >= 2)
422  PresolveResult<SCIP_Real> res = presolve.apply(problem, false);
423 #else
424  PresolveResult<SCIP_Real> res = presolve.apply(problem);
425 #endif
426  data->lastncols = problem.getNCols();
427  data->lastnrows = problem.getNRows();
428 
429  /* evaluate the result */
430  switch(res.status)
431  {
432  case PresolveStatus::kInfeasible:
433  *result = SCIP_CUTOFF;
435  " (%.1fs) MILP presolver detected infeasibility\n",
436  SCIPgetSolvingTime(scip));
437  SCIPmatrixFree(scip, &matrix);
438  return SCIP_OKAY;
439  case PresolveStatus::kUnbndOrInfeas:
440  case PresolveStatus::kUnbounded:
441  *result = SCIP_UNBOUNDED;
443  " (%.1fs) MILP presolver detected unboundedness\n",
444  SCIPgetSolvingTime(scip));
445  SCIPmatrixFree(scip, &matrix);
446  return SCIP_OKAY;
447  case PresolveStatus::kUnchanged:
448  *result = SCIP_DIDNOTFIND;
449  data->lastncols = nvars;
450  data->lastnrows = nconss;
452  " (%.1fs) MILP presolver found nothing\n",
453  SCIPgetSolvingTime(scip));
454  SCIPmatrixFree(scip, &matrix);
455  return SCIP_OKAY;
456  case PresolveStatus::kReduced:
457  data->lastncols = problem.getNCols();
458  data->lastnrows = problem.getNRows();
459  *result = SCIP_SUCCESS;
460  }
461 
462  /* result indicated success, now populate the changes into the SCIP structures */
463  std::vector<SCIP_VAR*> tmpvars;
464  std::vector<SCIP_Real> tmpvals;
465 
466  /* if the number of nonzeros decreased by a sufficient factor, rather create all constraints from scratch */
467  int newnnz = problem.getConstraintMatrix().getNnz();
468  bool constraintsReplaced = false;
469  if( newnnz == 0 || (allowconsmodification &&
470  (problem.getNRows() <= data->modifyconsfac * data->lastnrows ||
471  newnnz <= data->modifyconsfac * oldnnz)) )
472  {
473  int oldnrows = SCIPmatrixGetNRows(matrix);
474  int newnrows = problem.getNRows();
475 
476  constraintsReplaced = true;
477 
478  /* capture constraints that are still present in the problem after presolve */
479  for( int i = 0; i < newnrows; ++i )
480  {
481  SCIP_CONS* c = SCIPmatrixGetCons(matrix, res.postsolve.origrow_mapping[i]);
482  SCIP_CALL( SCIPcaptureCons(scip, c) );
483  }
484 
485  /* delete all constraints */
486  *ndelconss += oldnrows;
487  *naddconss += newnrows;
488 
489  for( int i = 0; i < oldnrows; ++i )
490  {
491  SCIP_CALL( SCIPdelCons(scip, SCIPmatrixGetCons(matrix, i)) );
492  }
493 
494  /* now loop over rows of presolved problem and create them as new linear constraints,
495  * then release the old constraint after its name was passed to the new constraint */
496  const Vec<RowFlags>& rflags = problem.getRowFlags();
497  const auto& consmatrix = problem.getConstraintMatrix();
498  for( int i = 0; i < newnrows; ++i )
499  {
500  auto rowvec = consmatrix.getRowCoefficients(i);
501  const int* rowcols = rowvec.getIndices();
502  /* SCIPcreateConsBasicLinear() requires a non const pointer */
503  SCIP_Real* rowvals = const_cast<SCIP_Real*>(rowvec.getValues());
504  int rowlen = rowvec.getLength();
505 
506  /* retrieve SCIP compatible left and right hand sides */
507  SCIP_Real lhs = rflags[i].test(RowFlag::kLhsInf) ? - SCIPinfinity(scip) : consmatrix.getLeftHandSides()[i];
508  SCIP_Real rhs = rflags[i].test(RowFlag::kRhsInf) ? SCIPinfinity(scip) : consmatrix.getRightHandSides()[i];
509 
510  /* create variable array matching the value array */
511  tmpvars.clear();
512  tmpvars.reserve(rowlen);
513  for( int j = 0; j < rowlen; ++j )
514  tmpvars.push_back(SCIPmatrixGetVar(matrix, res.postsolve.origcol_mapping[rowcols[j]]));
515 
516  /* create and add new constraint with name of old constraint */
517  SCIP_CONS* oldcons = SCIPmatrixGetCons(matrix, res.postsolve.origrow_mapping[i]);
518  SCIP_CONS* cons;
519  SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons, SCIPconsGetName(oldcons), rowlen, tmpvars.data(), rowvals, lhs, rhs) );
520  SCIP_CALL( SCIPaddCons(scip, cons) );
521 
522  /* release old and new constraint */
523  SCIP_CALL( SCIPreleaseCons(scip, &oldcons) );
524  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
525  }
526  }
527 
528  /* loop over res.postsolve and add all fixed variables and aggregations to scip */
529  for( std::size_t i = 0; i != res.postsolve.types.size(); ++i )
530  {
531  ReductionType type = res.postsolve.types[i];
532  int first = res.postsolve.start[i];
533  int last = res.postsolve.start[i + 1];
534 
535  switch( type )
536  {
537  case ReductionType::kFixedCol:
538  {
539  SCIP_Bool infeas;
540  SCIP_Bool fixed;
541  int col = res.postsolve.indices[first];
542 
543  SCIP_VAR* var = SCIPmatrixGetVar(matrix, col);
544 
545  SCIP_Real value = res.postsolve.values[first];
546 
547  SCIP_CALL( SCIPfixVar(scip, var, value, &infeas, &fixed) );
548  *nfixedvars += 1;
549 
550  assert(!infeas);
551  /* SCIP has different rules for aggregating variables than PaPILO: therefore the variable PaPILO
552  * tries to fix now may have been aggregated by SCIP before. Additionally, after aggregation SCIP
553  * sometimes performs bound tightening resulting in possible fixings. These cases need to be excluded. */
554  assert(fixed || SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED ||
556  break;
557  }
558 /*
559  * Dual-postsolving in PaPILO required introducing a postsolve-type for substitution with additional information.
560  * Further, the different Substitution-postsolving types store the required postsolving data differently (in different order) in the postsolving stack.
561  * Therefore, we need to distinguish how to parse the required data (rowLength, col, side, startRowCoefficients, lastRowCoefficients) from the postsolving stack.
562  * If these values are accessed, the procedure is the same for both.
563  */
564 #if (PAPILO_VERSION_MAJOR >= 2)
565  case ReductionType::kSubstitutedColWithDual:
566 #endif
567  case ReductionType::kSubstitutedCol:
568  {
569  int col = 0;
570  SCIP_Real side = 0;
571 
572  int rowlen = 0;
573  int startRowCoefficients = 0;
574  int lastRowCoefficients = 0;
575 
576  if( type == ReductionType::kSubstitutedCol )
577  {
578  rowlen = last - first - 1;
579  col = res.postsolve.indices[first];
580  side = res.postsolve.values[first];
581 
582  startRowCoefficients = first + 1;
583  lastRowCoefficients = last;
584  }
585 #if (PAPILO_VERSION_MAJOR >= 2)
586  if( type == ReductionType::kSubstitutedColWithDual )
587  {
588  rowlen = (int) res.postsolve.values[first];
589  col = res.postsolve.indices[first + 3 + rowlen];
590  side = res.postsolve.values[first + 1];
591 
592  startRowCoefficients = first + 3;
593  lastRowCoefficients = first + 3 + rowlen;
594 
595  assert(side == res.postsolve.values[first + 2]);
596  assert(res.postsolve.indices[first + 1] == 0);
597  assert(res.postsolve.indices[first + 2] == 0);
598 
599  }
600  assert( type == ReductionType::kSubstitutedCol || type == ReductionType::kSubstitutedColWithDual );
601 #else
602  assert( type == ReductionType::kSubstitutedCol );
603 #endif
604  SCIP_Bool infeas;
605  SCIP_Bool aggregated;
606  SCIP_Bool redundant = FALSE;
607  SCIP_Real constant = 0.0;
608  if( rowlen == 2 )
609  {
610  SCIP_Real updatedSide;
611  SCIP_VAR* varx = SCIPmatrixGetVar(matrix, res.postsolve.indices[startRowCoefficients]);
612  SCIP_VAR* vary = SCIPmatrixGetVar(matrix, res.postsolve.indices[startRowCoefficients + 1]);
613  SCIP_Real scalarx = res.postsolve.values[startRowCoefficients];
614  SCIP_Real scalary = res.postsolve.values[startRowCoefficients + 1];
615 
616  SCIP_CALL( SCIPgetProbvarSum(scip, &varx, &scalarx, &constant) );
617  assert(SCIPvarGetStatus(varx) != SCIP_VARSTATUS_MULTAGGR);
618 
619  SCIP_CALL( SCIPgetProbvarSum(scip, &vary, &scalary, &constant) );
620  assert(SCIPvarGetStatus(vary) != SCIP_VARSTATUS_MULTAGGR);
621 
622  updatedSide = side - constant;
623 
624  SCIP_CALL( SCIPaggregateVars(scip, varx, vary, scalarx, scalary, updatedSide, &infeas, &redundant, &aggregated) );
625  }
626  else
627  {
628  SCIP_Real colCoef = 0.0;
629  SCIP_Real updatedSide;
630 
631  for( int j = startRowCoefficients; j < lastRowCoefficients; ++j )
632  {
633  if( res.postsolve.indices[j] == col )
634  {
635  colCoef = res.postsolve.values[j];
636  break;
637  }
638  }
639 
640  tmpvars.clear();
641  tmpvals.clear();
642  tmpvars.reserve(rowlen);
643  tmpvals.reserve(rowlen);
644 
645  assert(colCoef != 0.0);
646  SCIP_VAR* aggrvar = SCIPmatrixGetVar(matrix, col);
647 
648  SCIP_CALL( SCIPgetProbvarSum(scip, &aggrvar, &colCoef, &constant) );
649  assert(SCIPvarGetStatus(aggrvar) != SCIP_VARSTATUS_MULTAGGR);
650 
651  updatedSide = side - constant;
652 
653  for( int j = startRowCoefficients; j < lastRowCoefficients; ++j )
654  {
655  if( res.postsolve.indices[j] == col )
656  continue;
657 
658  tmpvars.push_back(SCIPmatrixGetVar(matrix, res.postsolve.indices[j]));
659  tmpvals.push_back(- res.postsolve.values[j] / colCoef);
660  }
661 
662  SCIP_CALL( SCIPmultiaggregateVar(scip, aggrvar, tmpvars.size(),
663  tmpvars.data(), tmpvals.data(), updatedSide / colCoef, &infeas, &aggregated) );
664  }
665 
666  if( aggregated )
667  *naggrvars += 1;
668  else if( constraintsReplaced && !redundant )
669  {
670  /* if the constraints where replaced, we need to add the failed substitution as an equality to SCIP */
671  tmpvars.clear();
672  tmpvals.clear();
673  for( int j = startRowCoefficients; j < lastRowCoefficients; ++j )
674  {
675  tmpvars.push_back(SCIPmatrixGetVar(matrix, res.postsolve.indices[j]));
676  tmpvals.push_back(res.postsolve.values[j]);
677  }
678 
679  SCIP_CONS* cons;
680  String name = fmt::format("{}_failed_aggregation_equality", SCIPvarGetName(SCIPmatrixGetVar(matrix, col)));
681  SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons, name.c_str(),
682  tmpvars.size(), tmpvars.data(), tmpvals.data(), side, side ) );
683  SCIP_CALL( SCIPaddCons(scip, cons) );
684  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
685  *naddconss += 1;
686  }
687 
688  if( infeas )
689  {
690  *result = SCIP_CUTOFF;
691  break;
692  }
693 
694  break;
695  }
696  case ReductionType::kParallelCol:
697  return SCIP_INVALIDRESULT;
698 #if (PAPILO_VERSION_MAJOR <= 1 && PAPILO_VERSION_MINOR==0)
699 #else
700  case ReductionType::kFixedInfCol: {
701  /* todo: currently SCIP can not handle this kind of reduction (see issue #3391) */
702  assert(false);
703  if(!constraintsReplaced)
704  continue;
705  SCIP_Bool infeas;
706  SCIP_Bool fixed;
707  SCIP_Real value = SCIPinfinity(scip);
708 
709  int column = res.postsolve.indices[first];
710  bool is_negative_infinity = res.postsolve.values[first] < 0;
711  SCIP_VAR* column_variable = SCIPmatrixGetVar(matrix, column);
712 
713  if( is_negative_infinity )
714  {
715  value = -SCIPinfinity(scip);
716  }
717 
718  SCIP_CALL( SCIPfixVar(scip, column_variable, value, &infeas, &fixed) );
719  *nfixedvars += 1;
720 
721  assert(!infeas);
722  assert(fixed);
723  break;
724  }
725 #endif
726 #if (PAPILO_VERSION_MAJOR >= 2)
727  case ReductionType::kVarBoundChange :
728  case ReductionType::kRedundantRow :
729  case ReductionType::kRowBoundChange :
730  case ReductionType::kReasonForRowBoundChangeForcedByRow :
731  case ReductionType::kRowBoundChangeForcedByRow :
732  case ReductionType::kSaveRow :
733  case ReductionType::kReducedBoundsCost :
734  case ReductionType::kColumnDualValue :
735  case ReductionType::kRowDualValue :
736  case ReductionType::kCoefficientChange :
737  // dual ReductionTypes should be only calculated for dual reductions and should not appear for MIP
738  SCIPerrorMessage("PaPILO: PaPILO should not return dual postsolving reductions in SCIP!!\n");
739  SCIPABORT(); /*lint --e{527}*/
740  break;
741 #endif
742  default:
743  SCIPdebugMsg(scip, "PaPILO returned unknown data type: \n" );
744  continue;
745  }
746  }
747 
748  /* tighten bounds of variables that are still present after presolving */
749  if( *result != SCIP_CUTOFF )
750  {
751  VariableDomains<SCIP_Real>& varDomains = problem.getVariableDomains();
752  for( int i = 0; i != problem.getNCols(); ++i )
753  {
754  assert( ! varDomains.flags[i].test(ColFlag::kInactive) );
755  SCIP_VAR* var = SCIPmatrixGetVar(matrix, res.postsolve.origcol_mapping[i]);
756  if( !varDomains.flags[i].test(ColFlag::kLbInf) )
757  {
758  SCIP_Bool infeas;
759  SCIP_Bool tightened;
760  SCIP_CALL( SCIPtightenVarLb(scip, var, varDomains.lower_bounds[i], TRUE, &infeas, &tightened) );
761 
762  if( tightened )
763  *nchgbds += 1;
764 
765  if( infeas )
766  {
767  *result = SCIP_CUTOFF;
768  break;
769  }
770  }
771 
772  if( !varDomains.flags[i].test(ColFlag::kUbInf) )
773  {
774  SCIP_Bool infeas;
775  SCIP_Bool tightened;
776  SCIP_CALL( SCIPtightenVarUb(scip, var, varDomains.upper_bounds[i], TRUE, &infeas, &tightened) );
777 
778  if( tightened )
779  *nchgbds += 1;
780 
781  if( infeas )
782  {
783  *result = SCIP_CUTOFF;
784  break;
785  }
786  }
787  }
788  }
789 
790  /* finish with a final verb message and return */
792  " (%.1fs) MILP presolver (%d rounds): %d aggregations, %d fixings, %d bound changes\n",
793  SCIPgetSolvingTime(scip), presolve.getStatistics().nrounds, *naggrvars - oldnaggrvars,
794  *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
795 
796  /* free the matrix */
797  assert(initialized);
798  SCIPmatrixFree(scip, &matrix);
799 
800  return SCIP_OKAY;
801 }
802 
803 
804 /*
805  * presolver specific interface methods
806  */
807 
808 /** creates the xyz presolver and includes it in SCIP */
810  SCIP* scip /**< SCIP data structure */
811  )
812 {
813  SCIP_PRESOLDATA* presoldata;
814  SCIP_PRESOL* presol;
815 
816 #if defined(PAPILO_VERSION_TWEAK) && PAPILO_VERSION_TWEAK != 0
817  String name = fmt::format("PaPILO {}.{}.{}.{}", PAPILO_VERSION_MAJOR, PAPILO_VERSION_MINOR, PAPILO_VERSION_PATCH, PAPILO_VERSION_TWEAK);
818 #else
819  String name = fmt::format("PaPILO {}.{}.{}", PAPILO_VERSION_MAJOR, PAPILO_VERSION_MINOR, PAPILO_VERSION_PATCH);
820 #endif
821 
822 #ifdef PAPILO_GITHASH_AVAILABLE
823  String desc = fmt::format("parallel presolve for integer and linear optimization (github.com/scipopt/papilo) [GitHash: {}]", PAPILO_GITHASH);
824 #else
825  String desc("parallel presolve for integer and linear optimization (github.com/scipopt/papilo)");
826 #endif
827 
828  /* add external code info for the presolve library */
829  SCIP_CALL( SCIPincludeExternalCodeInformation(scip, name.c_str(), desc.c_str()) );
830 
831  /* create MILP presolver data */
832  presoldata = NULL;
833  SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
834  BMSclearMemory(presoldata);
835 
836  presol = NULL;
837 
838  /* include presolver */
840  presolExecMILP,
841  presoldata) );
842 
843  assert(presol != NULL);
844 
845  /* set non fundamental callbacks via setter functions */
846  SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyMILP) );
847  SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeMILP) );
848  SCIP_CALL( SCIPsetPresolInit(scip, presol, presolInitMILP) );
849 
850  /* add MILP presolver parameters */
852  "presolving/" PRESOL_NAME "/threads",
853  "maximum number of threads presolving may use (0: automatic)",
854  &presoldata->threads, FALSE, DEFAULT_THREADS, 0, INT_MAX, NULL, NULL) );
855 
857  "presolving/" PRESOL_NAME "/maxfillinpersubstitution",
858  "maximal possible fillin for substitutions to be considered",
859  &presoldata->maxfillinpersubstitution, FALSE, DEFAULT_MAXFILLINPERSUBST, INT_MIN, INT_MAX, NULL, NULL) );
860 
862  "presolving/" PRESOL_NAME "/maxshiftperrow",
863  "maximal amount of nonzeros allowed to be shifted to make space for substitutions",
864  &presoldata->maxshiftperrow, TRUE, DEFAULT_MAXSHIFTPERROW, 0, INT_MAX, NULL, NULL) );
865 
867  "presolving/" PRESOL_NAME "/randomseed",
868  "the random seed used for randomization of tie breaking",
869  &presoldata->randomseed, FALSE, DEFAULT_RANDOMSEED, INT_MIN, INT_MAX, NULL, NULL) );
870 
871  if( DependentRows<double>::Enabled )
872  {
874  "presolving/" PRESOL_NAME "/detectlineardependency",
875  "should linear dependent equations and free columns be removed? (0: never, 1: for LPs, 2: always)",
876  &presoldata->detectlineardependency, TRUE, DEFAULT_DETECTLINDEP, 0, 2, NULL, NULL) );
877  }
878  else
879  presoldata->detectlineardependency = 0;
880 
882  "presolving/" PRESOL_NAME "/modifyconsfac",
883  "modify SCIP constraints when the number of nonzeros or rows is at most this factor "
884  "times the number of nonzeros or rows before presolving",
885  &presoldata->modifyconsfac, FALSE, DEFAULT_MODIFYCONSFAC, 0.0, 1.0, NULL, NULL) );
886 
888  "presolving/" PRESOL_NAME "/markowitztolerance",
889  "the markowitz tolerance used for substitutions",
890  &presoldata->markowitztolerance, FALSE, DEFAULT_MARKOWITZTOLERANCE, 0.0, 1.0, NULL, NULL) );
891 
893  "presolving/" PRESOL_NAME "/hugebound",
894  "absolute bound value that is considered too huge for activitity based calculations",
895  &presoldata->hugebound, FALSE, DEFAULT_HUGEBOUND, 0.0, SCIP_REAL_MAX, NULL, NULL) );
896 
897 #if PAPILO_VERSION_MAJOR > 2 || (PAPILO_VERSION_MAJOR == 2 && PAPILO_VERSION_MINOR >= 1)
898  SCIP_CALL(SCIPaddIntParam(scip, "presolving/" PRESOL_NAME "/maxbadgesizeseq",
899  "maximal badge size in Probing in PaPILO if PaPILO is executed in sequential mode",
900  &presoldata->maxbadgesizeseq, FALSE, DEFAULT_MAXBADGESIZE_SEQ, -1, INT_MAX, NULL, NULL));
901 
902  SCIP_CALL(SCIPaddIntParam(scip, "presolving/" PRESOL_NAME "/maxbadgesizepar",
903  "maximal badge size in Probing in PaPILO if PaPILO is executed in parallel mode",
904  &presoldata->maxbadgesizepar, FALSE, DEFAULT_MAXBADGESIZE_PAR, -1, INT_MAX, NULL, NULL));
905 #else
906  presoldata->maxbadgesizeseq = DEFAULT_MAXBADGESIZE_SEQ;
907  presoldata->maxbadgesizepar = DEFAULT_MAXBADGESIZE_PAR;
908 #endif
909 
911  "presolving/" PRESOL_NAME "/enableparallelrows",
912  "should the parallel rows presolver be enabled within the presolve library?",
913  &presoldata->enableparallelrows, TRUE, DEFAULT_ENABLEPARALLELROWS, NULL, NULL) );
914 
916  "presolving/" PRESOL_NAME "/enabledomcol",
917  "should the dominated column presolver be enabled within the presolve library?",
918  &presoldata->enabledomcol, TRUE, DEFAULT_ENABLEDOMCOL, NULL, NULL) );
919 
921  "presolving/" PRESOL_NAME "/enabledualinfer",
922  "should the dualinfer presolver be enabled within the presolve library?",
923  &presoldata->enabledualinfer, TRUE, DEFAULT_ENABLEDUALINFER, NULL, NULL) );
924 
926  "presolving/" PRESOL_NAME "/enablemultiaggr",
927  "should the multi-aggregation presolver be enabled within the presolve library?",
928  &presoldata->enablemultiaggr, TRUE, DEFAULT_ENABLEMULTIAGGR, NULL, NULL) );
929 
931  "presolving/" PRESOL_NAME "/enableprobing",
932  "should the probing presolver be enabled within the presolve library?",
933  &presoldata->enableprobing, TRUE, DEFAULT_ENABLEPROBING, NULL, NULL) );
934 
936  "presolving/" PRESOL_NAME "/enablesparsify",
937  "should the sparsify presolver be enabled within the presolve library?",
938  &presoldata->enablesparsify, TRUE, DEFAULT_ENABLESPARSIFY, NULL, NULL) );
939 
940  SCIP_CALL( SCIPaddStringParam(scip, "presolving/" PRESOL_NAME "/probfilename",
941  "filename to store the problem before MILP presolving starts",
942  &presoldata->filename, TRUE, DEFAULT_FILENAME_PROBLEM, NULL, NULL) );
943 
944  return SCIP_OKAY;
945 }
946 
947 #endif
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_presol.c:96
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:369
struct SCIP_PresolData SCIP_PRESOLDATA
Definition: type_presol.h:42
#define PRESOL_NAME
MILP presolver that calls the presolve library on the constraint matrix.
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1620
#define PRESOL_MAXROUNDS
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5200
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition: matrix.c:1692
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
Definition: scip_presol.c:147
public methods for SCIP parameter handling
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
public methods for memory management
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:877
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17910
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:298
SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1820
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2842
public methods for timing
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition: matrix.c:1032
#define FALSE
Definition: def.h:87
#define SCIP_DECL_PRESOLCOPY(x)
Definition: type_presol.h:51
public methods for presolving plugins
#define DEFAULT_RANDOMSEED
Definition: reader_scflp.c:107
#define PRESOL_PRIORITY
SCIP_Real SCIPinfinity(SCIP *scip)
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition: presol.c:503
public methods for problem variables
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5317
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:99
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:185
public methods for SCIP variables
#define SCIPdebugMsg
Definition: scip_message.h:69
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:74
SCIP_Real SCIPepsilon(SCIP *scip)
public methods for numerical tolerances
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1668
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1066
#define PRESOL_TIMING
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17920
SCIP_RETCODE SCIPincludePresolMILP(SCIP *scip)
Definition: presol_milp.cpp:37
#define SCIP_DECL_PRESOLEXEC(x)
Definition: type_presol.h:158
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1702
SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip_var.c:8532
public methods for managing constraints
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2769
#define SCIP_DECL_PRESOLFREE(x)
Definition: type_presol.h:59
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition: presol.c:513
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1791
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8085
SCIP_RETCODE SCIPsetPresolInit(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLINIT((*presolinit)))
Definition: scip_presol.c:163
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1656
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17251
static SCIP_RETCODE presolve(SCIP *scip, SCIP_Bool *unbounded, SCIP_Bool *infeasible, SCIP_Bool *vanished)
Definition: scip_solve.c:1242
#define NULL
Definition: lpi_spx1.cpp:155
#define SCIP_CALL(x)
Definition: def.h:384
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
Definition: matrix.c:445
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1644
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:216
SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1075
public methods for constraint handler plugins and constraints
#define PRESOL_DESC
#define SCIP_Bool
Definition: def.h:84
SCIP_RETCODE SCIPwriteTransProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition: scip_prob.c:647
union SCIP_Var::@21 data
#define SCIP_DECL_PRESOLINIT(x)
Definition: type_presol.h:67
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17758
SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
Definition: scip_var.c:8653
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8273
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
#define BMSclearMemory(ptr)
Definition: memory.h:122
public methods for matrix
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1991
#define SCIP_REAL_MAX
Definition: def.h:178
public methods for presolvers
general public methods
SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1714
public methods for random numbers
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3041
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
Definition: scip_presol.c:131
public methods for message output
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17370
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip_var.c:8398
#define SCIP_Real
Definition: def.h:177
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4610
public methods for message handling
int SCIPmatrixGetNNonzs(SCIP_MATRIX *matrix)
Definition: matrix.c:1738
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17416
SCIP_RETCODE SCIPincludeExternalCodeInformation(SCIP *scip, const char *name, const char *description)
Definition: scip_general.c:704
unsigned int SCIPinitializeRandomSeed(SCIP *scip, unsigned int initialseedvalue)
SCIPallocBlockMemory(scip, subsol))
#define SCIPABORT()
Definition: def.h:356
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17442
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8626
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:130
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition: matrix.c:1564
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:48