Scippy

SCIP

Solving Constraint Integer Programs

heur_prune.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 heur_prune.c
17  * @brief reduction-based primal heuristic for Steiner problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements a reduction based heuristic for Steiner problems. See
21  * "SCIP-Jack - A solver for STP and variants with parallelization extensions" (2016) by
22  * Gamrath, Koch, Maher, Rehfeldt and Shinano
23  *
24  * A list of all interface methods can be found in heur_prune.h
25  *
26  */
27 
28 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 //#define SCIP_DEBUG
30 #include <assert.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include "scip/scip.h"
34 #include "scip/scipdefplugins.h"
35 #include "scip/cons_linear.h"
36 #include "heur_prune.h"
37 #include "heur_local.h"
38 #include "grph.h"
39 #include "heur_tm.h"
40 #include "cons_stp.h"
41 #include "scip/pub_misc.h"
42 #include "probdata_stp.h"
43 
44 #define HEUR_NAME "prune"
45 #define HEUR_DESC "Reduction based heuristic for Steiner problems"
46 #define HEUR_DISPCHAR 'P'
47 #define HEUR_PRIORITY 2
48 #define HEUR_FREQ -1
49 #define HEUR_FREQOFS 0
50 #define HEUR_MAXDEPTH -1
51 #define HEUR_TIMING (SCIP_HEURTIMING_DURINGLPLOOP | SCIP_HEURTIMING_AFTERLPLOOP | SCIP_HEURTIMING_AFTERNODE)
52 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
53 
54 #define DEFAULT_PRUNE_MAXFRQ FALSE /**< executions of the heuristic at maximum frequency? */
55 #define DEFAULT_PRUNE_TMRUNS 100 /**< number of runs in TM heuristic when called by prune heuristic */
56 #define PRUNE_MINREDELIMS 2 /**< maximum number of eliminations for reduction package when called by prune heuristic */
57 #define PRUNE_MAXREDROUNDS 6 /**< maximum number of reduction rounds in prune heuristic */
58 #define BREAKONERROR FALSE
59 #define MAXNTERMINALS 500
60 #define MAXNEDGES 10000
61 
62 #ifdef WITH_UG
63 extern
64 int getUgRank(void);
65 #endif
66 
67 /*
68  * Data structures
69  */
70 
71 /** primal heuristic data */
72 struct SCIP_HeurData
73 {
74  int bestsolindex; /**< best solution during the previous run */
75  int ntmruns; /**< number of runs in TM heuristic */
76  int nfailures; /**< number of failures since last successful call */
77  SCIP_Bool maxfreq; /**< should the heuristic be called at maximum frequency? */
78 };
79 
80 /*
81  * Local methods
82  */
83 
84 
85 
86 /* set node solution array and get solution value */
87 static
89  const GRAPH* g,
90  SCIP_Real* uborg,
91  int* solnode,
92  const int* soledge
93  )
94 {
95  SCIP_Real ub;
96  int e;
97  int k;
98  int nedges;
99  int nnodes;
100 
101  assert(g != NULL);
102  assert(solnode != NULL);
103  assert(soledge != NULL);
104 
105  ub = 0.0;
106  nedges = g->edges;
107  nnodes = g->knots;
108 
109  for( k = 0; k < nnodes; k++ )
110  solnode[k] = UNKNOWN;
111 
112  for( e = 0; e < nedges; e++ )
113  {
114  if( soledge[e] == CONNECT )
115  {
116  ub += g->cost[e];
117  solnode[g->tail[e]] = CONNECT;
118  solnode[g->head[e]] = CONNECT;
119  }
120  }
121 
122  if( uborg != NULL)
123  *uborg = ub;
124 }
125 
126 /** computes new solution during execution of prune and updates best global one if possible */
127 static
129  SCIP* scip, /**< SCIP data structure */
130  GRAPH* g, /**< graph data structure */
131  GRAPH* prunegraph, /**< pruned graph data structure */
132  PATH* path, /**< shortest path struct */
133  int* nodearrint, /**< array */
134  int* edgearrint, /**< array */
135  int* solnode, /**< array for best solution nodes wrt prunegraph */
136  int* soledge, /**< array for best solution edges wrt prunegraph */
137  int* globalsoledge, /**< array storing best solution wrt g */
138  STP_Bool* nodearrchar, /**< array */
139  SCIP_Real* globalobj, /**< pointer to objective value of best solution wrt g */
140  SCIP_Bool incumbentgiven, /**< incumbent solution for pruned graph given? */
141  SCIP_Bool* success /**< pointer to store whether a solution could be found */
142 )
143 {
144  int* const pmark = prunegraph->mark;
145  SCIP_Real dummyhop = 0.0;
146  int nruns;
147  int best_start;
148  const int nnodes = g->knots;
149 
150  assert(graph_valid(prunegraph));
151  assert(g->edges == prunegraph->edges);
152 
153  /*
154  * compute new solution on pruned graph
155  */
156 
157  nruns = 0;
158  for( int k = 0; k < nnodes; k++ )
159  {
160  pmark[k] = (prunegraph->grad[k] > 0);
161  if( pmark[k] )
162  nruns++;
163  }
164 
165  nruns = MIN(nruns, DEFAULT_PRUNE_TMRUNS);
166  SCIPStpHeurTMCompStarts(prunegraph, nodearrint, &nruns);
167 
168  /* run shortest path heuristic */
169  SCIP_CALL( SCIPStpHeurTMRun(scip, NULL, prunegraph, nodearrint, &best_start, soledge, nruns,
170  prunegraph->source, prunegraph->cost, prunegraph->cost, &dummyhop, NULL, 0.0, success, FALSE));
171 
172  SCIP_CALL( SCIPStpHeurLocalRun(scip, prunegraph, prunegraph->cost, soledge) );
173 
174  SCIP_CALL( SCIPStpHeurPruneUpdateSols(scip, g, prunegraph, path, nodearrint, edgearrint, solnode, soledge,
175  globalsoledge, nodearrchar, globalobj, incumbentgiven, success) );
176 
177  return SCIP_OKAY;
178 }
179 
180 /* get reduction bound */
181 static
183  int nround,
184  int nedges
185  )
186 {
187  if( nround == 0 )
188  return(MAX(nedges / 1000, PRUNE_MINREDELIMS));
189  if( nround == 1 )
190  return(MAX(nedges / 500, PRUNE_MINREDELIMS));
191  return(MAX(nedges / 200, PRUNE_MINREDELIMS));
192 }
193 
194 
195 static
197  SCIP* scip,
198  int* minnelims,
199  int* lminnelims,
200  int annodes,
201  int anedges,
202  int anterms,
203  int nround,
204  int maxrounds
205  )
206 {
207  int min;
208  int totminnelims;
209  SCIP_Real factor;
210 
211  assert(scip != NULL);
212  assert(minnelims != NULL);
213  assert(lminnelims != NULL);
214  assert(annodes > 0);
215  assert(nround >= 0);
216  assert(maxrounds >= 1);
217 
218  anedges = anedges / 2;
219 
220  totminnelims = MAX(PRUNE_MINREDELIMS, (anedges / 20));
221 
222  min = (anedges / 10);
223 
224  min -= (int) ( ((SCIP_Real) min * anterms) / ( (SCIP_Real) annodes) );
225  min = MAX(min, 1);
226 
227  factor = (SCIP_Real) anedges / min;
228  factor = ((SCIP_Real) nround / (3.0 * maxrounds)) * factor;
229 
230  if( SCIPisGT(scip, factor, 1.0) )
231  min = (int) ((SCIP_Real) min * factor);
232 
233  min = MAX(totminnelims, min);
234  min = MIN(min, (anedges - 1));
235  min = MAX(min, 1);
236 
237  *lminnelims = min / 2;
238  *lminnelims = MAX(*lminnelims, 1);
239 
240  *minnelims = min;
241 }
242 
243 /*
244  * Callback methods of primal heuristic
245  */
246 
247 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
248 static
249 SCIP_DECL_HEURCOPY(heurCopyPrune)
250 { /*lint --e{715}*/
251  assert(scip != NULL);
252  assert(heur != NULL);
253  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
254 
255  /* call inclusion method of primal heuristic */
257 
258  return SCIP_OKAY;
259 }
260 
261 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
262 static
263 SCIP_DECL_HEURFREE(heurFreePrune)
264 { /*lint --e{715}*/
265  SCIP_HEURDATA* heurdata;
266 
267  assert(heur != NULL);
268  assert(scip != NULL);
269 
270  /* get heuristic data */
271  heurdata = SCIPheurGetData(heur);
272  assert(heurdata != NULL);
273 
274  /* free heuristic data */
275  SCIPfreeMemory(scip, &heurdata);
276  SCIPheurSetData(heur, NULL);
277 
278  return SCIP_OKAY;
279 }
280 
281 
282 /** initialization method of primal heuristic (called after problem was transformed) */
283 static
284 SCIP_DECL_HEURINIT(heurInitPrune)
285 { /*lint --e{715}*/
286 
287 
288  return SCIP_OKAY;
289 }
290 
291 
292 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
293 static
294 SCIP_DECL_HEURINITSOL(heurInitsolPrune)
295 { /*lint --e{715}*/
296  SCIP_HEURDATA* heurdata;
297 
298  assert(heur != NULL);
299  assert(scip != NULL);
300 
301  /* get heuristic's data */
302  heurdata = SCIPheurGetData(heur);
303 
304  assert(heurdata != NULL);
305 
306  /* initialize data */
307  heurdata->ntmruns = DEFAULT_PRUNE_TMRUNS;
308  heurdata->nfailures = 0;
309  heurdata->bestsolindex = -1;
310 
311  return SCIP_OKAY;
312 }
313 
314 
315 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
316 static
317 SCIP_DECL_HEUREXITSOL(heurExitsolPrune)
318 { /*lint --e{715}*/
319 
320  return SCIP_OKAY;
321 }
322 
323 
324 /** execution method of primal heuristic */
325 static
326 SCIP_DECL_HEUREXEC(heurExecPrune)
327 { /*lint --e{715}*/
328  SCIP_HEURDATA* heurdata;
329  SCIP_PROBDATA* probdata;
330  SCIP_VAR** vars;
331  SCIP_SOL* bestsol; /* best known solution */
332  GRAPH* graph;
333  SCIP_Real* xval;
334  SCIP_Bool success;
335  int e;
336  int nvars;
337  int nedges;
338  int* soledge;
339 
340  assert(heur != NULL);
341  assert(scip != NULL);
342  assert(result != NULL);
343  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
344 
345  /* get heuristic data */
346  heurdata = SCIPheurGetData(heur);
347  assert(heurdata != NULL);
348 
349  /* get problem data */
350  probdata = SCIPgetProbData(scip);
351  assert(probdata != NULL);
352 
353  /* get graph */
354  graph = SCIPprobdataGetGraph(probdata);
355  assert(graph != NULL);
356 
357  nedges = graph->edges;
358  *result = SCIP_DIDNOTRUN;
359 
360  /* if not STP like variant, return */
361  if( graph->stp_type != STP_SPG && graph->stp_type != STP_RSMT && graph->stp_type != STP_OARSMT &&
362  graph->stp_type != STP_GSTP )
363  return SCIP_OKAY;
364 
365  if( (graph->edges > MAXNEDGES) && (graph->terms > MAXNTERMINALS) )
366  return SCIP_OKAY;
367 
368  /* get best current solution */
369  bestsol = SCIPgetBestSol(scip);
370 
371  /* no solution available? */
372  if( bestsol == NULL )
373  return SCIP_OKAY;
374 
375  /* has the new solution been found by this very heuristic? */
376  if( SCIPsolGetHeur(bestsol) == heur || heurdata->bestsolindex == SCIPsolGetIndex(SCIPgetBestSol(scip)) )
377  return SCIP_OKAY;
378 
379  xval = SCIPprobdataGetXval(scip, bestsol);
380 
381  if( xval == NULL )
382  return SCIP_OKAY;
383 
384  vars = SCIPprobdataGetVars(scip);
385  nvars = SCIPprobdataGetNVars(scip);
386 
387  SCIPdebugMessage("START prune heuristic \n");
388 
389  assert(vars != NULL);
390 
391  /* allocate array to store primal solution */
392  SCIP_CALL( SCIPallocBufferArray(scip, &soledge, nedges) );
393 
394  for( e = 0; e < nedges; e++ )
395  {
396  if( SCIPisEQ(scip, xval[e], 1.0) )
397  soledge[e] = CONNECT;
398  else
399  soledge[e] = UNKNOWN;
400  }
401 
402  /* execute prune heuristic */
403  SCIP_CALL( SCIPStpHeurPruneRun(scip, vars, graph, soledge, &success, TRUE, FALSE) );
404 
405  /* solution found by prune heuristic? */
406  if( success )
407  {
408  SCIP_SOL* sol;
409  SCIP_Real pobj;
410  SCIP_Real* nval;
411 
412  SCIPdebugMessage("ADDED valid solution in prune \n");
413 
414  assert(graph_sol_valid(scip, graph, soledge));
415  pobj = 0.0;
416 
417  /* allocate memory to store solution */
418  SCIP_CALL( SCIPallocBufferArray(scip, &nval, nvars) );
419 
420  for( e = 0; e < nedges; e++ )
421  {
422  if( soledge[e] == CONNECT )
423  {
424  nval[e] = 1.0;
425  pobj += graph->cost[e];
426  }
427  else
428  {
429  nval[e] = 0.0;
430  }
431  }
432 
433  SCIPdebugMessage("prune, best: old %f, new %f \n \n", SCIPgetSolOrigObj(scip, bestsol) - SCIPprobdataGetOffset(scip), pobj);
434 
435  /* try to add new solution to pool */
436  sol = NULL;
437  SCIP_CALL( SCIPprobdataAddNewSol(scip, nval, sol, heur, &success) );
438 
439  /* has solution been added? */
440  if( success )
441  {
442  SCIPdebugMessage("solution added by PRUNE \n \n");
443 
444  *result = SCIP_FOUNDSOL;
445 
446  assert(graph_sol_valid(scip, graph, soledge));
447 
448  /* is the solution the new incumbent? */
449  if( SCIPisGT(scip, SCIPgetSolOrigObj(scip, bestsol) - SCIPprobdataGetOffset(scip), pobj) )
450  {
451  heurdata->nfailures = 0;
452  }
453  else
454  {
455  success = FALSE;
456  }
457  }
458 
459  /* solution could not be added or is not best? */
460  if( !success )
461  heurdata->nfailures++;
462 
463  /* free memory */
464  SCIPfreeBufferArray(scip, &nval);
465  }
466 
467  /* store index of incumbent solution */
468  heurdata->bestsolindex = SCIPsolGetIndex(SCIPgetBestSol(scip));
469 
470  /* free memory */
471  SCIPfreeBufferArray(scip, &soledge);
472 
473  return SCIP_OKAY;
474 }
475 
476 
477 /*
478  * primal heuristic specific interface methods
479  */
480 
481 /** updates solutions for pruned graph */
483  SCIP* scip, /**< SCIP data structure */
484  GRAPH* g, /**< graph data structure */
485  GRAPH* prunegraph, /**< pruned graph data structure */
486  PATH* path, /**< shortest path struct */
487  int* nodearrint, /**< array */
488  int* edgearrint, /**< array */
489  int* solnode, /**< array for best solution nodes wrt prunegraph */
490  int* soledge, /**< array for best solution edges wrt prunegraph */
491  int* globalsoledge, /**< array storing best solution wrt g */
492  STP_Bool* nodearrchar, /**< array */
493  SCIP_Real* globalobj, /**< pointer to objective value of best solution wrt g */
494  SCIP_Bool incumbentgiven, /**< incumbent solution for pruned graph given? */
495  SCIP_Bool* success /**< pointer to store whether a solution could be found */
496  )
497 {
498  SCIP_Real objnew;
499  int* const pmark = prunegraph->mark;
500  const int nnodes = g->knots;
501  const int nedges = g->edges;
502  const int probtype = g->stp_type;
503  const SCIP_Bool pcmw = (probtype == STP_MWCSP || probtype == STP_RMWCSP || probtype == STP_RPCSPG || probtype == STP_PCSPG);
504 
505  assert(g != NULL);
506  assert(scip != NULL);
507  assert(soledge != NULL);
508  assert(path != NULL);
509  assert(solnode != NULL);
510  assert(edgearrint != NULL);
511  assert(nodearrint != NULL);
512  assert(nodearrchar != NULL);
513 
514  /*
515  * compare new solution on pruned graph with (reconstructed) incumbent
516  */
517 
518  if( incumbentgiven )
519  {
520  SCIP_Real objold;
521 
522  objnew = graph_sol_getObj(prunegraph->cost, soledge, 0.0, nedges);
523 
524  if( pcmw )
525  SCIP_CALL( SCIPStpHeurTMBuildTreePcMw(scip, prunegraph, path, prunegraph->cost, &objold, solnode) );
526  else
527  SCIP_CALL( SCIPStpHeurTMBuildTree(scip, prunegraph, path, prunegraph->cost, &objold, solnode) );
528 
529  SCIPdebugMessage("objold %f objnew %f \n", objold, objnew);
530 
531  /* keep (reconstructed) old solution? */
532  if( objold < objnew )
533  {
534  for( int e = 0; e < nedges; e++ )
535  soledge[e] = UNKNOWN;
536  for( int k = 0; k < nnodes; k++ )
537  {
538  const int e = path[k].edge;
539 
540  if( e >= 0 )
541  soledge[e] = CONNECT;
542  }
543  }
544  }
545 
546  assert(graph_sol_valid(scip, prunegraph, soledge));
547 
548  setNodeSolArray(prunegraph, NULL, solnode, soledge);
549 
550  /*
551  * retransform new solution and compare with best global one
552  */
553 
554  SCIP_CALL( graph_sol_getOrg(scip, prunegraph, g, soledge, edgearrint) );
555 
556  assert(graph_sol_valid(scip, g, edgearrint));
557 
558 #if BREAKONERROR
559  if( !graph_sol_valid(scip, g, edgearrint) )
560  {
561  printf("TM orig sol in prune not valid %d \n", 0);
562  exit(1);
563  }
564 #endif
565 
566  objnew = graph_sol_getObj(g->cost, edgearrint, 0.0, nedges);
567 
568  SCIPdebugMessage("old global obj: %f ... new global obj: %f \n", *globalobj, objnew);
569 
570  if( objnew < (*globalobj) )
571  {
572  SCIPdebugMessage("new global solution is better \n");
573  *globalobj = objnew;
574 
575  SCIP_CALL( SCIPStpHeurLocalRun(scip, g, g->cost, edgearrint) );
576 
577  objnew = graph_sol_getObj(g->cost, edgearrint, 0.0, nedges);
578 
579  assert(SCIPisLE(scip, objnew, *globalobj));
580 
581  if( objnew < (*globalobj) )
582  *globalobj = objnew;
583 
584  BMScopyMemoryArray(globalsoledge, edgearrint, nedges);
585  }
586 
587  assert(*globalobj < FARAWAY);
588 
589  for( int k = 0; k < nnodes; k++ )
590  pmark[k] = (prunegraph->grad[k] > 0);
591 
592  *success = TRUE;
593 
594  return SCIP_OKAY;
595 }
596 
597 /** execute prune heuristic on given graph */
599  SCIP* scip, /**< SCIP data structure */
600  SCIP_VAR** vars, /**< problem variables or NULL (need to be provided whenever available) */
601  GRAPH* g, /**< the graph */
602  int* soledge, /**< array to store primal solution (if no solution is provided,
603  withinitialsol must be set to FALSE) */
604  SCIP_Bool* success, /**< feasible solution found? */
605  const SCIP_Bool withinitialsol, /**< solution given? */
606  const SCIP_Bool reducegraph /**< try to reduce graph initially? */
607  )
608 {
609  GRAPH* prunegraph;
610  PATH* vnoi;
611  PATH* path;
612  SCIP_Real globalobj;
613  SCIP_Real uborg = 0.0;
614  SCIP_Real offset;
615  SCIP_Real* cost;
616  SCIP_Real* costrev;
617  SCIP_Real* nodearrreal;
618  const int probtype = g->stp_type;
619  const SCIP_Bool pc = (probtype == STP_RPCSPG || probtype == STP_PCSPG);
620  const SCIP_Bool mw = (probtype == STP_MWCSP || probtype == STP_RMWCSP);
621  const SCIP_Bool pcmw = (pc || mw);
622  const int nnodes = g->knots;
623  const int nedges = g->edges;
624  int annodes;
625  int anedges;
626  int anterms;
627  int reductbound;
628  int* heap;
629  int* state;
630  int* vbase;
631  int* solnode;
632  int* nodearrint;
633  int* edgearrint;
634  int* nodearrint2;
635  int* globalsoledge;
636  STP_Bool* nodearrchar;
637  SCIP_Bool solgiven;
638 
639  assert(g != NULL);
640  assert(scip != NULL);
641  assert(soledge != NULL);
642  assert(probtype != STP_DHCSTP);
643  assert(!(withinitialsol && reducegraph));
644 
645  *success = TRUE;
646 
647  if( reducegraph )
648  solgiven = FALSE;
649  else
650  solgiven = withinitialsol;
651 
652  if( g->terms <= 1)
653  {
654  for( int e = 0; e < nedges; e++ )
655  soledge[e] = UNKNOWN;
656  return SCIP_OKAY;
657  }
658 
659  /* allocate memory */
660  SCIP_CALL( SCIPallocBufferArray(scip, &globalsoledge, nedges) );
661  SCIP_CALL( SCIPallocBufferArray(scip, &solnode, nnodes) );
662  SCIP_CALL( SCIPallocBufferArray(scip, &cost, nedges) );
663  SCIP_CALL( SCIPallocBufferArray(scip, &costrev, nedges) );
664  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrchar, nnodes + 1) );
665  SCIP_CALL( SCIPallocBufferArray(scip, &heap, nnodes + 1) );
666  SCIP_CALL( SCIPallocBufferArray(scip, &state, 4 * nnodes) );
667  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrreal, nnodes) );
668  SCIP_CALL( SCIPallocBufferArray(scip, &vbase, 4 * nnodes) );
669  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrint, nnodes + 1) );
670  SCIP_CALL( SCIPallocBufferArray(scip, &edgearrint, nedges) );
671  SCIP_CALL( SCIPallocBufferArray(scip, &nodearrint2, nnodes + 1) );
672  SCIP_CALL( SCIPallocBufferArray(scip, &vnoi, 4 * nnodes) );
673  SCIP_CALL( SCIPallocBufferArray(scip, &path, nnodes + 1) );
674 
675  if( probtype == STP_RSMT || probtype == STP_OARSMT || probtype == STP_GSTP )
676  g->stp_type = STP_SPG;
677 
678  /* copy the graph */
679  SCIP_CALL( graph_copy(scip, g, &prunegraph) );
680 
681  if( probtype == STP_RSMT || probtype == STP_OARSMT || probtype == STP_GSTP )
682  g->stp_type = probtype;
683 
684  if( vars != NULL )
685  {
686  prunegraph->norgmodeledges = prunegraph->edges;
687  prunegraph->norgmodelknots = prunegraph->knots;
688  }
689 
690  /* set ancestors of the new graph */
691  SCIP_CALL( graph_init_history(scip, prunegraph) );
692 
693  /* set offset (within new graph) to 0.0 */
694  offset = 0.0;
695 
696  reductbound = getRedBound(0, nedges);
697 
698  SCIPdebugMessage("Starting prune... \n");
699 
700  assert(!pcmw || g->extended);
701 
702  /* problem variables given? */
703  if( vars != NULL )
704  {
705  int nfixedges = 0;
706 
707  /* delete fixed edges from the new graph */
708  for( int e = 0; e < nedges; e += 2 )
709  {
710  /* both e and its anti-parallel edge fixed to zero? */
711  if( SCIPvarGetUbLocal(vars[e]) < 0.5 && SCIPvarGetUbLocal(vars[e + 1]) < 0.5 )
712  {
713  if( pcmw )
714  {
715  if( (!solgiven || (soledge[e] != CONNECT && soledge[e + 1] != CONNECT))
716  && !Is_term(prunegraph->head[e]) && !Is_term(prunegraph->tail[e]) )
717  {
718  graph_edge_del(scip, prunegraph, e, TRUE);
719  nfixedges++;
720  }
721  }
722  else
723  {
724  if( !solgiven || (soledge[e] != CONNECT && soledge[e + 1] != CONNECT) )
725  {
726  graph_edge_del(scip, prunegraph, e, TRUE);
727  nfixedges++;
728  }
729  }
730  }
731  }
732  SCIPdebugMessage("fixed edges in prune: %d \n", nfixedges);
733 
734  if( nfixedges >= reductbound )
735  {
736  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
737  reductbound = getRedBound(0, anedges);
738  }
739  }
740 
741  SCIP_CALL(graph_path_init(scip, prunegraph));
742 
743  /* perform initial reductions? */
744  if( reducegraph )
745  {
746  if( pc )
747  SCIP_CALL( redLoopPc(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, heap, state,
748  vbase, nodearrint, edgearrint, nodearrint2, NULL, nodearrchar, &offset, FALSE, FALSE, reductbound, FALSE) );
749  else if( mw )
750  SCIP_CALL( redLoopMw(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, state,
751  vbase, nodearrint, edgearrint, nodearrint2, heap, NULL, nodearrchar, &offset, FALSE, FALSE, FALSE, reductbound, FALSE) );
752  else
753  SCIP_CALL( redLoopStp(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, heap, state,
754  vbase, nodearrint, edgearrint, nodearrint2, NULL, nodearrchar, &offset, -1.0, FALSE, FALSE, TRUE, reductbound, FALSE, FALSE) );
755  }
756 
757  /* get number of remaining nodes, edges and terminals */
758  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
759 
760  if( solgiven )
761  {
762  BMScopyMemoryArray(globalsoledge, soledge, nedges);
763  globalobj = graph_sol_getObj(g->cost, soledge, 0.0, nedges);
764  setNodeSolArray(g, &uborg, solnode, soledge);
765  }
766  else
767  {
768  globalobj = FARAWAY;
769  SCIP_CALL( computeNewSols(scip, g, prunegraph, path, nodearrint, edgearrint, solnode, soledge, globalsoledge, nodearrchar, &globalobj, FALSE, success) );
770 
771  assert(success);
772  }
773 
774  SCIPdebugMessage("initially reduced graph: |V| = %d, |E| = %d, |T| = %d \n", annodes, anedges, anterms);
775  SCIPdebugMessage("entering prune \n\n");
776 
777  if( annodes > 0 )
778  {
779  /* main prune reduction loop */
780  for( int i = 0; i < PRUNE_MAXREDROUNDS; i++ )
781  {
782  int minnelims = 0;
783  int brednelims = 0;
784  int lminnelims = 0;
785 
786  /* get number of remaining edges */
787  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
788 
789  if( anterms <= 2 )
790  {
791  SCIPdebugMessage("less than two terminals, break !! \n");
792  break;
793  }
794 
795  setMinMaxElims(scip, &minnelims, &lminnelims, annodes, anedges, anterms, i + 1, PRUNE_MAXREDROUNDS);
796 
797  if( i > 0 )
798  {
799  SCIP_CALL( computeNewSols(scip, g, prunegraph, path, nodearrint, edgearrint, solnode, soledge, globalsoledge,
800  nodearrchar, &globalobj, TRUE, success) );
801  }
802 
803  if( pcmw )
804  graph_pc_2org(prunegraph);
805 
806  SCIP_CALL( reduce_boundPrune(scip, prunegraph, vnoi, cost, nodearrreal, costrev,
807  &offset, heap, state, vbase, solnode, soledge, &brednelims, minnelims));
808 
809  if( pcmw )
810  graph_pc_2trans(prunegraph);
811 
812 #ifdef SCIP_DEBUG
813  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
814  printf("PRUNE round: %d edges %d nodes: %d \n", i, anedges / 2, annodes);
815  printf("PRUNE round: %d minelims %d really reduced: %d \n", i, minnelims, brednelims);
816 #endif
817 
818  /* not enough reductions possible? */
819  if( brednelims < lminnelims )
820  {
821  SCIPdebugMessage("not enough elims in PRUNE; exit %d \n\n", brednelims);
822  i = PRUNE_MAXREDROUNDS;
823  }
824 
825  /* delete all vertices not reachable from the root */
826  SCIP_CALL( level0(scip, prunegraph) );
827 
828  assert(graph_valid(prunegraph));
829 
830  /* is the reduced graph still feasible? */
831  if( !graph_valid(prunegraph) )
832  break;
833 
834  /* get number of remaining edges */
835  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
836 
837  reductbound = getRedBound(i + 1, anedges);
838 
839  /* reduce graph */
840  if( pc )
841  SCIP_CALL( redLoopPc(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, heap, state,
842  vbase, nodearrint, edgearrint, nodearrint2, solnode, nodearrchar, &offset, FALSE, FALSE, reductbound, FALSE) );
843  else if( mw )
844  SCIP_CALL( redLoopMw(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, state,
845  vbase, nodearrint, edgearrint, nodearrint2, heap, solnode, nodearrchar, &offset, FALSE, FALSE, FALSE, reductbound, FALSE) );
846  else
847  SCIP_CALL( redLoopStp(scip, prunegraph, vnoi, path, NULL, nodearrreal, cost, costrev, heap, state, vbase, nodearrint, edgearrint,
848  nodearrint2, solnode, nodearrchar, &offset, -1.0, FALSE, FALSE, TRUE, reductbound, FALSE, FALSE));
849 
850  /* delete all vertices not reachable from the root */
851  SCIP_CALL( level0(scip, prunegraph) );
852 
853  graph_get_NVET(prunegraph, &annodes, &anedges, &anterms);
854 
855  if( anterms <= 2 )
856  {
857  SCIPdebugMessage("less than two terminals, break !! \n");
858  SCIP_CALL( computeNewSols(scip, g, prunegraph, path, nodearrint, edgearrint, solnode, soledge, globalsoledge,
859  nodearrchar, &globalobj, TRUE, success) );
860  break;
861  }
862  } /* reduction loop */
863  } /* main prune loop */
864 
865  for( int k = 0; k < nnodes; k++ )
866  nodearrchar[k] = FALSE;
867 
868  graph_path_exit(scip, prunegraph);
869 
870  *success = graph_sol_valid(scip, g, globalsoledge);
871  assert(*success);
872 
873  SCIPdebugMessage("obj of best prune sol: %f \n", graph_sol_getObj(g->cost, globalsoledge, 0.0, nedges));
874 
875  BMScopyMemoryArray(soledge, globalsoledge, nedges);
876 
877 #if BREAKONERROR
878  if( !(*success) )
879  {
880  printf("final sol not valid %d \n", 0);
881  return SCIP_ERROR;
882  }
883 #endif
884 
885  /* free memory */
886  graph_free(scip, &prunegraph, TRUE);
887 
888  SCIPfreeBufferArray(scip, &path);
889  SCIPfreeBufferArray(scip, &vnoi);
890  SCIPfreeBufferArray(scip, &nodearrint2);
891  SCIPfreeBufferArray(scip, &edgearrint);
892  SCIPfreeBufferArray(scip, &nodearrint);
893  SCIPfreeBufferArray(scip, &vbase);
894  SCIPfreeBufferArray(scip, &nodearrreal);
895  SCIPfreeBufferArray(scip, &state);
896  SCIPfreeBufferArray(scip, &heap);
897  SCIPfreeBufferArray(scip, &nodearrchar);
898  SCIPfreeBufferArray(scip, &costrev);
899  SCIPfreeBufferArray(scip, &cost);
900  SCIPfreeBufferArray(scip, &solnode);
901  SCIPfreeBufferArray(scip, &globalsoledge);
902 
903  return SCIP_OKAY;
904 }
905 
906 
907 /** creates the prune primal heuristic and includes it in SCIP */
909  SCIP* scip /**< SCIP data structure */
910  )
911 {
912  SCIP_HEURDATA* heurdata;
913  SCIP_HEUR* heur;
914 
915  /* create prune primal heuristic data */
916  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
917 
918  /* include primal heuristic */
919  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
921  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecPrune, heurdata) );
922 
923  assert(heur != NULL);
924 
925  /* set non fundamental callbacks via setter functions */
926  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyPrune) );
927  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreePrune) );
928  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitPrune) );
929  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolPrune) );
930  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolPrune) );
931 
932  /* add prune primal heuristic parameters */
933  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/"HEUR_NAME"/maxfreq",
934  "should the heuristic be executed at maximum frequeny?",
935  &heurdata->maxfreq, FALSE, DEFAULT_PRUNE_MAXFRQ, NULL, NULL) );
936 
937  return SCIP_OKAY;
938 }
SCIP_RETCODE graph_path_init(SCIP *, GRAPH *)
Definition: grphpath.c:444
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip_heur.c:312
#define DEFAULT_PRUNE_TMRUNS
Definition: heur_prune.c:55
SCIP_RETCODE SCIPStpHeurPruneRun(SCIP *scip, SCIP_VAR **vars, GRAPH *g, int *soledge, SCIP_Bool *success, const SCIP_Bool withinitialsol, const SCIP_Bool reducegraph)
Definition: heur_prune.c:598
void graph_get_NVET(const GRAPH *, int *, int *, int *)
Definition: grphbase.c:3382
#define NULL
Definition: def.h:246
#define HEUR_TIMING
Definition: heur_prune.c:51
int *RESTRICT head
Definition: grph.h:96
Definition: grph.h:57
int source
Definition: grph.h:67
static int getRedBound(int nround, int nedges)
Definition: heur_prune.c:182
#define STP_GSTP
Definition: grph.h:49
static SCIP_DECL_HEURINITSOL(heurInitsolPrune)
Definition: heur_prune.c:294
Constraint handler for Steiner problems.
signed int edge
Definition: grph.h:146
SCIP_RETCODE reduce_boundPrune(SCIP *, GRAPH *, PATH *, SCIP_Real *, SCIP_Real *, SCIP_Real *, SCIP_Real *, int *, int *, int *, const int *, const int *, int *, int)
Definition: reduce_bnd.c:5415
SCIP_Bool graph_valid(const GRAPH *)
Definition: grphbase.c:4324
int terms
Definition: grph.h:64
SCIP_VAR ** SCIPprobdataGetVars(SCIP *scip)
#define HEUR_DISPCHAR
Definition: heur_prune.c:46
SCIP_RETCODE graph_copy(SCIP *, const GRAPH *, GRAPH **)
Definition: grphbase.c:3896
SCIP_RETCODE graph_init_history(SCIP *, GRAPH *)
Definition: grphbase.c:3569
int norgmodeledges
Definition: grph.h:88
#define FALSE
Definition: def.h:72
#define STP_RMWCSP
Definition: grph.h:50
void graph_free(SCIP *, GRAPH **, SCIP_Bool)
Definition: grphbase.c:3674
Problem data for stp problem.
#define TRUE
Definition: def.h:71
SCIP_RETCODE SCIPStpHeurTMRun(SCIP *scip, SCIP_HEURDATA *heurdata, GRAPH *graph, int *starts, int *bestnewstart, int *best_result, int runs, int bestincstart, SCIP_Real *cost, SCIP_Real *costrev, SCIP_Real *hopfactor, SCIP_Real *nodepriority, SCIP_Real maxcost, SCIP_Bool *success, SCIP_Bool pcmwfull)
Definition: heur_tm.c:1650
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
void graph_path_exit(SCIP *, GRAPH *)
Definition: grphpath.c:466
#define STP_DHCSTP
Definition: grph.h:48
int SCIPprobdataGetNVars(SCIP *scip)
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip_heur.c:187
#define STP_PCSPG
Definition: grph.h:40
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE redLoopPc(SCIP *, GRAPH *, PATH *, PATH *, GNODE **, SCIP_Real *, SCIP_Real *, SCIP_Real *, int *, int *, int *, int *, int *, int *, int *, STP_Bool *, SCIP_Real *, SCIP_Bool, SCIP_Bool, int, SCIP_Bool)
Definition: reduce.c:1158
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:142
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1175
GRAPH * SCIPprobdataGetGraph(SCIP_PROBDATA *probdata)
SCIP_RETCODE SCIPStpHeurPruneUpdateSols(SCIP *scip, GRAPH *g, GRAPH *prunegraph, PATH *path, int *nodearrint, int *edgearrint, int *solnode, int *soledge, int *globalsoledge, STP_Bool *nodearrchar, SCIP_Real *globalobj, SCIP_Bool incumbentgiven, SCIP_Bool *success)
Definition: heur_prune.c:482
int *RESTRICT mark
Definition: grph.h:70
SCIP_RETCODE SCIPStpIncludeHeurPrune(SCIP *scip)
Definition: heur_prune.c:908
SCIP_RETCODE redLoopStp(SCIP *, GRAPH *, PATH *, PATH *, GNODE **, SCIP_Real *, SCIP_Real *, SCIP_Real *, int *, int *, int *, int *, int *, int *, int *, STP_Bool *, SCIP_Real *, SCIP_Real, SCIP_Bool, SCIP_Bool, SCIP_Bool, int, SCIP_Bool, SCIP_Bool)
Definition: reduce.c:1409
void graph_pc_2org(GRAPH *)
Definition: grphbase.c:964
static SCIP_DECL_HEURCOPY(heurCopyPrune)
Definition: heur_prune.c:249
static SCIP_DECL_HEUREXEC(heurExecPrune)
Definition: heur_prune.c:326
#define CONNECT
Definition: grph.h:154
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:296
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1254
SCIP_Bool extended
Definition: grph.h:128
int stp_type
Definition: grph.h:127
SCIP_RETCODE level0(SCIP *, GRAPH *)
Definition: reduce.c:153
void graph_pc_2trans(GRAPH *)
Definition: grphbase.c:1002
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:248
unsigned char STP_Bool
Definition: grph.h:52
SCIP_RETCODE SCIPprobdataAddNewSol(SCIP *scip, SCIP_Real *nval, SCIP_SOL *sol, SCIP_HEUR *heur, SCIP_Bool *success)
SCIP_Real SCIPprobdataGetOffset(SCIP *scip)
void SCIPStpHeurTMCompStarts(GRAPH *graph, int *starts, int *runs)
Definition: heur_tm.c:115
static SCIP_RETCODE computeNewSols(SCIP *scip, GRAPH *g, GRAPH *prunegraph, PATH *path, int *nodearrint, int *edgearrint, int *solnode, int *soledge, int *globalsoledge, STP_Bool *nodearrchar, SCIP_Real *globalobj, SCIP_Bool incumbentgiven, SCIP_Bool *success)
Definition: heur_prune.c:128
int *RESTRICT grad
Definition: grph.h:73
#define HEUR_FREQOFS
Definition: heur_prune.c:49
SCIP_Bool graph_sol_valid(SCIP *, const GRAPH *, const int *)
Definition: grphbase.c:3066
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2553
#define MAXNEDGES
Definition: heur_prune.c:60
int knots
Definition: grph.h:62
#define SCIP_CALL(x)
Definition: def.h:358
static void setMinMaxElims(SCIP *scip, int *minnelims, int *lminnelims, int annodes, int anedges, int anterms, int nround, int maxrounds)
Definition: heur_prune.c:196
Improvement heuristic for Steiner problems.
reduction-based primal heuristic for Steiner problems
#define FARAWAY
Definition: grph.h:156
#define STP_SPG
Definition: grph.h:38
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:69
SCIP_RETCODE graph_sol_getOrg(SCIP *, const GRAPH *, const GRAPH *, const int *, int *)
Definition: grphbase.c:3214
#define STP_MWCSP
Definition: grph.h:47
int *RESTRICT tail
Definition: grph.h:95
#define MIN(x, y)
Definition: def.h:216
#define HEUR_DESC
Definition: heur_prune.c:45
static SCIP_DECL_HEUREXITSOL(heurExitsolPrune)
Definition: heur_prune.c:317
void graph_edge_del(SCIP *, GRAPH *, int, SCIP_Bool)
Definition: grphbase.c:2837
SCIP_Real graph_sol_getObj(const SCIP_Real *, const int *, SCIP_Real, int)
Definition: grphbase.c:3196
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:123
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1493
Constraint handler for linear constraints in their most general form, .
includes various files containing graph methods used for Steiner tree problems
#define SCIPfreeMemory(scip, ptr)
Definition: scip_mem.h:86
#define HEUR_USESSUBSCIP
Definition: heur_prune.c:52
#define PRUNE_MINREDELIMS
Definition: heur_prune.c:56
#define PRUNE_MAXREDROUNDS
Definition: heur_prune.c:57
#define Is_term(a)
Definition: grph.h:168
#define MAX(x, y)
Definition: def.h:215
#define MAXNTERMINALS
Definition: heur_prune.c:59
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2362
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
struct SCIP_ProbData SCIP_PROBDATA
Definition: type_prob.h:44
#define HEUR_MAXDEPTH
Definition: heur_prune.c:50
SCIP_PROBDATA * SCIPgetProbData(SCIP *scip)
Definition: scip_prob.c:1020
SCIP_Real * cost
Definition: grph.h:94
#define HEUR_PRIORITY
Definition: heur_prune.c:47
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:264
#define SCIP_Real
Definition: def.h:157
#define DEFAULT_PRUNE_MAXFRQ
Definition: heur_prune.c:54
SCIP_Real * SCIPprobdataGetXval(SCIP *scip, SCIP_SOL *sol)
SCIP_RETCODE SCIPStpHeurLocalRun(SCIP *scip, GRAPH *graph, const SCIP_Real *cost, int *best_result)
Definition: heur_local.c:208
shortest paths based primal heuristics for Steiner problems
int edges
Definition: grph.h:92
SCIP_RETCODE SCIPStpHeurTMBuildTree(SCIP *scip, const GRAPH *g, PATH *mst, const SCIP_Real *cost, SCIP_Real *objresult, int *connected)
Definition: heur_tm.c:654
#define SCIPallocMemory(scip, ptr)
Definition: scip_mem.h:70
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define UNKNOWN
Definition: sepa_mcf.c:4081
#define STP_RSMT
Definition: grph.h:45
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:232
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17410
#define nnodes
Definition: gastrans.c:65
#define STP_OARSMT
Definition: grph.h:46
static SCIP_DECL_HEURINIT(heurInitPrune)
Definition: heur_prune.c:284
#define HEUR_NAME
Definition: heur_prune.c:44
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1165
static SCIP_DECL_HEURFREE(heurFreePrune)
Definition: heur_prune.c:263
default SCIP plugins
#define STP_RPCSPG
Definition: grph.h:41
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:2584
#define HEUR_FREQ
Definition: heur_prune.c:48
SCIP callable library.
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
int norgmodelknots
Definition: grph.h:60
SCIP_RETCODE SCIPStpHeurTMBuildTreePcMw(SCIP *scip, const GRAPH *g, PATH *mst, const SCIP_Real *cost, SCIP_Real *objresult, int *connected)
Definition: heur_tm.c:383
static void setNodeSolArray(const GRAPH *g, SCIP_Real *uborg, int *solnode, const int *soledge)
Definition: heur_prune.c:88
SCIP_RETCODE redLoopMw(SCIP *, GRAPH *, PATH *, PATH *, GNODE **, SCIP_Real *, SCIP_Real *, SCIP_Real *, int *, int *, int *, int *, int *, int *, int *, STP_Bool *, SCIP_Real *, STP_Bool, STP_Bool, STP_Bool, int, SCIP_Bool)
Definition: reduce.c:921