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