Scippy

SCIP

Solving Constraint Integer Programs

heur_rec.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-2015 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_rec.c
17  * @brief Primal recombination heuristic for Steiner problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements a recombination heuristic for Steiner problems, see
21  * "SCIP-Jack - A solver for STP and variants with parallelization extensions" by
22  * Gamrath, Koch, Maher, Rehfeldt and Shinano
23  *
24  * A list of all interface methods can be found in heur_rec.h
25  *
26  */
27 
28 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 
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_rec.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 "rec"
45 #define HEUR_DESC "LNS heuristic fixing all variables corresponding to edges used in at least one of several selected solutions"
46 #define HEUR_DISPCHAR 'R'
47 #define HEUR_PRIORITY 100
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 TRUE /**< does the heuristic use a secondary SCIP instance? */
53 
54 #define DEFAULT_MAXFREQREC FALSE /**< executions of the rec heuristic at maximum frequency? */
55 #define DEFAULT_MAXNSOLS 50 /**< maximum number of (good) solutions be regarded in the subproblem */
56 #define DEFAULT_NUSEDSOLS 4 /**< number of solutions that will be taken into account */
57 #define DEFAULT_RANDSEED 0 /**< random seed */
58 #define DEFAULT_NTMRUNS 75 /**< number of runs in TM heuristic */
59 #define DEFAULT_NWAITINGSOLS 4 /**< max number of new solutions to be available before executing the heuristic again */
60 
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 {
75  int bestsolindex; /**< best solution during the previous run */
76  int maxnsols; /**< maximum number of (good) solutions be regarded in the subproblem */
77  SCIP_Longint ncalls; /**< number of calls */
78  SCIP_Longint nlastsols; /**< number of solutions during the last run */
79  int ntmruns; /**< number of runs in TM heuristic */
80  int nusedsols; /**< number of solutions that will be taken into account */
81  int nselectedsols; /**< number of solutions actually selected */
82  int nwaitingsols; /**< number of new solutions before executing the heuristic again */
83  int nfailures; /**< number of failures since last successful call */
84  unsigned int randseed; /**< seed value for random number generator */
85  SCIP_Bool maxfreq; /**< should the heuristic be called at maximum frequency? */
86 };
87 
88 
89 /*
90  * Local methods
91  */
92 
93 /** information method for a parameter change of random seed */
94 static
95 SCIP_DECL_PARAMCHGD(paramChgdRandomseed)
96 { /*lint --e{715}*/
97  SCIP_HEURDATA* heurdata;
98  int newrandseed;
99 
100  newrandseed = SCIPparamGetInt(param);
101 
102  heurdata = (SCIP_HEURDATA*)SCIPparamGetData(param);
103  assert(heurdata != NULL);
104 
105  heurdata->randseed = (unsigned int)newrandseed;
106 
107  return SCIP_OKAY;
108 }
109 
110 /** edge cost multiplier */
111 static
112 SCIP_Real costMultiplier(
113  SCIP* scip, /**< SCIP data structure */
114  SCIP_HEURDATA* heurdata, /**< SCIP data structure */
115  SCIP_Real avg /**< number of solutions containing this edge */
116  )
117 {
118  int factor = 1;
119  int nusedsols = heurdata->nusedsols;
120  SCIP_Real mult = 1;
121  assert(SCIPisGE(scip, avg, 1.0));
122  if( nusedsols <= 3 )
123  {
124  if( SCIPisLT(scip, avg, 1.6) )
125  {
126  factor = SCIPgetRandomInt(1000, 1400, &(heurdata->randseed));
127  mult = (double) factor * (1.0 / avg);
128  }
129  else if( SCIPisLT(scip, avg, 2.6) )
130  {
131  factor = SCIPgetRandomInt(200, 1000, &(heurdata->randseed));
132  mult = (double) factor * (1.0 / avg);
133  }
134  else if( nusedsols == 3 && SCIPisLT(scip, avg, 3.6) )
135  {
136  factor = SCIPgetRandomInt(40, 100, &(heurdata->randseed));
137  mult = (double) factor * (1.0 / avg);
138  }
139  }
140  else
141  {
142  if( SCIPisLT(scip, avg, 1.6) )
143  {
144  factor = SCIPgetRandomInt(1400, 1800, &(heurdata->randseed));
145  }
146  else if( SCIPisLT(scip, avg, 2.6) )
147  {
148  factor = SCIPgetRandomInt(400, 1400, &(heurdata->randseed));
149  }
150  else if( SCIPisLT(scip, avg, 3.6) )
151  {
152  factor = SCIPgetRandomInt(150, 250, &(heurdata->randseed));
153  }
154  else if( SCIPisLT(scip, avg, 4.6) )
155  {
156  factor = SCIPgetRandomInt(60, 90, &(heurdata->randseed));
157  }
158  else if( nusedsols >= 5 && SCIPisLT(scip, avg, 5.6) )
159  {
160  factor = SCIPgetRandomInt(20, 40, &(heurdata->randseed));
161  }
162  mult = (double) factor * (1.0 / avg);
163  }
164 
165  return mult;
166 }
167 
168 /** select solutions to be merged */
169 static
170 SCIP_RETCODE selectdiffsols(
171  SCIP* scip, /**< SCIP data structure */
172  GRAPH* graph, /**< graph data structure */
173  SCIP_HEURDATA* heurdata, /**< SCIP data structure */
174  SCIP_VAR** vars, /**< problem variables */
175  SCIP_SOL** newsol, /**< new solution */
176  int* selection, /**< selected solutions */
177  SCIP_Bool* success /**< could at least two solutions be selected? */
178  )
179 {
180  SCIP_Real* soltimes;
181  SCIP_SOL** sols; /* array of all solutions found so far */
182  SCIP_Real varsolval;
183  SCIP_Real varrevsolval;
184  int i;
185  int e;
186  int k;
187  int head;
188  int tail;
189  int eqnedges;
190  int diffnedges;
191  int maxnsols;
192  int nselectedsols;
193  int nsols; /* number of all solutions found so far */
194  int nedges;
195  int nusedsols; /* number of solutions to use in rec */
196  int* perm;
197  int* solselected;
198  char* soledges;
199  assert(selection != NULL);
200  assert(graph != NULL);
201  assert(vars != NULL);
202 
203  /* get solution data */
204  sols = SCIPgetSols(scip);
205  nsols = SCIPgetNSols(scip);
206  maxnsols = heurdata->maxnsols;
207  nusedsols = heurdata->nusedsols;
208  nedges = graph->edges;
209  assert(nusedsols <= nsols);
210  nselectedsols = 0;
211 
212  assert(nusedsols > 1);
213  assert(nsols >= nusedsols);
214 
215  /* allocate memory */
216  SCIP_CALL( SCIPallocBufferArray(scip, &solselected, nsols) );
217  SCIP_CALL( SCIPallocBufferArray(scip, &soltimes, nsols) );
218  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nsols) );
219  SCIP_CALL( SCIPallocBufferArray(scip, &soledges, nedges / 2) );
220 
221  for( i = 0; i < nsols; i++ )
222  {
223  perm[i] = i;
224  soltimes[i] = SCIPgetSolTime(scip, sols[i]);
225  solselected[i] = FALSE;
226  }
227 
228  if( *newsol == NULL )
229  {
230  SCIPsortRealInt(soltimes, perm, nsols);
231  i = nsols - 1;
232  /* has the latest solution already been tried? */
233  if( heurdata->lastsolindex != SCIPsolGetIndex(sols[perm[i]]) )
234  {
235  *newsol = sols[perm[i]];
236  }
237  else
238  {
239  i = SCIPgetRandomInt(0, nsols - 1, &(heurdata->randseed));
240  }
241  *newsol = sols[perm[i]];
242  solselected[perm[i]] = TRUE;
243  selection[nselectedsols++] = perm[i];
244 
245  for( i = 0; i < nsols; i++ )
246  perm[i] = i;
247  }
248  else
249  {
250  for( i = 0; i < nsols; i++ )
251  if( *newsol == sols[i] )
252  break;
253  assert(i < nsols);
254  solselected[i] = TRUE;
255  selection[nselectedsols++] = i;
256  }
257 
258  for( e = 0; e < nedges; e += 2 )
259  {
260  varsolval = SCIPgetSolVal(scip, sols[selection[0]], vars[e]);
261  varrevsolval = SCIPgetSolVal(scip, sols[selection[0]], vars[e + 1]);
262 
263  if( SCIPisEQ(scip, varsolval, 1.0) || SCIPisEQ(scip, varrevsolval, 1.0) )
264  {
265  soledges[e / 2] = TRUE;
266  }
267  else
268  {
269  soledges[e / 2] = FALSE;
270  }
271  }
272  maxnsols = MIN(nsols, maxnsols);
273 
274  SCIPpermuteIntArray(perm, 0, maxnsols, &(heurdata->randseed));
275  for( i = 0; i < maxnsols; i++ )
276  {
277  if( solselected[perm[i]] == FALSE )
278  {
279  k = perm[i];
280  eqnedges = 0;
281  diffnedges = 0;
282  for( e = 0; e < nedges; e += 2 )
283  {
284  varsolval = SCIPgetSolVal(scip, sols[k], vars[e]);
285  varrevsolval = SCIPgetSolVal(scip, sols[k], vars[e + 1]);
286 
287  if( SCIPisEQ(scip, varsolval, 1.0) || SCIPisEQ(scip, varrevsolval, 1.0) )
288  {
289  head = graph->head[e];
290  tail = graph->tail[e];
291  if( soledges[e / 2] == FALSE )
292  {
293  soledges[e / 2] = TRUE;
294  if( !(Is_term(graph->term[tail]) && Is_term(graph->term[head])) )
295  diffnedges++;
296  }
297  else
298  {
299  if( !(Is_term(graph->term[tail]) && Is_term(graph->term[head])) )
300  eqnedges++;
301  }
302  }
303  }
304 
305  if( diffnedges > 3 && eqnedges > 0 )
306  {
307  selection[nselectedsols++] = k;
308  solselected[k] = TRUE;
309  *success = TRUE;
310  if( nselectedsols >= nusedsols )
311  break;
312  }
313 
314  }
315  }
316 
317  assert(nselectedsols <= nusedsols);
318  heurdata->nselectedsols = nselectedsols;
319  SCIPfreeBufferArray(scip, &soledges);
320  SCIPfreeBufferArray(scip, &perm);
321  SCIPfreeBufferArray(scip, &soltimes);
322  SCIPfreeBufferArray(scip, &solselected);
323 
324  return SCIP_OKAY;
325 }
326 
327 /** select solutions to be merged */
328 static
329 SCIP_RETCODE selectsols(
330  SCIP* scip, /**< SCIP data structure */
331  SCIP_HEURDATA* heurdata, /**< SCIP data structure */
332  SCIP_SOL** newsol, /**< new solution */
333  int* selection, /**< selected solutions */
334  SCIP_Bool randomize /**< select solutions randomly? */
335  )
336 {
337  SCIP_Real* soltimes;
338  SCIP_SOL** sols; /* array of all solutions found so far */
339  int i;
340  int end;
341  int maxnsols;
342  int nselectedsols;
343  int shift;
344  int nsols; /* number of all solutions found so far */
345  int nusedsols; /* number of solutions to use in rec */
346  int* perm;
347  int* solselected;
348 
349  assert(selection != NULL);
350 
351  /* get solution data */
352  sols = SCIPgetSols(scip);
353  nsols = SCIPgetNSols(scip);
354  maxnsols = heurdata->maxnsols;
355  nusedsols = heurdata->nusedsols;
356  assert(nusedsols <= nsols);
357  nselectedsols = 0;
358 
359  assert(nusedsols > 1);
360  assert(nsols >= nusedsols);
361 
362  /* allocate memory */
363  SCIP_CALL( SCIPallocBufferArray(scip, &solselected, nsols) );
364  SCIP_CALL( SCIPallocBufferArray(scip, &soltimes, nsols) );
365  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nsols) );
366 
367  for( i = 0; i < nsols; i++ )
368  {
369  perm[i] = i;
370  soltimes[i] = SCIPgetSolTime(scip, sols[i]);
371  solselected[i] = FALSE;
372  }
373 
374  if( *newsol == NULL )
375  {
376  SCIPsortRealInt(soltimes, perm, nsols);
377  i = nsols - 1;
378 
379  /* has the latest solution already been tried? */
380  if( heurdata->lastsolindex != SCIPsolGetIndex(sols[perm[i]]) )
381  {
382  *newsol = sols[perm[i]];
383  }
384  else
385  {
386  i = SCIPgetRandomInt(0, nsols - 1, &(heurdata->randseed));
387  }
388  *newsol = sols[perm[i]];
389  solselected[perm[i]] = TRUE;
390  selection[nselectedsols++] = perm[i];
391 
392  for( i = 0; i < nsols; i++ )
393  perm[i] = i;
394  }
395  else
396  {
397  for( i = 0; i < nsols; i++ )
398  if( *newsol == sols[i] )
399  break;
400  assert(i < nsols);
401  if( i >= nsols )
402  i = 0;
403  solselected[i] = TRUE;
404  selection[nselectedsols++] = i;
405  }
406 
407  if( !randomize )
408  {
409  end = (int) ((SCIPgetRandomReal(1.0, (double) nusedsols - 1, &(heurdata->randseed))) );
410 
411  shift = SCIPgetRandomInt(end, 2 * nusedsols - 1, &(heurdata->randseed));
412 
413  if( shift > nsols )
414  shift = nsols;
415  SCIPpermuteIntArray(perm, 0, shift, &(heurdata->randseed));
416 
417  for( i = 0; i < end; i++ )
418  {
419  if( solselected[perm[i]] == FALSE )
420  {
421  selection[nselectedsols++] = perm[i];
422  solselected[perm[i]] = TRUE;
423  }
424  }
425  }
426  maxnsols = MIN(nsols, maxnsols);
427  if( nselectedsols < nusedsols )
428  {
429  SCIPpermuteIntArray(perm, 0, maxnsols, &(heurdata->randseed));
430  for( i = 0; i < maxnsols; i++ )
431  {
432  if( solselected[perm[i]] == FALSE )
433  {
434  selection[nselectedsols++] = perm[i];
435  if( nselectedsols >= nusedsols )
436  break;
437  }
438  }
439  }
440  assert(nselectedsols <= nusedsols);
441  heurdata->nselectedsols = nselectedsols;
442  SCIPfreeBufferArray(scip, &perm);
443  SCIPfreeBufferArray(scip, &soltimes);
444  SCIPfreeBufferArray(scip, &solselected);
445 
446  return SCIP_OKAY;
447 }
448 
449 /** merge selected solutions to a new graph */
450 static
451 SCIP_RETCODE buildsolgraph(
452  SCIP* scip, /**< SCIP data structure */
453  SCIP_HEURDATA* heurdata, /**< SCIP data structure */
454  SCIP_SOL** newsol, /**< new solution */
455  GRAPH* graph, /**< graph structure */
456  GRAPH** solgraph, /**< pointer to store new graph */
457  int** edgeancestor, /**< ancestor to edge edge */
458  int** edgeweight, /**< fore each edge: number of solution that contain this edge */
459  SCIP_Bool* success, /**< new graph constructed? */
460  SCIP_Bool randomize /**< select solution randomly? */
461  )
462 {
463  GRAPH* newgraph;
464  SCIP_SOL** sols;
465  SCIP_VAR** vars;
466  SCIP_Real varsolval;
467  SCIP_Real varrevsolval;
468 
469  int i;
470  int j;
471  int k;
472  int nedges;
473  int nnodes;
474  int nsoledges;
475  int nsolnodes;
476  int* dnodemap;
477  int* solselection; /* pool of solutions rec will use */
478  SCIP_Bool pcmw;
479  char* solnode; /* marks nodes contained in at least one solution */
480  char* soledge; /* marks edges contained in at least one solution */
481 
482  assert(scip != NULL);
483  assert(graph != NULL);
484 
485  sols = SCIPgetSols(scip);
486  nedges = graph->edges;
487  nnodes = graph->knots;
488  nsoledges = 0;
489  nsolnodes = 0;
490  *success = TRUE;
491  *edgeweight = NULL;
492  *edgeancestor = NULL;
493  newgraph = NULL;
495  assert(sols != NULL);
496 
497  vars = SCIPprobdataGetEdgeVars(scip);
498 
499  /* allocate memory */
500  SCIP_CALL( SCIPallocBufferArray(scip, &solselection, heurdata->nusedsols) );
501  SCIP_CALL( SCIPallocBufferArray(scip, &solnode, nnodes) );
502  SCIP_CALL( SCIPallocBufferArray(scip, &dnodemap, nnodes) );
503  SCIP_CALL( SCIPallocBufferArray(scip, &soledge, nedges / 2) );
504 
505  for( i = 0; i < nedges / 2; i++ )
506  soledge[i] = FALSE;
507  for( i = 0; i < nnodes; i++ )
508  {
509  solnode[i] = FALSE;
510  dnodemap[i] = UNKNOWN;
511  }
512 
513  /* select solutions to be merged */
514  if( pcmw || graph->stp_type == STP_DEG_CONS )
515  SCIP_CALL( selectdiffsols(scip, graph, heurdata, vars, newsol, solselection, success) );
516  else
517  SCIP_CALL( selectsols(scip, heurdata, newsol, solselection, randomize) );
518 
519  if( *success )
520  {
521  assert(heurdata->nselectedsols > 0);
522 
523  /* count and mark selected nodes and edges */
524  for( i = 0; i < nedges; i += 2 )
525  {
526  for( j = 0; j < heurdata->nselectedsols; j++ )
527  {
528  varsolval = SCIPgetSolVal(scip, sols[solselection[j]], vars[i]);
529  varrevsolval = SCIPgetSolVal(scip, sols[solselection[j]], vars[i + 1]);
530 
531  if( SCIPisEQ(scip, varsolval, 1.0) || SCIPisEQ(scip, varrevsolval, 1.0) )
532  {
533  nsoledges++;
534  soledge[i / 2] = TRUE;
535  if( !solnode[graph->tail[i]] )
536  {
537  solnode[graph->tail[i]] = TRUE;
538  nsolnodes++;
539  }
540  if( !solnode[graph->head[i]] )
541  {
542  solnode[graph->head[i]] = TRUE;
543  nsolnodes++;
544  }
545  break;
546  }
547  }
548  }
549  if( pcmw )
550  {
551  for( i = graph->outbeg[graph->source[0]]; i != EAT_LAST; i = graph->oeat[i] )
552  {
553  if( soledge[i / 2] == FALSE && Is_gterm(graph->term[graph->head[i]]) )
554  {
555  nsoledges++;
556  soledge[i / 2] = TRUE;
557  if( !solnode[graph->head[i]] && SCIPisEQ(scip, graph->cost[flipedge(i)], FARAWAY) )
558  {
559  solnode[graph->head[i]] = TRUE;
560  nsolnodes++;
561  }
562  assert(solnode[graph->head[i]]);
563  }
564  }
565  }
566 
567  if( graph->stp_type == GSTP )
568  {
569  for( k = 0; k < nnodes; k++ )
570  {
571  if( Is_term(graph->term[k]) )
572  {
573  assert(solnode[k]);
574  for( i = graph->outbeg[k]; i != EAT_LAST; i = graph->oeat[i] )
575  {
576  if( solnode[graph->head[i]] && !soledge[i / 2] )
577  {
578  soledge[i / 2] = TRUE;
579  nsoledges++;
580  }
581  }
582  }
583  }
584  }
585  /* initialize new graph */
586  SCIP_CALL( graph_init(scip, &newgraph, nsolnodes, 2 * nsoledges, 1, 0) );
587 
588  if( graph->stp_type == STP_GRID || graph->stp_type == STP_OBSTACLES_GRID )
589  newgraph->stp_type = STP_UNDIRECTED;
590  else
591  newgraph->stp_type = graph->stp_type;
592 
593  if( pcmw )
594  SCIP_CALL( SCIPallocMemoryArray(scip, &(newgraph->prize), nsolnodes) );
595 
596  newgraph->hoplimit = graph->hoplimit;
597  j = 0;
598  for( i = 0; i < nnodes; i++ )
599  {
600  if( solnode[i] )
601  {
602  if( pcmw )
603  {
604  if( (!Is_term(graph->term[i])) )
605  newgraph->prize[j] = graph->prize[i];
606  else
607  newgraph->prize[j] = 0.0;
608  }
609 
610  graph_knot_add(newgraph, graph->term[i]);
611  dnodemap[i] = j++;
612  }
613  }
614 
615  /* set root */
616  newgraph->source[0] = dnodemap[graph->source[0]];
617  if( newgraph->stp_type == STP_ROOTED_PRIZE_COLLECTING )
618  newgraph->prize[newgraph->source[0]] = FARAWAY;
619  assert(newgraph->source[0] >= 0);
620 
621  /* copy max degrees*/
622  if( graph->stp_type == STP_DEG_CONS )
623  {
624  SCIP_CALL( SCIPallocMemoryArray(scip, &(newgraph->maxdeg), nsolnodes) );
625  for( i = 0; i < nnodes; i++ )
626  if( solnode[i] )
627  newgraph->maxdeg[dnodemap[i]] = graph->maxdeg[i];
628  }
629  /* allocate memory */
630  SCIP_CALL( SCIPallocMemoryArray(scip, edgeancestor, 2 * nsoledges) );
631  SCIP_CALL( SCIPallocMemoryArray(scip, edgeweight, 2 * nsoledges) );
632 
633  for( i = 0; i < 2 * nsoledges; i++ )
634  (*edgeweight)[i] = 1;
635 
636  /* store original ID of each new edge (i.e. edge in the merged graph) */
637  j = 0;
638  for( i = 0; i < nedges; i += 2 )
639  {
640  if( soledge[i / 2] )
641  {
642  (*edgeancestor)[j++] = i;
643  (*edgeancestor)[j++] = i + 1;
644  graph_edge_add(scip, newgraph, dnodemap[graph->tail[i]], dnodemap[graph->head[i]], graph->cost[i], graph->cost[i + 1]);
645 
646  /* (*edgeweight)[e]: number of solutions containing edge e */
647  for( k = 0; k < heurdata->nselectedsols; k++ )
648  {
649  varsolval = SCIPgetSolVal(scip, sols[solselection[k]], vars[i]);
650  varrevsolval = SCIPgetSolVal(scip, sols[solselection[k]], vars[i + 1]);
651  if( SCIPisEQ(scip, varsolval, 1.0) || SCIPisEQ(scip, varrevsolval, 1.0) )
652  {
653  (*edgeweight)[j - 2]++;
654  (*edgeweight)[j - 1]++;
655  }
656  }
657  }
658  }
659  for( i = 0; i < 2 * nsoledges; i++ )
660  assert((*edgeweight)[i] >= 1);
661 
662 #if 0
663  int e;
664  for( i = 0; i < graph->knots; i++ )
665  if( !Is_term(graph->term[i]) && !Is_pterm(graph->term[i]) )
666  for( e = graph->inpbeg[i]; e != EAT_LAST; e = graph->ieat[e] )
667  if( !SCIPisEQ(scip, -graph->prize[i], graph->cost[e]) && !Is_term(graph->term[graph->tail[e]]) )
668  printf("org neq: %d %f %f termi: %d termtail %d \n", i, graph->prize[i], graph->cost[e], graph->term[i], graph->term[graph->tail[e]]);
669 
670  for( i = 0; i < nsolnodes; i++ )
671  if( !Is_term(newgraph->term[i]) && !Is_pterm(newgraph->term[i]) )
672  for( e = newgraph->inpbeg[i]; e != EAT_LAST; e = newgraph->ieat[e] )
673  if( !SCIPisEQ(scip, -newgraph->prize[i], newgraph->cost[e]) && !Is_term(newgraph->term[newgraph->tail[e]]) )
674  printf("neq: %d %f %f termi: %d termtail %d \n", i, newgraph->prize[i], newgraph->cost[e], newgraph->term[i], newgraph->term[newgraph->tail[e]]);
675 
676  for( i = 0; i < nsolnodes; i++ )
677  if( Is_pterm(newgraph->term[i]) )
678  for( e = newgraph->inpbeg[i]; e != EAT_LAST; e = newgraph->ieat[e] )
679  if( !SCIPisEQ(scip, 0.0, newgraph->cost[e]) && !Is_term(newgraph->term[newgraph->tail[e]]) )
680  printf("pterm neq: %d %f %f termi: %d termtail %d \n", i, newgraph->prize[i], newgraph->cost[e], newgraph->term[i], newgraph->term[newgraph->tail[e]]);
681 
682 #endif
683  assert(j == 2 * nsoledges);
684  }
685 
686  /* free memory */
687  SCIPfreeBufferArray(scip, &soledge);
688  SCIPfreeBufferArray(scip, &dnodemap);
689  SCIPfreeBufferArray(scip, &solnode);
690  SCIPfreeBufferArray(scip, &solselection);
691  *solgraph = newgraph;
692  return SCIP_OKAY;
693 }
694 
695 /*
696  * Callback methods of primal heuristic
697  */
698 
699 
700 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
701 static
702 SCIP_DECL_HEURCOPY(heurCopyRec)
703 { /*lint --e{715}*/
704  assert(scip != NULL);
705  assert(heur != NULL);
706  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
707 
708  /* call inclusion method of primal heuristic */
709  SCIP_CALL( SCIPincludeHeurRec(scip) );
710 
711  return SCIP_OKAY;
712 }
713 
714 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
715 static
716 SCIP_DECL_HEURFREE(heurFreeRec)
717 { /*lint --e{715}*/
718  SCIP_HEURDATA* heurdata;
719 
720  assert(heur != NULL);
721  assert(scip != NULL);
722 
723  /* get heuristic data */
724  heurdata = SCIPheurGetData(heur);
725  assert(heurdata != NULL);
726 
727  /* free heuristic data */
728  SCIPfreeMemory(scip, &heurdata);
729  SCIPheurSetData(heur, NULL);
730 
731  return SCIP_OKAY;
732 }
733 
734 /** initialization method of primal heuristic (called after problem was transformed) */
735 static
736 SCIP_DECL_HEURINIT(heurInitRec)
737 { /*lint --e{715}*/
738  SCIP_HEURDATA* heurdata;
739 
740  assert(heur != NULL);
741  assert(scip != NULL);
742 
743  /* get heuristic's data */
744  heurdata = SCIPheurGetData(heur);
745  assert(heurdata != NULL);
746 
747  /* initialize data */
748  heurdata->nselectedsols = 0;
749  heurdata->ncalls = 0;
750  heurdata->ntmruns = 100;
751  heurdata->nlastsols = 0;
752  heurdata->lastsolindex = -1;
753  heurdata->bestsolindex = -1;
754  heurdata->nfailures = 0;
755 
756 #ifdef WITH_UG
757  heurdata->randseed += getUgRank();
758 #else
759  heurdata->randseed = 0;
760 #endif
761 
762  return SCIP_OKAY;
763 }
764 
765 /** execution method of primal heuristic */
766 static
767 SCIP_DECL_HEUREXEC(heurExecRec)
768 { /*lint --e{715}*/
769  SCIP_HEURDATA* heurdata;
770  SCIP_HEURDATA* tmheurdata;
771  SCIP_PROBDATA* probdata;
772  SCIP_VAR** vars;
773  SCIP_SOL** sols;
774  GRAPH* graph;
775  GRAPH* solgraph;
776  GRAPH* psolgraph;
777  SCIP_SOL* sol;
778  SCIP_SOL* newsol;
779  SCIP_SOL* bestsol;
780  SCIP_Real* nval;
781  SCIP_Real* cost = NULL;
782  SCIP_Real* costrev = NULL;
783  SCIP_Real* nodepriority = NULL;
784  SCIP_Real pobj;
785  SCIP_Real avg;
786  SCIP_Real maxcost = 0.0;
787  SCIP_Real hopfactor = 0.1;
788  SCIP_Longint nsols;
789  SCIP_Bool pcmw;
790  SCIP_Bool success;
791  SCIP_Bool fixed;
792  SCIP_Bool randomize;
793  SCIP_Bool modcost;
794  SCIP_Bool solfound;
795  IDX* curr;
796  IDX** ancestors;
797  int i;
798  int e;
799  int v;
800  int head;
801  int tail;
802  int runs;
803  int count;
804  int solindex;
805  int nedges;
806  int nnodes;
807  int probtype;
808  int nsoledges;
809  int best_start;
810  int lastsolindex;
811  int* perm;
812  int* results;
813  int* edgeweight;
814  int* orgresults;
815  int* edgeancestor;
816  char* stnodes;
817 
818  assert(heur != NULL);
819  assert(scip != NULL);
820  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
821  assert(result != NULL);
822 
823  /* get heuristic data */
824  heurdata = SCIPheurGetData(heur);
825  assert(heurdata != NULL);
826 
827  /* get problem data */
828  probdata = SCIPgetProbData(scip);
829  assert(probdata != NULL);
830 
831  /* get graph */
832  graph = SCIPprobdataGetGraph(probdata);
833  assert(graph != NULL);
834 
835  probtype = graph->stp_type;
836  *result = SCIP_DIDNOTRUN;
837 
838  if( probtype == STP_MAX_NODE_WEIGHT )
839  return SCIP_OKAY;
840 
841  pcmw = (probtype == STP_PRIZE_COLLECTING || probtype == STP_MAX_NODE_WEIGHT || probtype == STP_ROOTED_PRIZE_COLLECTING);
842  nsols = SCIPgetNSolsFound(scip);
843 
844  /* only call heuristic, if sufficiently many solutions are available */
845  if( (SCIPgetNSols(scip) < DEFAULT_NUSEDSOLS) || (SCIPgetNSols(scip) < DEFAULT_NUSEDSOLS + 1 && !pcmw) )
846  return SCIP_OKAY;
847 
848  /* suspend heuristic? */
849  if( pcmw || probtype == STP_HOP_CONS || probtype == STP_DEG_CONS )
850  {
851  if( heurdata->ncalls == 0 )
852  i = 0;
853  else if( heurdata->maxfreq )
854  i = 1;
855  else if( probtype == STP_ROOTED_PRIZE_COLLECTING || probtype == STP_DEG_CONS )
856  i = MIN(heurdata->nwaitingsols, 2 * heurdata->nfailures);
857  else
858  i = MIN(heurdata->nwaitingsols, heurdata->nfailures);
859 
860  if( nsols <= heurdata->nlastsols + i )
861  return SCIP_OKAY;
862  }
863  else
864  {
865  if( heurdata->maxfreq )
866  i = 1;
867  else
868  i = MIN(heurdata->nwaitingsols, heurdata->nfailures);
869 
870  if( nsols <= heurdata->nlastsols + i && heurdata->bestsolindex == SCIPsolGetIndex(SCIPgetBestSol(scip)) )
871  return SCIP_OKAY;
872  }
873 
874  /* get edge variables */
875  vars = SCIPprobdataGetVars(scip);
876  assert(vars != NULL);
877  assert(vars[0] != NULL);
878 
879  nedges = graph->edges;
880  nnodes = graph->knots;
881  bestsol = SCIPgetBestSol(scip);
882  results = NULL;
883  randomize = TRUE;
884 
885  heurdata->ncalls++;
886 
887  if( pcmw || probtype == STP_HOP_CONS )
888  runs = 8;
889  else
890  runs = 8;
891 
892  /* allocate memory */
893  SCIP_CALL( SCIPallocBufferArray(scip, &perm, runs) );
894  SCIP_CALL( SCIPallocBufferArray(scip, &nval, nedges) );
895  SCIP_CALL( SCIPallocBufferArray(scip, &orgresults, nedges) );
896 
897  for( v = 0; v < runs; v++ )
898  perm[v] = v;
899 
900  if( probtype == STP_MAX_NODE_WEIGHT || probtype == STP_HOP_CONS || probtype == STP_DEG_CONS )
901  {
902  newsol = (SCIPgetSols(scip))[0];
903  }
904  /* first run? */
905  else if( heurdata->lastsolindex == -1 )
906  {
907  newsol = (SCIPgetSols(scip))[SCIPgetRandomInt(0, heurdata->nusedsols - 1, &(heurdata->randseed))];
908  }
909  else
910  {
911  newsol = NULL;
912  }
913 
914  /* save last solution index */
915  solindex = 0;
916  nsols = SCIPgetNSols(scip);
917  assert(nsols > 0);
918  sols = SCIPgetSols(scip);
919  for( i = 1; i < nsols; i++ )
920  if( SCIPisGT(scip, SCIPgetSolTime(scip, sols[i]), SCIPgetSolTime(scip, sols[solindex])) )
921  solindex = i;
922 
923  lastsolindex = SCIPsolGetIndex(sols[solindex]);
924 
925  count = 0;
926 
927  if( SCIPgetRandomInt(0, 10, &(heurdata->randseed)) == 1 )
928  modcost = FALSE;
929  else
930  modcost = TRUE;
931 
932  solfound = FALSE;
933  for( v = 0; v < 5 * runs && !SCIPisStopped(scip); v++ )
934  {
935  if( count >= runs )
936  {
937  if( solfound )
938  {
939  count = 0;
940  solfound = FALSE;
941  }
942  else
943  {
944  break;
945  }
946  }
947  if( perm[count] <= 1 )
948  {
949  heurdata->nusedsols = 2;
950  if( SCIPgetRandomInt(0, 1, &(heurdata->randseed)) == 1 )
951  randomize = TRUE;
952  else
953  randomize = FALSE;
954  }
955  else if( perm[count] <= 4 )
956  {
957  if( SCIPgetRandomInt(0, 1, &(heurdata->randseed)) == 1 )
958  randomize = TRUE;
959  else
960  randomize = FALSE;
961  heurdata->nusedsols = DEFAULT_NUSEDSOLS - 1 ;
962  }
963  else if( perm[count] <= 6 || pcmw )
964  {
965  heurdata->nusedsols = DEFAULT_NUSEDSOLS;
966  }
967  else if( perm[count] <= 7 )
968  {
969  heurdata->nusedsols = DEFAULT_NUSEDSOLS + 1;
970  }
971 
972  /* build up a new graph, consisting of several solutions */
973  SCIP_CALL( buildsolgraph(scip, heurdata, &newsol, graph, &solgraph, &edgeancestor, &edgeweight, &success, randomize) );
974 
975  if( success )
976  {
977  assert(newsol != NULL);
978 
979  /* get TM heuristic data */
980  assert(SCIPfindHeur(scip, "TM") != NULL);
981  tmheurdata = SCIPheurGetData(SCIPfindHeur(scip, "TM"));
982 
983  /* presolve new graph */
984 
985  /* reduce new graph */
986  if( probtype == STP_ROOTED_PRIZE_COLLECTING || probtype == STP_HOP_CONS || probtype == STP_DEG_CONS || probtype == STP_MAX_NODE_WEIGHT )
987  SCIP_CALL( reduce(scip, &solgraph, &pobj, 0, 2) );
988  else
989  SCIP_CALL( reduce(scip, &solgraph, &pobj, 1, 10) );
990 
991  SCIP_CALL( graph_pack(scip, solgraph, &psolgraph, FALSE) );
992  solgraph = psolgraph;
993  assert(graph_valid(solgraph));
994  ancestors = solgraph->ancestors;
995  nsoledges = solgraph->edges;
996 
997  /* if graph reduction solved the whole problem, solgraph has only one node */
998  if( solgraph->terms > 1 )
999  {
1000  /* edge multiplier */
1001  SCIP_Real mult;
1002 
1003  /* allocate memory */
1004  SCIP_CALL( SCIPallocBufferArray(scip, &results, nsoledges) );
1005  SCIP_CALL( SCIPallocBufferArray(scip, &cost, nsoledges) );
1006  SCIP_CALL( SCIPallocBufferArray(scip, &costrev, nsoledges) );
1007  SCIP_CALL( SCIPallocBufferArray(scip, &nodepriority, solgraph->knots) );
1008 
1009  for( i = 0; i < solgraph->knots; i++ )
1010  nodepriority[i] = 0.0;
1011 
1012  /* copy edge costs */
1013  BMScopyMemoryArray(cost, solgraph->cost, nsoledges);
1014 
1015  maxcost = 0.0;
1016  for( e = 0; e < nsoledges; e++ )
1017  {
1018  curr = ancestors[e];
1019  avg = 0.0;
1020  i = 0;
1021  fixed = FALSE;
1022  if( curr != NULL )
1023  {
1024  while( curr != NULL )
1025  {
1026  i++;
1027  avg += edgeweight[curr->index];
1028  if( SCIPvarGetUbGlobal(vars[edgeancestor[curr->index]] ) < 0.5 )
1029  fixed = TRUE;
1030 
1031  curr = curr->parent;
1032  }
1033  avg = (double) avg / (double) i;
1034  assert(avg >= 1);
1035  }
1036  /* is an ancestor edge fixed? */
1037  if( fixed )
1038  {
1039  cost[e] = BLOCKED;
1040  }
1041  else
1042  {
1043  nodepriority[solgraph->head[e]] += avg - 1.0;
1044  nodepriority[solgraph->tail[e]] += avg - 1.0;
1045  if( modcost )
1046  {
1047  mult = costMultiplier(scip, heurdata, avg);
1048  cost[e] = cost[e] * mult;
1049  }
1050  }
1051 
1052  if( probtype == STP_HOP_CONS && SCIPisLT(scip, cost[e], BLOCKED) && SCIPisGT(scip, cost[e], maxcost) )
1053  maxcost = cost[e];
1054  }
1055 
1056  for( e = 0; e < nsoledges; e++ )
1057  {
1058  costrev[e] = cost[flipedge(e)];
1059  results[e] = UNKNOWN;
1060  }
1061 
1062  /* init shortest path algorithm */
1063  SCIP_CALL( graph_path_init(scip, solgraph) );
1064 
1065  /* run TM heuristic */
1066  SCIP_CALL( SCIPheurComputeSteinerTree(scip, tmheurdata, solgraph, NULL, &best_start, results, heurdata->ntmruns,
1067  solgraph->source[0], cost, costrev, &hopfactor, nodepriority, maxcost, &success) );
1068 
1069  if( !success )
1070  {
1071  SCIPdebugMessage("failed to build tree\n");
1072  graph_path_exit(scip, solgraph);
1073  SCIPfreeBufferArrayNull(scip, &nodepriority);
1074  SCIPfreeBufferArrayNull(scip, &costrev);
1075  SCIPfreeBufferArrayNull(scip, &cost);
1076  SCIPfreeBufferArrayNull(scip, &results);
1077  SCIPfreeMemoryArray(scip, &edgeancestor);
1078  SCIPfreeMemoryArray(scip, &edgeweight);
1079  graph_free(scip, solgraph, TRUE);
1080  continue;
1081  }
1082 
1083  assert(graph_valid(solgraph));
1084  assert(graph_sol_valid(scip, solgraph, results));
1085 
1086  /* run local heuristic */
1087  if( solgraph->stp_type != STP_HOP_CONS && probtype != STP_DEG_CONS && solgraph->stp_type != STP_MAX_NODE_WEIGHT )
1088  SCIP_CALL( SCIPheurImproveSteinerTree(scip, solgraph, cost, costrev, results) );
1089 
1090  if( probtype == STP_UNDIRECTED )
1091  assert(graph_sol_valid(scip, solgraph, results));
1092 
1093  graph_path_exit(scip, solgraph);
1094  }
1095 
1096  for( i = 0; i < nedges; i++ )
1097  orgresults[i] = UNKNOWN;
1098 
1099  /* allocate memory */
1100  SCIP_CALL( SCIPallocBufferArray(scip, &stnodes, nedges) );
1101 
1102  for( i = 0; i < nnodes; i++ )
1103  stnodes[i] = FALSE;
1104 
1105  /* retransform solution found by TM heuristic */
1106  if( solgraph->terms > 1 )
1107  {
1108  assert(results != NULL);
1109  for( e = 0; e < nsoledges; e++ )
1110  {
1111  if( results[e] == CONNECT )
1112  {
1113  /* iterate through list of ancestors */
1114  curr = ancestors[e];
1115  while( curr != NULL )
1116  {
1117  i = edgeancestor[curr->index];
1118  if( probtype == STP_DEG_CONS )
1119  orgresults[i] = CONNECT;
1120  head = graph->head[i];
1121  tail = graph->tail[i];
1122  stnodes[tail] = TRUE;
1123  stnodes[head] = TRUE;
1124  curr = curr->parent;
1125  }
1126  }
1127  }
1128  }
1129 
1130  /* retransform edges fixed during graph reduction */
1131  curr = solgraph->fixedges;
1132  while( curr != NULL )
1133  {
1134  i = edgeancestor[curr->index];
1135  if( probtype == STP_DEG_CONS )
1136  orgresults[i] = CONNECT;
1137  head = graph->head[i];
1138  tail = graph->tail[i];
1139  stnodes[tail] = TRUE;
1140  stnodes[head] = TRUE;
1141  curr = curr->parent;
1142  }
1143  /* prune solution (in the original graph) */
1144  if( pcmw )
1145  SCIP_CALL( SCIPheurPrunePCSteinerTree(scip, graph, graph->cost, orgresults, stnodes) );
1146  else if( probtype == STP_DEG_CONS )
1147  SCIP_CALL( SCIPheurPruneDegConsSteinerTree(scip, graph, orgresults, stnodes) );
1148  else
1149  SCIP_CALL( SCIPheurPruneSteinerTree(scip, graph, graph->cost, 0, orgresults, stnodes) );
1150 
1151  SCIPfreeBufferArray(scip, &stnodes);
1152  pobj = 0.0;
1153 
1154  for( e = 0; e < graph->edges; e++ )
1155  {
1156  if( orgresults[e] == CONNECT )
1157  {
1158  nval[e] = 1.0;
1159  pobj += graph->cost[e];
1160  }
1161  else
1162  {
1163  nval[e] = 0.0;
1164  }
1165  }
1166 
1167  if( SCIPisGT(scip, SCIPgetSolOrigObj(scip, newsol) - SCIPprobdataGetOffset(scip), pobj) )
1168  {
1169  SCIPdebugMessage("better solution found ... ");
1170  sol = NULL;
1171  SCIP_CALL( SCIPprobdataAddNewSol(scip, nval, sol, heur, &success) );
1172 
1173  if( success )
1174  {
1175  SCIPdebugMessage("and added! \n");
1176  *result = SCIP_FOUNDSOL;
1177  solfound = TRUE;
1178  nsols = SCIPgetNSols(scip);
1179  assert(nsols > 0);
1180  sols = SCIPgetSols(scip);
1181  solindex = 0;
1182  for( i = 1; i < nsols; i++ )
1183  if( SCIPisGT(scip, SCIPgetSolTime(scip, sols[i]), SCIPgetSolTime(scip, sols[solindex])) )
1184  solindex = i;
1185  newsol = sols[solindex];
1186  assert(graph_sol_valid(scip, graph, orgresults));
1187 
1188  if( SCIPisGT(scip, SCIPgetSolOrigObj(scip, bestsol) - SCIPprobdataGetOffset(scip), pobj) )
1189  heurdata->nfailures = 0;
1190  }
1191  else
1192  {
1193  count++;
1194  }
1195  }
1196  else
1197  {
1198  count++;
1199  }
1200 
1201  /* free memory */
1202  SCIPfreeBufferArrayNull(scip, &nodepriority);
1203  SCIPfreeBufferArrayNull(scip, &costrev);
1204  SCIPfreeBufferArrayNull(scip, &cost);
1205  SCIPfreeBufferArrayNull(scip, &results);
1206 
1207  SCIPfreeMemoryArray(scip, &edgeancestor);
1208  SCIPfreeMemoryArray(scip, &edgeweight);
1209  graph_free(scip, solgraph, TRUE);
1210  }
1211  else
1212  {
1213  count++;
1214  }
1215  }
1216 
1217  if( *result != SCIP_FOUNDSOL )
1218  heurdata->nfailures++;
1219 
1220  heurdata->lastsolindex = lastsolindex;
1221  heurdata->bestsolindex = SCIPsolGetIndex(SCIPgetBestSol(scip));
1222  heurdata->nlastsols = SCIPgetNSolsFound(scip);
1223  SCIPfreeBufferArray(scip, &orgresults);
1224  SCIPfreeBufferArray(scip, &nval);
1225  SCIPfreeBufferArray(scip, &perm);
1226 
1227  return SCIP_OKAY;
1228 }
1229 
1230 
1231 /*
1232  * primal heuristic specific interface methods
1233  */
1234 
1235 /** creates the rec primal heuristic and includes it in SCIP */
1236 SCIP_RETCODE SCIPincludeHeurRec(
1237  SCIP* scip /**< SCIP data structure */
1238  )
1239 {
1240  SCIP_HEURDATA* heurdata;
1241  SCIP_HEUR* heur;
1242 
1243  /* create Rec primal heuristic data */
1244  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1245 
1246  /* include primal heuristic */
1247  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1249  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRec, heurdata) );
1250 
1251  assert(heur != NULL);
1252 
1253  /* set non-NULL pointers to callback methods */
1254  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRec) );
1255  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRec) );
1256  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRec) );
1257 
1258  /* add rec primal heuristic parameters */
1259  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/nwaitingsols",
1260  "number of solution findings to be in abeyance",
1261  &heurdata->nwaitingsols, FALSE, DEFAULT_NWAITINGSOLS, 1, INT_MAX, NULL, NULL) );
1262 
1263  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/randseed",
1264  "random seed for heuristic",
1265  NULL, FALSE, DEFAULT_RANDSEED, 0, INT_MAX, paramChgdRandomseed, (SCIP_PARAMDATA*)heurdata) );
1266 
1267  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/maxnsols",
1268  "max size of solution pool for heuristic",
1269  &heurdata->maxnsols, FALSE, DEFAULT_MAXNSOLS, 5, INT_MAX, NULL, NULL) );
1270 
1271  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/ntmruns",
1272  "number of runs in TM",
1273  &heurdata->ntmruns, FALSE, DEFAULT_NTMRUNS, 1, INT_MAX, NULL, NULL) );
1274 
1275  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/"HEUR_NAME"/maxfreq",
1276  "should the heuristic be executed at maximum frequeny?",
1277  &heurdata->maxfreq, FALSE, DEFAULT_MAXFREQREC, NULL, NULL) );
1278 
1279  heurdata->nusedsols = DEFAULT_NUSEDSOLS;
1280 
1281  return SCIP_OKAY;
1282 }
SCIP_RETCODE graph_path_init(SCIP *, GRAPH *)
Definition: grphpath.c:407
#define Is_term(a)
Definition: grph.h:158
SCIP_RETCODE SCIPheurPruneSteinerTree(SCIP *scip, const GRAPH *g, SCIP_Real *cost, int layer, int *result, char *connected)
Definition: heur_tm.c:381
SCIP_RETCODE SCIPheurPrunePCSteinerTree(SCIP *scip, const GRAPH *g, SCIP_Real *cost, int *result, char *connected)
Definition: heur_tm.c:197
int graph_valid(const GRAPH *)
Definition: grphbase.c:2532
#define HEUR_FREQ
Definition: heur_rec.c:48
Definition: grph.h:55
#define TRUE
Definition: portab.h:34
int nwaitingsols
Definition: heur_rec.c:82
Constraint handler for Steiner problems.
SCIP_Longint ncalls
Definition: heur_rec.c:77
static SCIP_RETCODE selectsols(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL **newsol, int *selection, SCIP_Bool randomize)
Definition: heur_rec.c:329
int terms
Definition: grph.h:63
SCIP_VAR ** SCIPprobdataGetVars(SCIP *scip)
#define DEFAULT_NTMRUNS
Definition: heur_rec.c:58
int lastsolindex
Definition: heur_rec.c:74
#define STP_HOP_CONS
Definition: grph.h:48
#define EAT_LAST
Definition: grph.h:31
#define GSTP
Definition: grph.h:49
#define BLOCKED
Definition: grph.h:150
#define HEUR_PRIORITY
Definition: heur_rec.c:47
static SCIP_DECL_PARAMCHGD(paramChgdRandomseed)
Definition: heur_rec.c:95
SCIP_RETCODE SCIPheurPruneDegConsSteinerTree(SCIP *scip, const GRAPH *g, int *result, char *connected)
Definition: heur_tm.c:527
static SCIP_DECL_HEURCOPY(heurCopyRec)
Definition: heur_rec.c:702
Problem data for stp problem.
void graph_path_exit(SCIP *, GRAPH *)
Definition: grphpath.c:429
int nfailures
Definition: heur_rec.c:83
int * oeat
Definition: grph.h:100
void graph_free(SCIP *, GRAPH *, SCIP_Bool)
Definition: grphbase.c:1137
static SCIP_Real costMultiplier(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real avg)
Definition: heur_rec.c:112
#define STP_GRID
Definition: grph.h:45
SCIP_RETCODE SCIPincludeHeurRec(SCIP *scip)
Definition: heur_rec.c:1236
static SCIP_DECL_HEUREXEC(heurExecRec)
Definition: heur_rec.c:767
GRAPH * SCIPprobdataGetGraph(SCIP_PROBDATA *probdata)
#define DEFAULT_MAXNSOLS
Definition: heur_rec.c:55
int * head
Definition: grph.h:94
IDX * fixedges
Definition: grph.h:82
#define STP_OBSTACLES_GRID
Definition: grph.h:46
#define FALSE
Definition: portab.h:37
static SCIP_RETCODE buildsolgraph(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL **newsol, GRAPH *graph, GRAPH **solgraph, int **edgeancestor, int **edgeweight, SCIP_Bool *success, SCIP_Bool randomize)
Definition: heur_rec.c:451
SCIP_RETCODE graph_pack(SCIP *, GRAPH *, GRAPH **, SCIP_Bool)
Definition: grphbase.c:2342
#define CONNECT
Definition: grph.h:147
int stp_type
Definition: grph.h:123
IDX ** ancestors
Definition: grph.h:83
int * outbeg
Definition: grph.h:77
#define Is_pterm(a)
Definition: grph.h:159
SCIP_Real hopfactor
Definition: heur_tm.c:79
#define HEUR_FREQOFS
Definition: heur_rec.c:49
SCIP_RETCODE SCIPprobdataAddNewSol(SCIP *scip, SCIP_Real *nval, SCIP_SOL *sol, SCIP_HEUR *heur, SCIP_Bool *success)
SCIP_Real SCIPprobdataGetOffset(SCIP *scip)
SCIP_Real * prize
Definition: grph.h:92
int bestsolindex
Definition: heur_rec.c:75
int * maxdeg
Definition: grph.h:79
int * tail
Definition: grph.h:93
SCIP_RETCODE SCIPheurComputeSteinerTree(SCIP *scip, SCIP_HEURDATA *heurdata, const 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)
Definition: heur_tm.c:1419
SCIP_RETCODE reduce(SCIP *, GRAPH **, SCIP_Real *, int, int)
Definition: reduce.c:1886
int * term
Definition: grph.h:69
int knots
Definition: grph.h:61
#define STP_MAX_NODE_WEIGHT
Definition: grph.h:47
#define DEFAULT_NUSEDSOLS
Definition: heur_rec.c:56
SCIP_RETCODE SCIPheurImproveSteinerTree(SCIP *scip, GRAPH *graph, SCIP_Real *cost, SCIP_Real *costrev, int *best_result)
Definition: heur_local.c:282
#define STP_DEG_CONS
Definition: grph.h:43
Improvement heuristic for Steiner problems.
#define Is_gterm(a)
Definition: grph.h:160
int * inpbeg
Definition: grph.h:75
#define FARAWAY
Definition: grph.h:149
static SCIP_DECL_HEURFREE(heurFreeRec)
Definition: heur_rec.c:716
static SCIP_DECL_HEURINIT(heurInitRec)
Definition: heur_rec.c:736
SCIP_Bool graph_sol_valid(SCIP *, const GRAPH *, int *)
Definition: grphbase.c:2639
#define DEFAULT_NWAITINGSOLS
Definition: heur_rec.c:59
int nusedsols
Definition: heur_rec.c:80
int nselectedsols
Definition: heur_rec.c:81
SCIP_Bool maxfreq
Definition: heur_local.c:68
SCIP_VAR ** SCIPprobdataGetEdgeVars(SCIP *scip)
#define HEUR_USESSUBSCIP
Definition: heur_rec.c:52
#define HEUR_DESC
Definition: heur_rec.c:45
#define UNKNOWN
Definition: grph.h:148
#define DEFAULT_MAXFREQREC
Definition: heur_rec.c:54
static SCIP_RETCODE selectdiffsols(SCIP *scip, GRAPH *graph, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, SCIP_SOL **newsol, int *selection, SCIP_Bool *success)
Definition: heur_rec.c:170
#define STP_PRIZE_COLLECTING
Definition: grph.h:40
SCIP_RETCODE graph_init(SCIP *, GRAPH **, int, int, int, int)
Definition: grphbase.c:44
#define HEUR_DISPCHAR
Definition: heur_rec.c:46
#define DEFAULT_RANDSEED
Definition: heur_rec.c:57
includes various files containing graph methods used for Steiner problems
#define HEUR_MAXDEPTH
Definition: heur_rec.c:50
SCIP_Real * cost
Definition: grph.h:91
#define STP_ROOTED_PRIZE_COLLECTING
Definition: grph.h:41
int * source
Definition: grph.h:67
Primal recombination heuristic for Steiner problems.
shortest paths based primal heuristics for Steiner problems
int edges
Definition: grph.h:89
#define flipedge(edge)
Definition: grph.h:143
void graph_knot_add(GRAPH *, int)
Definition: grphbase.c:1362
int * ieat
Definition: grph.h:99
SCIP_Longint nlastsols
Definition: heur_rec.c:78
#define STP_UNDIRECTED
Definition: grph.h:38
struct Int_List_Node * parent
Definition: misc_stp.h:69
int hoplimit
Definition: grph.h:86
void graph_edge_add(SCIP *, GRAPH *, int, int, double, double)
unsigned int randseed
Definition: heur_rec.c:84
#define HEUR_TIMING
Definition: heur_rec.c:51
#define HEUR_NAME
Definition: heur_rec.c:44