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