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