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