Scippy

SCIP

Solving Constraint Integer Programs

dpborder_util.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-2022 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 dpborder_util.c
17  * @brief Utility methods for dynamic programming solver for Steiner tree (sub-) problems with small border
18  * @author Daniel Rehfeldt
19  *
20  * Implements utility methods.
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 //#define SCIP_DEBUG
25 #include "dpborder.h"
26 #include "dpborderinterns.h"
27 
28 /*
29  * Local methods
30  */
31 
32 #ifndef NDEBUG
33 static
35  const DPBORDER* dpborder, /**< border */
36  const DPB_Ptype* partition, /**< array of size 'size' */
37  int size /**< size */
38 )
39 {
40  const int levelstart = dpborder_getTopLevel(dpborder)->globalstartidx;
41  const int levelend = dpborder->global_npartitions - 1;
42 
43  assert(levelstart <= levelend);
44 
45  for( int i = levelstart; i != levelend; i++ )
46  {
47  const int start = dpborder->global_partstarts[i];
48  const int end = dpborder->global_partstarts[i + 1];
49  assert(start < end);
50 
51  if( size != end - start )
52  continue;
53 
54  if( memcmp(partition, &(dpborder->global_partitions[start]), size) == 0 )
55  {
56  SCIPdebugMessage("included at pos=%d \n", i);
57  return TRUE;
58  }
59  }
60 
61  return FALSE;
62 }
63 
64 
65 
66 /** fully sorted? */
67 static
69  const DPB_Ptype* partition, /**< array of size 'size' with delimiter at [size] */
70  DPB_Ptype delimiter, /**< delimiter */
71  int size /**< size */
72 )
73 {
74  int nsubsets = 0;
75  int substarts[BPBORDER_MAXBORDERSIZE + 1];
76 
77  assert(size > 0);
78  assert(partition[size] == delimiter);
79 
80  substarts[0] = 0;
81 
82  for( int iter = 1; iter < size; iter++ )
83  {
84  if( partition[iter - 1] == delimiter )
85  {
86  substarts[++nsubsets] = iter;
87  continue;
88  }
89 
90  if( partition[iter - 1] >= partition[iter] )
91  {
92  SCIPdebugMessage("unsorted subset \n");
93  return FALSE;
94  }
95  }
96  substarts[++nsubsets] = size + 1;
97 
98  for( int iter = 1; iter < nsubsets; iter++ )
99  {
100  const int start_curr = substarts[iter];
101  const int start_prev = substarts[iter - 1];
102  const int start_next = substarts[iter + 1];
103 
104  assert(start_prev < start_curr && start_curr < start_next);
105 
106  if( (start_curr - start_prev) < (start_next - start_curr) )
107  continue;
108 
109  if( (start_curr - start_prev) > (start_next - start_curr) )
110  {
111  SCIPdebugMessage("wrongly ordered sizes \n");
112  return FALSE;
113  }
114 
115  if( memcmp(&partition[start_prev], &partition[start_curr], start_curr - start_prev) >= 0 )
116  {
117  SCIPdebugMessage("wrongly ordered substrings \n");
118  return FALSE;
119  }
120  }
121 
122  return TRUE;
123 }
124 #endif
125 
126 
127 /** sorts all subsets
128  * NOTE: partition needs to have allocated entry [-1] and [size] */
129 static inline
131  DPB_Ptype* RESTRICT partition, /**< array of size 'size' */
132  DPB_Ptype delimiter, /**< delimiter */
133  int size /**< size */
134 )
135 {
136  int nsubsets = 0;
137  int dummy[BPBORDER_MAXBORDERSIZE + 1];
138  DPB_Ptype subbuffer[BPBORDER_MAXBORDERSIZE + 1];
139  int* subsizes = &dummy[1];
140  assert(size >= 1);
141 
142  /* sentinel */
143  dummy[0] = 0;
144 
145  for( int iter = 0; iter < size; iter++ )
146  {
147  int iter2;
148  for( iter2 = iter + 1; iter2 < size; iter2++ )
149  {
150  if( partition[iter2] == delimiter )
151  break;
152  }
153 
154  subsizes[nsubsets++] = (iter2 - iter) + 1;
155 
156  /* sentinel */
157  for( int i = iter + 1; i < iter2; i++ )
158  {
159  int j;
160  const DPB_Ptype curr = partition[i];
161 
162  for( j = i - 1; curr < partition[j] && j >= 0; j-- )
163  {
164  assert(j >= 0);
165  partition[j + 1] = partition[j];
166  }
167  partition[j + 1] = curr;
168  }
169 
170  iter = iter2;
171  }
172 
173 #ifndef NDEBUG
174  for( int iter = 1; iter < size; iter++ )
175  {
176  if( partition[iter - 1] == delimiter )
177  continue;
178 
179  assert(partition[iter - 1] < partition[iter]);
180  }
181 #endif
182 
183  assert(nsubsets >= 1);
184 
185  // todo extra method
186 
187  /* add delimiter so that each subset ends with a delimiter */
188  partition[size] = delimiter;
189 
190  for( int i = 1, curr_pos = subsizes[0]; i < nsubsets; i++ )
191  {
192  const int curr_size = subsizes[i];
193  int j;
194  int j_pos;
195  assert(curr_size > 0);
196 
197  memcpy(subbuffer, &partition[curr_pos], curr_size * sizeof(partition[0]));
198 
199  for( j = i - 1, j_pos = curr_pos - subsizes[i - 1];
200  curr_size < subsizes[j] ||
201  (curr_size == subsizes[j] && memcmp(&partition[curr_pos], &partition[j_pos], curr_size) < 0 );
202  j-- )
203  {
204  assert(j >= 0 && j_pos >= 0);
205  j_pos -= subsizes[j - 1];
206  subsizes[j + 1] = subsizes[j];
207  }
208  j_pos += subsizes[j];
209  memmove(&partition[j_pos + curr_size], &partition[j_pos], (curr_pos - j_pos) * sizeof(partition[0]));
210  memcpy(&partition[j_pos], subbuffer, curr_size * sizeof(partition[0]));
211  subsizes[j + 1] = curr_size;
212  curr_pos += curr_size;
213  }
214 
215  assert(partition[size] == delimiter);
216  assert(partitionIsSorted(partition, delimiter, size));
217 }
218 
219 
220 /*
221  * Interface methods
222  */
223 
224 
225 /** is partition valid? */
227  const DPBPART* borderpartition /**< partition */
228 )
229 {
230  const DPB_Ptype* const partitionchars = borderpartition->partchars;
231  const DPB_Ptype delimiter = borderpartition->delimiter;
232  const int partsize = borderpartition->partsize;
233 
234  assert(partsize > 0);
235 
236  if( partitionchars[0] == delimiter )
237  {
238  SCIPdebugMessage("partition starts with delimiter\n");
239  return FALSE;
240  }
241 
242  if( partitionchars[partsize - 1] == delimiter )
243  {
244  SCIPdebugMessage("partition ends with delimiter\n");
245  return FALSE;
246  }
247 
248  for( int i = 1; i < partsize; i++ )
249  {
250  if( partitionchars[i] == delimiter && partitionchars[i - 1] == delimiter )
251  {
252  SCIPdebugMessage("empty subset at %d %d \n", i - 1, i);
253  return FALSE;
254  }
255  }
256 
257  for( int i = 0; i < partsize; i++ )
258  {
259  const DPB_Ptype borderchar = partitionchars[i];
260  if( borderchar > delimiter )
261  {
262  SCIPdebugMessage("char %d to large \n", i);
263  return FALSE;
264  }
265 
266  if( borderchar == delimiter )
267  continue;
268 
269  for( int j = 0; j < partsize; j++ )
270  {
271  const DPB_Ptype borderchar2 = partitionchars[j];
272 
273  if( i != j && borderchar == borderchar2 )
274  {
275  SCIPdebugMessage("duplicate char, positions %d %d \n", i, j);
276  return FALSE;
277  }
278  }
279  }
280 
281  return TRUE;
282 }
283 
284 
285 /** prints partition */
287  const DPBPART* borderpartition /**< partition */
288 )
289 {
290  const DPB_Ptype* const partitionchars = borderpartition->partchars;
291  const DPB_Ptype delimiter = borderpartition->delimiter;
292  const int partsize = borderpartition->partsize;
293 
294  for( int i = 0; i < partsize; i++ )
295  {
296  const DPB_Ptype borderchar = partitionchars[i];
297 
298  if( borderchar == delimiter )
299  {
300  printf("X ");
301  continue;
302  }
303 
304  printf("%d ", borderchar);
305  }
306 
307  printf(" \n");
308 
309  assert(dpborder_partIsValid(borderpartition));
310 }
311 
312 
313 /** gets candidates start for given partition */
314 STP_Vectype(int) dpborder_partGetCandstarts(
315  SCIP* scip, /**< SCIP data structure */
316  const DPBPART* borderpartition, /**< partition */
317  const DPBORDER* dpborder /**< border */
318 )
319 {
320  STP_Vectype(int) candstarts = NULL;
321  const DPB_Ptype* const partitionchars = borderpartition->partchars;
322  const DPB_Ptype delimiter = borderpartition->delimiter;
323  const int partsize = borderpartition->partsize;
324  const SCIP_Real* const borderchardists = dpborder->borderchardists;
325 
326  assert(dpborder_partIsValid(borderpartition));
327 
328  for( int i = 0; i < partsize; i++ )
329  {
330  const DPB_Ptype borderchar = partitionchars[i];
331  assert(0 <= borderchar && borderchar <= delimiter);
332 
333  if( borderchar == delimiter )
334  continue;
335 
336  if( LT(borderchardists[(unsigned char)borderchar], FARAWAY) )
337  {
338  int startpos;
339  for( startpos = i; startpos > 0; startpos-- )
340  {
341  if( partitionchars[startpos] == delimiter )
342  break;
343  }
344 
345  if( partitionchars[startpos] == delimiter )
346  startpos++;
347 
348  StpVecPushBack(scip, candstarts, startpos);
349 
350  /* move to next set of the partition */
351  for( ; i < partsize && partitionchars[i] != delimiter; i++ )
352  {
353  assert(partitionchars[i] < delimiter);
354  }
355  }
356  }
357 
358  return candstarts;
359 }
360 
361 
362 /** gets cardinality from global index of new global partition. */
364  int globalindex, /**< global index */
365  int delimiter, /**< delimiter */
366  const DPBORDER* dpborder /**< border */
367 )
368 {
369  int card = 1;
370  const int globalstart = dpborder->global_partstarts[globalindex];
371  const int globalend = dpborder->global_partstarts[globalindex + 1];
372  const DPB_Ptype* const global_partitions = dpborder->global_partitions;
373 
374  assert(0 <= globalindex && globalindex < dpborder->global_npartitions);
375  assert(0 <= delimiter);
376  assert(globalstart < globalend);
377 
378  for( int i = globalstart; i != globalend; i++ )
379  {
380  if( global_partitions[i] == delimiter )
381  card++;
382  }
383 
384  return card;
385 }
386 
387 
388 /** gets minimum connection cost of connection selected sets of partition to extension vertex */
390  const DPBORDER* dpborder, /**< border */
391  const DPBPART* borderpartition, /**< base partition */
392  const int* candstarts_sub, /**< candidate starts from which to construct new partition */
393  int ncandstarts_sub /**< number of candidate starts */
394 )
395 {
396  SCIP_Real costsum = 0.0;
397  const SCIP_Real* const borderchardists = dpborder->borderchardists;
398  const DPB_Ptype* const partitionchars = borderpartition->partchars;
399  const DPB_Ptype delimiter_prev = borderpartition->delimiter;
400  const int partsize = borderpartition->partsize;
401 
402  assert(dpborder_partIsValid(borderpartition));
403 
404  for( int i = 0; i < ncandstarts_sub; i++ )
405  {
406  SCIP_Real minedgecost = FARAWAY;
407  const int candstart = candstarts_sub[i];
408  assert(0 <= candstart && candstart < partsize);
409 
410  for( int j = candstart; j < partsize; j++ )
411  {
412  const DPB_Ptype partchar = partitionchars[j];
413  assert(0 <= partchar && partchar <= delimiter_prev);
414 
415  if( partchar == delimiter_prev )
416  break;
417 
418  if( LT(borderchardists[(unsigned char)partchar], minedgecost) )
419  minedgecost = borderchardists[(unsigned char)partchar];
420  }
421 
422  costsum += minedgecost;
423 
424  if( GE(costsum, FARAWAY) )
425  break;
426  }
427  assert(GE(costsum, 0.0));
428 
429  return costsum;
430 }
431 
432 
433 /** Gets global index of new global partition.
434  * Returns -1 if no valid partition could be built. */
436  SCIP* scip, /**< SCIP data structure */
437  const DPBPART* borderpartition, /**< base partition */
438  const int* candstarts_sub, /**< candidate starts from which to construct new partition */
439  int ncandstarts_sub, /**< number of candidate starts */
440  DPBORDER* dpborder /**< border */
441 )
442 {
443  int i;
444  int globalstart = dpborder->global_partstarts[dpborder->global_npartitions];
445  int globalend = globalstart;
446  DPB_Ptype* RESTRICT global_partitions = dpborder->global_partitions;
447  const int* const bordercharmap = dpborder->bordercharmap;
448  DPB_Ptype* RESTRICT partitionchars = borderpartition->partchars;
449  const DPB_Ptype delimiter_prev = borderpartition->delimiter;
450  const DPB_Ptype delimiter_new = dpborder_getTopDelimiter(dpborder);
451  const int partsize = borderpartition->partsize;
453 #ifdef SCIP_DEBUG
454  DPBPART partition;
455 #endif
456 
457  assert(dpborder_partIsValid(borderpartition));
458  assert(globalstart + partsize + 2 < dpborder->global_partcap);
459  assert(globalstart >= 1);
460 
461  /* form the union of marked subsets, as well as of extension node (if in border) */
462  for( i = 0; i < ncandstarts_sub; i++ )
463  {
464  const int candstart = candstarts_sub[i];
465  assert(0 <= candstart && candstart < partsize);
466 
467  for( int j = candstart; j < partsize; j++ )
468  {
469  const DPB_Ptype partchar = partitionchars[j];
470  assert(0 <= partchar && partchar <= delimiter_prev);
471 
472  if( partchar == delimiter_prev )
473  break;
474 
475  if( bordercharmap[(unsigned char)partchar] != -1 )
476  global_partitions[globalend++] = bordercharmap[(unsigned char)partchar];
477  }
478 
479  assert(partitionchars[candstart] < delimiter_prev);
480 
481  /* we mark the starts to skip them later on */
482  partitionchars[candstart] = -partitionchars[candstart] - 1;
483  assert(partitionchars[candstart] < 0);
484  }
485 
486  if( dpborder->extborderchar >= 0 )
487  {
488  assert(dpborder_getTopLevel(dpborder)->extnode == dpborder->bordernodes[(unsigned char)dpborder->extborderchar]);
489  global_partitions[globalend++] = dpborder->extborderchar;
490  }
491 
492  if( globalend == globalstart )
493  {
494  SCIPdebugMessage("...empty first subset... \n");
495  for( int j = 0; j < partsize; j++ )
496  {
497  if( partitionchars[j] < 0 )
498  partitionchars[j] = -(partitionchars[j] + 1);
499  }
500 
501 #ifndef NDEBUG
502  for( int j = 0; j < partsize; j++ )
503  assert(0 <= partitionchars[j] && partitionchars[j] <= delimiter_prev);
504 #endif
505 
506  return -1;
507  }
508 
509  doCopy = TRUE;
510 
511  if( partitionchars[0] >= 0 )
512  {
513  assert(delimiter_prev != partitionchars[0]);
514  global_partitions[globalend++] = delimiter_new;
515  }
516 
517  /* now we add the remaining sets of the partition */
518  for( i = 0; i < partsize; i++ )
519  {
520  const DPB_Ptype partchar = partitionchars[i];
521  if( partchar < 0 )
522  {
523  partitionchars[i] = -(partitionchars[i] + 1);
524  doCopy = FALSE;
525  continue;
526  }
527 
528  if( partchar == delimiter_prev )
529  {
530  assert(i < partsize);
531 
532  if( partitionchars[i + 1] >= 0 )
533  {
534  /* empty subset? */
535  if( delimiter_new == global_partitions[globalend - 1] )
536  {
537  globalstart = -1;
538  break;
539  }
540 
541  global_partitions[globalend++] = delimiter_new;
542  doCopy = TRUE;
543  }
544  continue;
545  }
546 
547  if( !doCopy )
548  continue;
549 
550  if( bordercharmap[(unsigned char)partchar] != -1 )
551  global_partitions[globalend++] = bordercharmap[(unsigned char)partchar];
552  }
553 
554  if( delimiter_new == global_partitions[globalend - 1] )
555  globalstart = -1;
556 
557  if( globalstart == -1 )
558  {
559  for( int j = i + 1; j < partsize; j++ )
560  {
561  if( partitionchars[j] < 0 )
562  partitionchars[j] = -(partitionchars[j] + 1);
563  }
564  }
565 
566 #ifndef NDEBUG
567  for( int j = 0; j < partsize; j++ )
568  assert(0 <= partitionchars[j] && partitionchars[j] <= delimiter_prev);
569 #endif
570 
571  if( globalstart != -1 )
572  {
573  int position;
574  const int partition_length = globalend - globalstart;
575 
576 #ifdef SCIP_DEBUG
577  partition.partchars = &(global_partitions[globalstart]);
578  partition.partsize = (globalend - globalstart);
579  partition.delimiter = delimiter_new;
580  printf("new (sub) partition \n");
581  dpborder_partPrint(&partition);
582 #endif
583 
584  partitionSortSubsets(&global_partitions[globalstart], delimiter_new, partition_length);
585 
586 #ifdef SCIP_DEBUG
587  printf("sorted: \n");
588  dpborder_partPrint(&partition);
589 #endif
590 
591  position = hashmap_get(&dpborder->hashmap, globalstart, partition_length);
592 
593  /* not found? */
594  if( -1 == position )
595  {
596  SCIPdebugMessage("...partition is new \n");
597  StpVecPushBack(scip, dpborder->global_partstarts, globalend);
598  StpVecPushBack(scip, dpborder->global_partcosts, FARAWAY);
599  StpVecPushBack(scip, dpborder->global_partsUseExt, TRUE);
600  StpVecPushBack(scip, dpborder->global_predparts, -1);
601  position = dpborder->global_npartitions;
602  dpborder->global_npartitions++;
603 
604  assert(!partitionIsIncluded(dpborder, &global_partitions[globalstart], partition_length));
605  hashmap_put(&dpborder->hashmap, globalstart, partition_length, position);
606  }
607  else
608  {
609  assert(LT(dpborder->global_partcosts[position], FARAWAY));
610  assert(0 == memcmp(&global_partitions[globalstart], &global_partitions[dpborder->global_partstarts[position]], partition_length));
611  }
612 
613 #ifdef SCIP_DEBUG
614  printf("final new (sub) partition glbpos=%d \n", position);
615 #endif
616 
617  assert(1 <= position && position < dpborder->global_npartitions);
618  assert(dpborder_getTopLevel(dpborder)->globalstartidx <= position);
619 
620  return position;
621  }
622 
623  SCIPdebugMessage("invalid partition... \n");
624 
625  return -1;
626 }
627 
628 
629 
630 /** Gets global index of new global partition, similar to above, but merely removes prev. border
631  * nodes.
632  * Returns -1 if no valid partition could be built. */
634  SCIP* scip, /**< SCIP data structure */
635  const DPBPART* borderpartition, /**< base partition */
636  DPBORDER* dpborder /**< border */
637 )
638 {
639  int position;
640  int partition_length;
641  int globalstart = dpborder->global_partstarts[dpborder->global_npartitions];
642  int globalend = globalstart;
643  DPB_Ptype* RESTRICT global_partitions = dpborder->global_partitions;
644  const int* const bordercharmap = dpborder->bordercharmap;
645  const DPB_Ptype* const partitionchars = borderpartition->partchars;
646  const DPB_Ptype delimiter_new = dpborder_getTopDelimiter(dpborder);
647  const int partsize = borderpartition->partsize;
648 #ifdef SCIP_DEBUG
649  DPBPART partition;
650 #endif
651 
652  assert(dpborder_partIsValid(borderpartition));
653  assert(globalstart + partsize < dpborder->global_partcap);
654  assert(globalstart >= 1);
655 
656  for( int i = 0; i < partsize; i++ )
657  {
658  const DPB_Ptype partchar = partitionchars[i];
659  assert(0 <= partchar && partchar <= borderpartition->delimiter);
660  assert(partchar != borderpartition->delimiter || bordercharmap[(unsigned char)partchar] == delimiter_new);
661 
662  if( bordercharmap[(unsigned char)partchar] != -1 )
663  global_partitions[globalend++] = bordercharmap[(unsigned char)partchar];
664  }
665 
666  if( globalstart == globalend
667  || global_partitions[globalstart] == delimiter_new
668  || global_partitions[globalend - 1] == delimiter_new )
669  {
670  SCIPdebugMessage("exlusive sub-partition is invalid (empty)... \n");
671  return -1;
672  }
673 
674  for( int i = globalstart + 1; i != globalend; i++ )
675  {
676  if( global_partitions[i] == delimiter_new && global_partitions[i - 1] == delimiter_new )
677  {
678  SCIPdebugMessage("exlusive sub-partition is invalid (empty subset)... \n");
679  return -1;
680  }
681  }
682 
683  partition_length = (globalend - globalstart);
684 
685 #ifdef SCIP_DEBUG
686  partition.partchars = &(global_partitions[globalstart]);
687  partition.partsize = partition_length;
688  partition.delimiter = delimiter_new;
689  printf("new (exclusive sub) partition \n");
690  dpborder_partPrint(&partition);
691 #endif
692 
693  partitionSortSubsets(&global_partitions[globalstart], delimiter_new, partition_length);
694 #ifdef SCIP_DEBUG
695  printf("sorted: \n");
696  dpborder_partPrint(&partition);
697 #endif
698 
699  position = hashmap_get(&dpborder->hashmap, globalstart, partition_length);
700 
701  /* not found? */
702  if( -1 == position )
703  {
704  SCIPdebugMessage("...partition is new \n");
705  StpVecPushBack(scip, dpborder->global_partstarts, globalend);
706  StpVecPushBack(scip, dpborder->global_partcosts, FARAWAY);
707  StpVecPushBack(scip, dpborder->global_predparts, -1);
708  StpVecPushBack(scip, dpborder->global_partsUseExt, FALSE);
709  position = dpborder->global_npartitions;
710  dpborder->global_npartitions++;
711 
712  assert(!partitionIsIncluded(dpborder, &global_partitions[globalstart], partition_length));
713  hashmap_put(&dpborder->hashmap, globalstart, partition_length, position);
714  }
715  else
716  {
717  assert(LT(dpborder->global_partcosts[position], FARAWAY));
718  assert(0 == memcmp(&global_partitions[globalstart], &global_partitions[dpborder->global_partstarts[position]], partition_length));
719  }
720 
721 #ifdef SCIP_DEBUG
722  printf("final new (sub) partition glbpos=%d \n", position);
723 #endif
724  assert(1 <= position && position < dpborder->global_npartitions);
725  assert(dpborder_getTopLevel(dpborder)->globalstartidx <= position);
726  assert(dpborder->global_npartitions == StpVecGetSize(dpborder->global_predparts));
727  assert(dpborder->global_npartitions == StpVecGetSize(dpborder->global_partcosts));
728  assert(dpborder->global_npartitions == StpVecGetSize(dpborder->global_partsUseExt));
729  assert(dpborder->global_npartitions + 1 == StpVecGetSize(dpborder->global_partstarts));
730 
731  return position;
732 }
733 
734 
735 /** marks optimal solution nodes */
737  const DPBORDER* dpborder, /**< border */
738  STP_Bool* RESTRICT nodes_isSol /**< solution nodes */
739 )
740 {
741 
742  const DPB_Ptype* const global_partitions = dpborder->global_partitions;
743  const STP_Vectype(int) global_partstarts = dpborder->global_partstarts;
744  const int nnodes = dpborder->nnodes;
745  const int optposition = dpborder->global_optposition;
746  int nlevels = 0;
747 
748  assert(dpborder && nodes_isSol);
749 
750  BMSclearMemoryArray(nodes_isSol, nnodes);
751  SCIPdebugMessage("marking solution nodes: \n");
752 
753  for( int pos = optposition; pos != 0; pos = dpborder->global_predparts[pos] )
754  nlevels++;
755 
756  for( int pos = optposition, level = nlevels; pos != 0; pos = dpborder->global_predparts[pos], level-- )
757  {
758  const int globalend = global_partstarts[pos + 1];
759  const STP_Vectype(int) nodemap = dpborder->borderlevels[level]->bordernodesMapToOrg;
760  const DPB_Ptype delimiter = dpborder_getDelimiter(dpborder, level);
761 
762  assert(level > 0);
763  assert(0 <= pos && pos < dpborder->global_npartitions);
764  assert(global_partstarts[pos + 1] > global_partstarts[pos]);
765  assert(nodemap);
766  assert(delimiter == StpVecGetSize(nodemap));
767 
768  SCIPdebugMessage("pos=%d, size %d range: %d-%d \n", pos,
769  global_partstarts[pos + 1] - global_partstarts[pos], global_partstarts[pos], globalend);
770 
771  if( dpborder->global_partsUseExt[pos] )
772  {
773  const int extnode = dpborder->borderlevels[level]->extnode;
774  assert(0 <= extnode && extnode < nnodes);
775  SCIPdebugMessage("solnode=%d (ext) \n", extnode);
776 
777  nodes_isSol[extnode] = TRUE;
778  }
779 
780  for( int i = global_partstarts[pos]; i != globalend; i++ )
781  {
782  const DPB_Ptype borderchar = global_partitions[i];
783  assert(0 <= borderchar && borderchar <= delimiter);
784 
785  if( borderchar != delimiter )
786  {
787  const int node = nodemap[(unsigned char)borderchar];
788  SCIPdebugMessage("solnode=%d \n", node);
789  assert(0 <= node && node < nnodes);
790 
791  nodes_isSol[node] = TRUE;
792  }
793  }
794  }
795 
796  SCIPdebugMessage("final solnode=%d \n", dpborder->borderlevels[0]->extnode);
797  nodes_isSol[dpborder->borderlevels[0]->extnode] = TRUE;
798 }
#define StpVecGetSize(vec)
Definition: stpvector.h:139
int dpborder_partGetIdxNew(SCIP *scip, const DPBPART *borderpartition, const int *candstarts_sub, int ncandstarts_sub, DPBORDER *dpborder)
static SCIP_Bool partitionIsSorted(const DPB_Ptype *partition, DPB_Ptype delimiter, int size)
Definition: dpborder_util.c:68
static SCIP_RETCODE doCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool useconscompression, SCIP_Bool global, SCIP_Bool original, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip_copy.c:2636
#define FALSE
Definition: def.h:87
unsigned size
#define TRUE
Definition: def.h:86
static SCIP_Bool partitionIsIncluded(const DPBORDER *dpborder, const DPB_Ptype *partition, int size)
Definition: dpborder_util.c:34
static DPBLEVEL * dpborder_getTopLevel(const DPBORDER *dpborder)
#define SCIPdebugMessage
Definition: pub_message.h:87
static int dpborder_getTopDelimiter(const DPBORDER *dpborder)
#define FARAWAY
Definition: graphdefs.h:89
STP_Vectype(int)
void dpborder_markSolNodes(const DPBORDER *dpborder, STP_Bool *RESTRICT nodes_isSol)
SCIP_Real dpborder_partGetConnectionCost(const DPBORDER *dpborder, const DPBPART *borderpartition, const int *candstarts_sub, int ncandstarts_sub)
#define GE(a, b)
Definition: portab.h:85
static int hashmap_get(const struct hashmap_s *const hashmap, int position, const unsigned len) HASHMAP_USED
Get an element from the hashmap.
#define NULL
Definition: lpi_spx1.cpp:155
#define LT(a, b)
Definition: portab.h:81
void dpborder_partPrint(const DPBPART *borderpartition)
unsigned char STP_Bool
Definition: portab.h:34
int dpborder_partglobalGetCard(int globalindex, int delimiter, const DPBORDER *dpborder)
#define SCIP_Bool
Definition: def.h:84
#define BPBORDER_MAXBORDERSIZE
static int dpborder_getDelimiter(const DPBORDER *dpborder, int iteration)
static void hashmap_put(struct hashmap_s *const hashmap, int position, const unsigned len, int value) HASHMAP_USED
#define DPB_Ptype
Dynamic programming solver for Steiner tree (sub-) problems with small border.
#define SCIP_Real
Definition: def.h:177
Dynamic programming internals for Steiner tree (sub-) problems with small number of terminals...
#define nnodes
Definition: gastrans.c:65
#define StpVecPushBack(scip, vec, value)
Definition: stpvector.h:167
static void partitionSortSubsets(DPB_Ptype *RESTRICT partition, DPB_Ptype delimiter, int size)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:123
SCIP_Bool dpborder_partIsValid(const DPBPART *borderpartition)
int dpborder_partGetIdxNewExclusive(SCIP *scip, const DPBPART *borderpartition, DPBORDER *dpborder)