Scippy

SCIP

Solving Constraint Integer Programs

miniisc.c
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-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file miniisc.c
17  * @brief find a minimum IIS cover
18  * @author Marc Pfetsch
19  */
20 
21 #include <string.h>
22 #include <scip/scipdefplugins.h>
23 #include <lpi/lpi.h>
24 
25 #include "benders.h"
26 #include "readargs.h"
27 
28 /* default parameters */
29 #define DEFAULT_SOLVEMASTERAPPROX FALSE /**< Solve master problem approximately? */
30 #define DEFAULT_MASTERGAPLIMIT 0.1 /**< gap bound for approximately solving the master problem */
31 #define DEFAULT_REOPTIMIZATION FALSE /**< Use reoptimization to solve master problem? */
32 #define DEFAULT_MASTERSTALLNODES 5000L /**< stall nodes for the master problem */
33 
34 /** data needed for cut generation */
35 struct BENDERS_Data
36 {
37  SCIP_LPI* lp; /**< alternative polyhedron */
38  int m; /**< number of constraints considered */
39 };
40 
41 
42 /* Macro for setting parameters in LPI */
43 #define SCIP_CALL_PARAM(x) /*lint -e527 */ do \
44 { \
45  SCIP_RETCODE _restat_; \
46  if ( (_restat_ = (x)) != SCIP_OKAY && (_restat_ != SCIP_PARAMETERUNKNOWN) ) \
47  { \
48  SCIPerrorMessage("[%s:%d] Error <%d> in function call\n", __FILE__, __LINE__, _restat_); \
49  SCIPABORT(); \
50  return _restat_; \
51  } \
52 } \
53 while ( FALSE )
54 
55 
56 /** Fix variable @a ind to 0 */
57 static
59  SCIP_LPI* lp, /**< alternative LP */
60  int ind /**< variable that should be fixed to 0 */
61  )
62 {
63  SCIP_Real lb = 0.0;
64  SCIP_Real ub = 0.0;
65 
66  /* change bounds */
67  SCIP_CALL( SCIPlpiChgBounds(lp, 1, &ind, &lb, &ub) );
68 
69  return SCIP_OKAY;
70 }
71 
72 
73 /** fix variables in @a S to 0 */
74 static
76  SCIP* masterscip, /**< SCIP pointer */
77  int nmastervars, /**< number of variables in master */
78  SCIP_Bool* S, /**< indices to fix */
79  SCIP_LPI* lp /**< alternative LP */
80  )
81 {
82  SCIP_Real* lb = NULL;
83  SCIP_Real* ub = NULL;
84  int* indices = NULL;
85  int cnt = 0;
86  int j;
87 
88  assert( masterscip != NULL );
89  assert( S != NULL );
90  assert( lp != NULL );
91 
92  SCIP_CALL( SCIPallocBufferArray(masterscip, &lb, nmastervars) );
93  SCIP_CALL( SCIPallocBufferArray(masterscip, &ub, nmastervars) );
94  SCIP_CALL( SCIPallocBufferArray(masterscip, &indices, nmastervars) );
95 
96  /* collect bounds to be changed */
97  for (j = 0; j < nmastervars; ++j)
98  {
99  if ( S[j] )
100  {
101  indices[cnt] = j;
102  lb[cnt] = 0.0;
103  ub[cnt] = 0.0;
104  ++cnt;
105  }
106  }
107 
108  /* change bounds */
109  if ( cnt > 0 )
110  {
111  SCIP_CALL( SCIPlpiChgBounds(lp, cnt, indices, lb, ub) );
112  }
113 
114  SCIPfreeBufferArray(masterscip, &indices);
115  SCIPfreeBufferArray(masterscip, &ub);
116  SCIPfreeBufferArray(masterscip, &lb);
117 
118  return SCIP_OKAY;
119 }
120 
121 /** unfix variables in @a S */
122 static
124  SCIP* masterscip, /**< SCIP pointer */
125  int nmastervars, /**< number of variables in master */
126  SCIP_Bool* S, /**< indices to fix */
127  SCIP_LPI* lp /**< alternative LP */
128  )
129 {
130  SCIP_Real* lb = NULL;
131  SCIP_Real* ub = NULL;
132  int* indices = NULL;
133  int cnt = 0;
134  int j;
135 
136  assert( masterscip != NULL );
137  assert( S != NULL );
138  assert( lp != NULL );
139 
140  SCIP_CALL( SCIPallocBufferArray(masterscip, &lb, nmastervars) );
141  SCIP_CALL( SCIPallocBufferArray(masterscip, &ub, nmastervars) );
142  SCIP_CALL( SCIPallocBufferArray(masterscip, &indices, nmastervars) );
143 
144  /* collect bounds to be changed */
145  for (j = 0; j < nmastervars; ++j)
146  {
147  if ( S[j] )
148  {
149  indices[cnt] = j;
150  lb[cnt] = 0.0;
151  ub[cnt] = SCIPlpiInfinity(lp);
152  ++cnt;
153  }
154  }
155 
156  /* change bounds */
157  if ( cnt > 0 )
158  {
159  SCIP_CALL( SCIPlpiChgBounds(lp, cnt, indices, lb, ub) );
160  }
161 
162  SCIPfreeBufferArray(masterscip, &indices);
163  SCIPfreeBufferArray(masterscip, &ub);
164  SCIPfreeBufferArray(masterscip, &lb);
165 
166  return SCIP_OKAY;
167 }
168 
169 /** Check whether the given LP is infeasible
170  *
171  * If @a primal is false we assume that the problem is <em>dual feasible</em>, e.g., the problem
172  * was only changed by fixing bounds!
173  *
174  * This is the workhorse for all methods that have to solve the alternative LP. We try in several
175  * ways to recover from possible stability problems.
176  *
177  * @pre It is assumed that all parameters for the alternative LP are set.
178  */
179 static
181  SCIP* masterscip, /**< SCIP pointer */
182  SCIP_LPI* lp, /**< LP */
183  SCIP_Bool primal, /**< whether we are using the primal or dual simplex */
184  SCIP_Bool* infeasible, /**< output: whether the LP is infeasible */
185  SCIP_Bool* error /**< output: whether an error occured */
186  )
187 {
188  SCIP_RETCODE retcode;
189 
190  assert( masterscip != NULL );
191  assert( lp != NULL );
192  assert( infeasible != NULL );
193  assert( error != NULL );
194 
195  *error = FALSE;
196 
197  /* solve LP */
198  if ( primal )
199  retcode = SCIPlpiSolvePrimal(lp); /* use primal simplex */
200  else
201  retcode = SCIPlpiSolveDual(lp); /* use dual simplex */
202 
203  if ( retcode == SCIP_LPERROR )
204  {
205  *error = TRUE;
206  return SCIP_OKAY;
207  }
208  SCIP_CALL( retcode );
209 
210  /* resolve if LP is not stable */
211  if ( ! SCIPlpiIsStable(lp) )
212  {
215  SCIPwarningMessage(masterscip, "Numerical problems, retrying ...\n");
216 
217  /* re-solve LP */
218  if ( primal )
219  retcode = SCIPlpiSolvePrimal(lp); /* use primal simplex */
220  else
221  retcode = SCIPlpiSolveDual(lp); /* use dual simplex */
222 
223  /* reset parameters */
226 
227  if ( retcode == SCIP_LPERROR )
228  {
229  *error = TRUE;
230  return SCIP_OKAY;
231  }
232  SCIP_CALL( retcode );
233  }
234 
235  /* check whether we are in the paradoxical situation that
236  * - the primal is not infeasible
237  * - the primal is not unbounded
238  * - the LP is not optimal
239  * - we have a primal ray
240  *
241  * If we ran the dual simplex algorithm, then we run again with the primal simplex
242  */
243  if ( ! SCIPlpiIsPrimalInfeasible(lp) && ! SCIPlpiIsPrimalUnbounded(lp) && ! SCIPlpiIsOptimal(lp) && SCIPlpiExistsPrimalRay(lp) && ! primal )
244  {
245  SCIPwarningMessage(masterscip, "The dual simplex produced a primal ray. Retrying with primal ...\n");
246 
247  /* the following settings might be changed: */
251 
252  SCIP_CALL( SCIPlpiSolvePrimal(lp) ); /* use primal simplex */
253 
254  /* reset parameters */
258  }
259 
260  /* examine LP solution status */
261  if ( SCIPlpiIsPrimalInfeasible(lp) ) /* the LP is provably infeasible */
262  {
263  assert( ! SCIPlpiIsPrimalUnbounded(lp) ); /* can't be unbounded or optimal */
264  assert( ! SCIPlpiIsOptimal(lp) ); /* if it is infeasible! */
265  *infeasible = TRUE; /* LP is infeasible */
266  return SCIP_OKAY;
267  }
268  else
269  {
270  /* By assumption the dual is feasible if the dual simplex is run, therefore
271  * the status has to be primal unbounded or optimal. */
272  if ( ! SCIPlpiIsPrimalUnbounded(lp) && ! SCIPlpiIsOptimal(lp) )
273  {
274  /* We have a status different from unbounded or optimal. This should not be the case ... */
275  if (primal)
276  SCIPwarningMessage(masterscip, "Primal simplex returned with unknown status: %d\n", SCIPlpiGetInternalStatus(lp));
277  else
278  SCIPwarningMessage(masterscip, "Dual simplex returned with unknown status: %d\n", SCIPlpiGetInternalStatus(lp));
279 
280  /* SCIP_CALL( SCIPlpiWriteLP(lp, "debug.lp") ); */
281  *error = TRUE;
282  return SCIP_OKAY;
283  }
284  }
285 
286  /* at this point we have a feasible solution */
287  *infeasible = FALSE;
288  return SCIP_OKAY;
289 }
290 
291 
292 /** produce Benders cuts from the alternative polyhedron
293  *
294  * input:
295  * - masterscip: SCIP pointer of Benders master problem
296  * - nmastervars: number of variables in master problem
297  * - mastervars: variables in master problem
298  * - mastersolution: solution of Benders master problem
299  * - data: user data for oracle
300  * - timelimit: time limit for subproblem
301  * - ntotalcuts: total number of cuts
302  * output:
303  * - ncuts: number of cuts added
304  * - status: status
305  *
306  * @todo apply time limit
307  */
308 static
310 { /*lint --e{715}*/
311 #ifdef SCIP_DEBUG
312  char name[SCIP_MAXSTRLEN];
313 #endif
314  SCIP_LPI* lp;
315  SCIP_Real* primsol;
316  SCIP_Real value = 0.0;
317  SCIP_Bool* S;
318  int size = 0;
319  int step = 0;
320  int ncols;
321  int j;
322 
323  assert( masterscip != NULL );
324  assert( data != NULL );
325  assert( mastersolution != NULL );
326  assert( ncuts != NULL );
327  assert( status != NULL );
328  assert( data->lp != NULL );
329  assert( data->m == nmastervars );
330 
331  lp = data->lp;
332 
333  *ncuts = 0;
334  *status = BENDERS_STATUS_UNKNOWN;
335 
336  SCIP_CALL( SCIPlpiGetNCols(lp, &ncols) );
337  SCIP_CALL( SCIPallocBufferArray(masterscip, &primsol, ncols) );
338  assert( nmastervars <= ncols );
339 
340  /* init set S */
341  SCIP_CALL( SCIPallocClearBufferArray(masterscip, &S, nmastervars) );
342  for (j = 0; j < nmastervars; ++j)
343  {
344  assert( SCIPisFeasIntegral(masterscip, mastersolution[j]) );
345  if ( mastersolution[j] > 0.5 )
346  {
347  S[j] = TRUE;
348  ++size;
349  value += SCIPvarGetObj(mastervars[j]);
350  }
351  }
352  SCIP_CALL( fixAltLPVariables(masterscip, nmastervars, S, lp) );
353 
354  do
355  {
356  SCIP_CONS* cons;
357  SCIP_VAR** vars;
358  SCIP_Bool infeasible;
359  SCIP_Real candobj = -1.0;
360  SCIP_Bool error;
361  int sizeIIS = 0;
362  int candidate = -1;
363  int cnt = 0;
364 
365  if ( step == 0 )
366  {
367  /* the first LP is solved without warm start, after that we use a warmstart. */
369  SCIP_CALL( checkAltLPInfeasible(masterscip, lp, TRUE, &infeasible, &error) );
371  }
372  else
373  SCIP_CALL( checkAltLPInfeasible(masterscip, lp, FALSE, &infeasible, &error) );
374 
375  if ( error )
376  {
377  *status = BENDERS_STATUS_ERROR;
378  break;
379  }
380 
381  /* if the alternative polyhedron is infeasible, we found a cover */
382  if ( infeasible )
383  {
384  /* if the problem is infeasible in the first step, we are successful */
385  if ( step == 0 )
386  *status = BENDERS_STATUS_SUCESS;
387 
388  SCIPdebugMessage(" size: %4d produced possible cover with objective value %f.\n", size, value);
389  break;
390  }
391 
392  /* get solution of alternative LP */
393  SCIP_CALL( SCIPlpiGetSol(lp, NULL, primsol, NULL, NULL, NULL) );
394 
395  /* find candidate for variable to add */
396  for (j = 0; j < nmastervars; ++j)
397  {
398  /* check support of the solution, i.e., the corresponding IIS */
399  if ( ! SCIPisFeasZero(masterscip, primsol[j]) )
400  {
401  assert( ! S[j] );
402  ++sizeIIS;
403 
404  /* take first element */
405  if ( candidate < 0 )
406  {
407  candidate = j;
408  candobj = SCIPvarGetObj(mastervars[j]);
409  }
410  }
411  }
412 
413  /* check for error */
414  if ( candidate < 0 )
415  {
416  /* Because of numerical problem it might happen that the solution primsol above is zero
417  * within the tolerances. In this case we quit. */
418  break;
419  }
420  assert( candidate >= 0 );
421  assert( ! S[candidate] );
422  assert( sizeIIS > 0 );
423 
424  SCIPdebugMessage(" size: %4d add %4d with objective value %6g and alt-LP solution value %-8.4g (IIS size: %4d).\n",
425  size, candidate, candobj, primsol[candidate], sizeIIS);
426 
427  /* update new set S */
428  S[candidate] = TRUE;
429  ++size;
430  value += candobj;
431 
432  SCIP_CALL( SCIPallocBufferArray(masterscip, &vars, nmastervars) );
433 
434  /* collect variables corresponding to support to cut */
435  for (j = 0; j < nmastervars; ++j)
436  {
437  /* check support of the solution, i.e., the corresponding IIS */
438  if ( ! SCIPisFeasZero(masterscip, primsol[j]) )
439  vars[cnt++] = mastervars[j];
440  }
441  assert( cnt == sizeIIS );
442 
443 #ifdef SCIP_DEBUG
444  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "iis%d", (int) ntotalcuts + *ncuts);
445  SCIP_CALL( SCIPcreateConsLogicor(masterscip, &cons, name, cnt, vars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
446 #else
447  SCIP_CALL( SCIPcreateConsLogicor(masterscip, &cons, "", cnt, vars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
448 #endif
449 
450 #ifdef SCIP_OUTPUT
451  SCIP_CALL( SCIPprintCons(masterscip, cons, NULL) );
452  SCIPinfoMessage(masterscip, NULL, ";\n");
453 #endif
454 
455  SCIP_CALL( SCIPaddCons(masterscip, cons) );
456  SCIP_CALL( SCIPreleaseCons(masterscip, &cons) );
457 
458  SCIPfreeBufferArray(masterscip, &vars);
459 
460  ++(*ncuts);
461  *status = BENDERS_STATUS_ADDEDCUT;
462 
463  /* fix chosen variable to 0 */
464  SCIP_CALL( fixAltLPVariable(lp, candidate) );
465 
466  ++step;
467  }
468  while (step < nmastervars);
469 
470  SCIP_CALL( unfixAltLPVariables(masterscip, nmastervars, S, lp) );
471 
472  SCIPfreeBufferArray(masterscip, &S);
473  SCIPfreeBufferArray(masterscip, &primsol);
474 
475  return SCIP_OKAY;
476 }
477 
478 
479 /** creates column in alternative polyhedron */
480 static
482  SCIP* origscip, /**< SCIP pointer */
483  SCIP_LPI* lp, /**< alternative LP */
484  int nvars, /**< number of variables in column */
485  SCIP_VAR** vars, /**< variables for column */
486  SCIP_Real* vals, /**< values for column */
487  SCIP_Real rhscoef, /**< coefficient for first row */
488  SCIP_Real sign /**< sign (+1,-1) for column */
489  )
490 {
491  SCIP_Real obj = 1.0;
492  SCIP_Real lb = 0.0;
493  SCIP_Real ub;
494  SCIP_Real* matval;
495  int* matind;
496  int matbeg = 0;
497  int cnt = 0;
498  int v;
499 
500  assert( origscip != NULL );
501  assert( vars != NULL );
502  assert( vals != NULL );
503  assert( SCIPisEQ(origscip, sign, 1.0) || SCIPisEQ(origscip, sign, -1.0) );
504 
505  if ( SCIPisInfinity(origscip, rhscoef) || SCIPisInfinity(origscip, -rhscoef) )
506  return SCIP_OKAY;
507 
508  /* set up data for construction */
509  SCIP_CALL( SCIPallocBufferArray(origscip, &matind, nvars + 1) );
510  SCIP_CALL( SCIPallocBufferArray(origscip, &matval, nvars + 1) );
511 
512  /* handle first row */
513  if ( ! SCIPisFeasZero(origscip, rhscoef) )
514  {
515  matind[cnt] = 0;
516  matval[cnt++] = sign * rhscoef;
517  }
518 
519  /* set up column */
520  for (v = 0; v < nvars; ++v)
521  {
522  assert( vars[v] != NULL );
523  if ( vals != NULL )
524  matval[cnt] = vals[v] * sign;
525  else
526  matval[cnt] = sign;
527  matind[cnt++] = SCIPvarGetIndex(vars[v]) + 1;
528  }
529 
530  /* now add column */
531  ub = SCIPlpiInfinity(lp);
532 
533  SCIP_CALL( SCIPlpiAddCols(lp, 1, &obj, &lb, &ub, NULL, cnt, &matbeg, matind, matval) );
534 
535  SCIPfreeBufferArray(origscip, &matval);
536  SCIPfreeBufferArray(origscip, &matind);
537 
538  return SCIP_OKAY;
539 }
540 
541 
542 /** create alternative polyhedron */
543 static
545  SCIP* origscip, /**< original SCIP instance */
546  SCIP_LPI* lp /**< alternative polyhedron */
547  )
548 {
549  SCIP_CONS** origconss;
550  int norigconss;
551  int c;
552  int v;
553 
554  assert( origscip != NULL );
555  assert( lp != NULL );
556 
557  origconss = SCIPgetConss(origscip);
558  norigconss = SCIPgetNConss(origscip);
559 
560  for (c = 0; c < norigconss; ++c)
561  {
562  const char* origconshdlrname;
563  SCIP_CONSHDLR* origconshdlr;
564  SCIP_VAR** origconsvars;
565  SCIP_CONS* origcons;
566  int norigconsvars;
567 
568  origcons = origconss[c];
569  assert( origcons != NULL );
570 
571  origconshdlr = SCIPconsGetHdlr(origcons);
572  assert( origconshdlr != NULL );
573  origconshdlrname = SCIPconshdlrGetName(origconshdlr);
574 
575  if ( strcmp(origconshdlrname, "linear") == 0 )
576  {
577  origconsvars = SCIPgetVarsLinear(origscip, origcons);
578  norigconsvars = SCIPgetNVarsLinear(origscip, origcons);
579 
580  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, SCIPgetValsLinear(origscip, origcons), SCIPgetRhsLinear(origscip, origcons), 1.0) );
581  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, SCIPgetValsLinear(origscip, origcons), SCIPgetLhsLinear(origscip, origcons), -1.0) );
582  }
583  else if ( strcmp(origconshdlrname, "setppc") == 0 )
584  {
585  origconsvars = SCIPgetVarsSetppc(origscip, origcons);
586  norigconsvars = SCIPgetNVarsSetppc(origscip, origcons);
587 
588  switch ( SCIPgetTypeSetppc(origscip, origcons) )
589  {
591  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, NULL, 1.0, 1.0) );
592  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, NULL, 1.0, -1.0) );
593  break;
595  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, NULL, 1.0, 1.0) );
596  break;
598  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, NULL, 1.0, -1.0) );
599  break;
600  }
601  }
602  else if ( strcmp(origconshdlrname, "logicor") == 0 )
603  {
604  origconsvars = SCIPgetVarsLogicor(origscip, origcons);
605  norigconsvars = SCIPgetNVarsLogicor(origscip, origcons);
606 
607  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, NULL, 1.0, -1.0) );
608  }
609  else if ( strcmp(origconshdlrname, "knapsack") == 0 )
610  {
611  SCIP_Longint* origweights;
612  SCIP_Real* consvals;
613 
614  origconsvars = SCIPgetVarsKnapsack(origscip, origcons);
615  norigconsvars = SCIPgetNVarsKnapsack(origscip, origcons);
616 
617  /* copy Longint array to SCIP_Real array */
618  origweights = SCIPgetWeightsKnapsack(origscip, origcons);
619  SCIP_CALL( SCIPallocBufferArray(origscip, &consvals, norigconsvars) );
620 
621  for ( v = 0; v < norigconsvars; ++v )
622  consvals[v] = (SCIP_Real) origweights[v];
623 
624  SCIP_CALL( createAltLPColumn(origscip, lp, norigconsvars, origconsvars, consvals, (SCIP_Real) SCIPgetCapacityKnapsack(origscip, origcons), 1.0) );
625 
626  SCIPfreeBufferArray(origscip, &consvals);
627  }
628  else if ( strcmp(origconshdlrname, "varbound") == 0 )
629  {
630  SCIP_VAR* consvars[2];
631  SCIP_Real consvals[2];
632 
633  consvars[0] = SCIPgetVarVarbound(origscip, origcons);
634  consvars[1] = SCIPgetVbdvarVarbound(origscip, origcons);
635 
636  consvals[0] = 1.0;
637  consvals[1] = SCIPgetVbdcoefVarbound(origscip, origcons);
638 
639  SCIP_CALL( createAltLPColumn(origscip, lp, 2, consvars, consvals, SCIPgetRhsVarbound(origscip, origcons), 1.0) );
640  SCIP_CALL( createAltLPColumn(origscip, lp, 2, consvars, consvals, SCIPgetLhsVarbound(origscip, origcons), -1.0) );
641  }
642  else
643  {
644  SCIPwarningMessage(origscip, "Cannot handle constraints of type <%s>.\n", origconshdlrname);
645  }
646  }
647  return SCIP_OKAY;
648 }
649 
650 
651 /** solve minimum IIS cover problem */
652 static
654  const char* filename, /**< problem name */
655  const char* settingsname, /**< name of parameter file (or NULL) */
656  SCIP_Real timelimit, /**< time limit read from arguments */
657  SCIP_Real memlimit, /**< memory limit read from arguments */
658  int dispfreq /**< display frequency */
659  )
660 {
661  char name[SCIP_MAXSTRLEN];
662  BENDERS_DATA data;
663  SCIP* masterscip;
664  SCIP* origscip;
665  SCIP_STATUS status;
666  SCIP_LPI* lp;
667  SCIP_Real lhs = -1.0;
668  SCIP_Real rhs = -1.0;
669  SCIP_VAR** origvars;
670  SCIP_Real obj = 0.0;
671  SCIP_Real lb = 0.0;
672  SCIP_Real ub;
673  int norigvars;
674  int nrows = 0;
675  int m = 0;
676  int v;
677 
678  /* parameters */
679  SCIP_Bool solvemasterapprox;
680  SCIP_Longint masterstallnodes;
681  SCIP_Real mastergaplimit;
682  SCIP_Bool reoptimization;
683 
684  /* create master SCIP */
685  SCIP_CALL( SCIPcreate(&masterscip) );
686  SCIP_CALL( SCIPincludeDefaultPlugins(masterscip) );
687  if ( getProblemName(filename, name, SCIP_MAXSTRLEN) == 0 )
688  {
689  SCIPerrorMessage("Cannot extract problem name for filename <%s>.\n", filename);
690  return SCIP_ERROR;
691  }
692  SCIP_CALL( SCIPcreateProb(masterscip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
694 
695  SCIPinfoMessage(masterscip, NULL, "Finding a minimum IIS cover using a set covering approach.\n");
696  SCIPinfoMessage(masterscip, NULL, "Implemented by Marc Pfetsch, 2015\n\n");
697 
698  SCIPprintVersion(masterscip, NULL);
699  SCIPinfoMessage(masterscip, NULL, "\n");
700 
701  /* add parameters */
702  SCIP_CALL( SCIPaddBoolParam(masterscip,
703  "miniisc/solvemasterapprox",
704  "Solve master problem approximately?",
705  &solvemasterapprox, TRUE, DEFAULT_SOLVEMASTERAPPROX, NULL, NULL) );
706 
707  SCIP_CALL( SCIPaddRealParam(masterscip,
708  "miniisc/mastergaplimit",
709  "gap bound for approximately solving the master problem",
710  &mastergaplimit, TRUE, DEFAULT_MASTERGAPLIMIT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
711 
712  SCIP_CALL( SCIPaddLongintParam(masterscip,
713  "miniisc/masterstallnodes",
714  "stall nodes for the master problem",
715  &masterstallnodes, TRUE, DEFAULT_MASTERSTALLNODES, 0L, SCIP_LONGINT_MAX, NULL, NULL) );
716 
717  SCIP_CALL( SCIPaddBoolParam(masterscip,
718  "miniisc/reoptimization",
719  "Use reoptimization to solve master problem?",
720  &reoptimization, TRUE, DEFAULT_REOPTIMIZATION, NULL, NULL) );
721 
722  /* read parameters if required */
723  if ( settingsname != NULL )
724  {
725  if ( SCIPfileExists(settingsname) )
726  {
727  SCIPinfoMessage(masterscip, NULL, "\nreading user parameter file <%s> ...\n\n", settingsname);
728  SCIP_CALL( SCIPreadParams(masterscip, settingsname) );
729  SCIP_CALL( SCIPwriteParams(masterscip, NULL, FALSE, TRUE) );
730  }
731  else
732  {
733  SCIPwarningMessage(masterscip, NULL, "\nparameter file <%s> not found - using default parameters.\n", settingsname);
734  }
735  }
736 
737  if ( ! SCIPisInfinity(masterscip, timelimit) )
738  SCIPinfoMessage(masterscip, NULL, "limits/time = %f\n\n", timelimit);
739 
740  SCIPinfoMessage(masterscip, NULL, "Input file:\t%s\n", filename);
741  SCIPinfoMessage(masterscip, NULL, "Problem name:\t%s\n\n", name);
742 
743  /* ----------------------------------------------------------------------------------------*/
744 
745  /* read instance to create alternative polyhedron */
746  SCIP_CALL( SCIPcreate(&origscip) );
747 
748  /* include default SCIP plugins */
750 
751  /* read problem */
752  SCIP_CALL( SCIPreadProb(origscip, filename, NULL) );
753 
754  /* check that we have an LP */
755  if ( SCIPgetNOrigBinVars(origscip) + SCIPgetNOrigIntVars(origscip) > 0 )
756  {
757  SCIPinfoMessage(masterscip, NULL, "ERROR: input file contains integer variables. The code only works for LPs.\n");
758  return SCIP_ERROR;
759  }
760 
761  /* ----------------------------------------------------------------------------------------*/
762 
763  /* init alternative polyhedron */
764  SCIP_CALL( SCIPlpiCreate(&lp, SCIPgetMessagehdlr(masterscip), "altlp", SCIP_OBJSEN_MINIMIZE) );
765 
766  /* init parameters */
771 
772  /* add first row */
773  SCIP_CALL( SCIPlpiAddRows(lp, 1, &lhs, &rhs, NULL, 0, NULL, NULL, NULL) );
774 
775  norigvars = SCIPgetNOrigVars(origscip);
776  origvars = SCIPgetOrigVars(origscip);
777 
778  /* add rows for each variable */
779  lhs = 0.0;
780  rhs = 0.0;
781  for (v = 0; v < norigvars; ++v)
782  {
783  SCIP_CALL( SCIPlpiAddRows(lp, 1, &lhs, &rhs, NULL, 0, NULL, NULL, NULL) );
784  }
785  SCIP_CALL( SCIPlpiGetNRows(lp, &nrows) );
786 
787  /* create alternative polyhedron */
788  SCIP_CALL( createAltLP(origscip, lp) );
789 
790  /* get number of constraints */
791  SCIP_CALL( SCIPlpiGetNCols(lp, &m) );
792 
793  /* add columns for bounds */
794  ub = SCIPlpiInfinity(lp);
795  for (v = 0; v < norigvars; ++v)
796  {
797  SCIP_Real val;
798  SCIP_VAR* var;
799  SCIP_Real matval[2];
800  int matind[2];
801  int matbeg = 0;
802  int cnt = 0;
803 
804  var = origvars[v];
805  assert( var != NULL );
806  assert( 0 <= SCIPvarGetIndex(var) && SCIPvarGetIndex(var) < nrows );
807 
808  /* if the lower bound is finite */
809  val = SCIPvarGetLbGlobal(var);
810  if ( ! SCIPisInfinity(origscip, -val) )
811  {
812  if ( ! SCIPisZero(origscip, val) )
813  {
814  matind[cnt] = 0;
815  matval[cnt++] = -val;
816  }
817  matind[cnt] = SCIPvarGetIndex(var) + 1;
818  matval[cnt++] = -1.0;
819  SCIP_CALL( SCIPlpiAddCols(lp, 1, &obj, &lb, &ub, NULL, cnt, &matbeg, matind, matval) );
820  }
821 
822  /* if the upper bound is finite */
823  cnt = 0;
824  val = SCIPvarGetUbGlobal(var);
825  if ( ! SCIPisInfinity(origscip, val) )
826  {
827  if ( ! SCIPisZero(origscip, val) )
828  {
829  matind[cnt] = 0;
830  matval[cnt++] = val;
831  }
832  matind[cnt] = SCIPvarGetIndex(var) + 1;
833  matval[cnt++] = 1.0;
834  SCIP_CALL( SCIPlpiAddCols(lp, 1, &obj, &lb, &ub, NULL, cnt, &matbeg, matind, matval) );
835  }
836  }
837 
838  /* free SCIP instance */
839  SCIP_CALL( SCIPfree(&origscip) );
840 
841 #ifdef SCIP_OUTPUT
842  SCIP_CALL( SCIPlpiWriteLP(lp, "alt.lp") );
843 #endif
844 
845  /* ----------------------------------------------------------------------------------------*/
846  /* initialize master problem */
847  for (v = 0; v < m; ++v)
848  {
849  SCIP_VAR* var;
850 
851  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "y%d", v);
852  SCIP_CALL( SCIPcreateVar(masterscip, &var, name, 0.0, 1.0, 1.0, SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
853  SCIP_CALL( SCIPaddVar(masterscip, var) );
854  SCIP_CALL( SCIPreleaseVar(masterscip, &var) );
855  }
856 
857  /* run Benders algorithm */
858  data.lp = lp;
859  data.m = m;
860  SCIP_CALL( runBenders(masterscip, cutoracle, &data, timelimit, memlimit, dispfreq, reoptimization, solvemasterapprox,
861  masterstallnodes, mastergaplimit, SCIP_VERBLEVEL_NORMAL, &status) );
862 
863  SCIP_CALL( SCIPlpiFree(&lp) );
864 
865  SCIP_CALL( SCIPfree(&masterscip) );
866 
867  return SCIP_OKAY;
868 }
869 
870 
871 
872 
873 /** main function */
874 int
876  int argc, /**< number of shell parameters */
877  char** argv /**< array with shell parameters */
878  )
879 {
880  SCIP_RETCODE retcode;
881  const char* filename;
882  const char* settingsname;
883  SCIP_Real timelimit;
884  SCIP_Real memlimit;
885  SCIP_Longint nodelimit;
886  int dispfreq;
887 
888  retcode = readArguments(argc, argv, &filename, &settingsname, &timelimit, &memlimit, &nodelimit, &dispfreq);
889  if ( retcode != SCIP_OKAY )
890  return -1;
891  assert( filename != NULL );
892 
893  /* read file */
894  if ( ! SCIPfileExists(filename) )
895  {
896  SCIPerrorMessage("file <%s> does not exist.\n", filename);
897  return -1;
898  }
899 
900  retcode = solveMinIISC(filename, settingsname, timelimit, memlimit, dispfreq);
901  if ( retcode != SCIP_OKAY )
902  {
903  SCIPprintError(retcode);
904  return -1;
905  }
906 
908 
909  return 0;
910 }
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
#define NULL
Definition: def.h:246
#define BMScheckEmptyMemory()
Definition: memory.h:144
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
int main(int argc, char **argv)
Definition: miniisc.c:875
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9252
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip_mem.h:132
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17344
static SCIP_RETCODE unfixAltLPVariables(SCIP *masterscip, int nmastervars, SCIP_Bool *S, SCIP_LPI *lp)
Definition: miniisc.c:123
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
#define SCIP_MAXSTRLEN
Definition: def.h:267
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip_prob.c:162
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2484
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1251
interface methods for specific LP solvers
#define FALSE
Definition: def.h:72
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:183
SCIP_RETCODE runBenders(SCIP *masterscip, BENDERS_CUTORACLE((*Oracle)), BENDERS_DATA *data, SCIP_Real timelimit, SCIP_Real memlimit, int dispfreq, SCIP_Bool usereopt, SCIP_Bool solvemasterapprox, SCIP_Longint masterstallnodes, SCIP_Real mastergaplimit, SCIP_VERBLEVEL verblevel, SCIP_STATUS *status)
Definition: benders.c:198
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10253
#define TRUE
Definition: def.h:71
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip_prob.c:2457
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:171
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3140
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIP_LONGINT_MAX
Definition: def.h:143
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:142
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:338
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:203
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:279
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
static BENDERS_CUTORACLE(cutoracle)
Definition: miniisc.c:309
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:10456
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17354
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1298
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4191
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2822
SCIP_RETCODE SCIPreadProb(SCIP *scip, const char *filename, const char *extension)
Definition: scip_prob.c:382
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE createAltLPColumn(SCIP *origscip, SCIP_LPI *lp, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real rhscoef, SCIP_Real sign)
Definition: miniisc.c:481
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE checkAltLPInfeasible(SCIP *masterscip, SCIP_LPI *lp, SCIP_Bool primal, SCIP_Bool *infeasible, SCIP_Bool *error)
Definition: miniisc.c:180
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
SCIPInterval sign(const SCIPInterval &x)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL(x)
Definition: def.h:358
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE fixAltLPVariables(SCIP *masterscip, int nmastervars, SCIP_Bool *S, SCIP_LPI *lp)
Definition: miniisc.c:75
SCIP_LPI * lp
Definition: classify.c:40
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
#define SCIP_Bool
Definition: def.h:69
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
void SCIPprintVersion(SCIP *scip, FILE *file)
Definition: scip_general.c:201
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:58
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9294
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2550
#define DEFAULT_REOPTIMIZATION
Definition: miniisc.c:31
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8096
#define DEFAULT_MASTERSTALLNODES
Definition: miniisc.c:32
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17192
static SCIP_RETCODE fixAltLPVariable(SCIP_LPI *lp, int ind)
Definition: miniisc.c:58
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:104
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9273
#define SCIP_REAL_MAX
Definition: def.h:158
SCIP_RETCODE readArguments(int argc, char **argv, const char **filename, const char **settingsname, SCIP_Real *timelimit, SCIP_Real *memlimit, SCIP_Longint *nodelimit, int *dispfreq)
Definition: readargs.c:86
int SCIPgetNOrigIntVars(SCIP *scip)
Definition: scip_prob.c:2538
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1724
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_MASTERGAPLIMIT
Definition: miniisc.c:30
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3094
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1187
SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
Definition: scip_param.c:842
static SCIP_RETCODE solveMinIISC(const char *filename, const char *settingsname, SCIP_Real timelimit, SCIP_Real memlimit, int dispfreq)
Definition: miniisc.c:653
struct SCIP_LPi SCIP_LPI
Definition: type_lpi.h:96
#define SCIP_Real
Definition: def.h:157
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
#define SCIP_CALL_PARAM(x)
Definition: miniisc.c:43
#define SCIP_Longint
Definition: def.h:142
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17027
run Benders algorithm
read comand line arguments
int getProblemName(const char *filename, char *probname, int maxsize)
Definition: readargs.c:28
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPwriteParams(SCIP *scip, const char *filename, SCIP_Bool comments, SCIP_Bool onlychanged)
Definition: scip_param.c:883
int SCIPgetNOrigBinVars(SCIP *scip)
Definition: scip_prob.c:2511
void SCIPprintError(SCIP_RETCODE retcode)
Definition: scip_general.c:266
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_SOLVEMASTERAPPROX
Definition: miniisc.c:29
static SCIP_RETCODE createAltLP(SCIP *origscip, SCIP_LPI *lp)
Definition: miniisc.c:544
default SCIP plugins
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
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:211
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:129
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:370