Scippy

SCIP

Solving Constraint Integer Programs

bidecomposition.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 bidecomposition.c
17  * @brief several decomposition methods for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements bi-connected components decomposition methods for several Steiner problems.
21  *
22  * A list of all interface methods can be found in bidecomposition.h.
23  *
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 //#define SCIP_DEBUG
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include "bidecomposition.h"
34 #include "stpvector.h"
35 #include "portab.h"
36 
37 /*
38  * Local methods
39  */
40 
41 
42 /** sets root */
43 static inline
45  const GRAPH* g, /**< graph data structure */
46  CUTNODES* cutnodes /**< cut nodes */
47  )
48 {
49  if( !graph_pc_isPcMw(g) )
50  {
51  cutnodes->dfsroot = g->source;
52  }
53  else
54  {
55  int i;
56  const int nnodes = graph_get_nNodes(g);
57  const int pseudoroot = graph_pc_isRootedPcMw(g) ? -1 : g->source;
58 
59  assert(!g->extended);
60 
61  for( i = 0; i < nnodes; i++ )
62  {
63  if( Is_term(g->term[i]) && i != pseudoroot)
64  {
65  assert(!graph_pc_knotIsDummyTerm(g, i));
66  cutnodes->dfsroot = i;
67  break;
68  }
69  }
70 
71  assert(i < nnodes);
72  }
73 }
74 
75 
76 /** processes bi-connected component */
77 static
79  int root, /**< root of component */
80  int stack_start, /**< start of component in the stack */
81  CUTNODES* cutnodes /**< cut nodes */
82  )
83 {
84  const int ncomps = ++(cutnodes->biconn_ncomps);
85  int* biconn_nodesmark = cutnodes->biconn_nodesmark;
86  int* biconn_comproot = cutnodes->biconn_comproots;
87  STP_Vectype(int) biconn_stack = cutnodes->biconn_stack;
88 
89  assert(stack_start >= 0);
90  assert(StpVecGetSize(biconn_stack) > stack_start);
91  assert(ncomps > 0);
92  assert(biconn_comproot[ncomps] == -1);
93  assert(ncomps == 1 || biconn_comproot[ncomps - 1] != -1);
94 
95  biconn_comproot[ncomps] = root;
96 
97  for( int size = StpVecGetSize(biconn_stack); size != stack_start; size-- )
98  {
99  const int compnode = biconn_stack[size - 1];
100  SCIPdebugMessage("%d \n", compnode);
101 
102  assert(size >= 1);
103  assert(size == StpVecGetSize(biconn_stack));
104  assert(biconn_nodesmark[compnode] == 0);
105  assert(compnode != root);
106 
107  biconn_nodesmark[compnode] = ncomps;
108  StpVecPopBack(biconn_stack);
109  }
110 }
111 
112 
113 /** recursive DFS */
114 static
116  const GRAPH* g, /**< graph data structure */
117  int node, /**< vertex */
118  int parent, /**< parent of node */
119  CUTNODES* cutnodes /**< cut nodes */
120  )
121 {
122 #ifdef CUTTREE_PRINT_STATISTICS
123  int* childcount_terms = cutnodes->childcount_terms;
124  int* childcount_nodes = cutnodes->childcount_nodes;
125 #endif
126 
127  int* const nodes_hittime = cutnodes->nodes_hittime;
128  const int myhittime = cutnodes->curr_hittime;
129  int mylowpoint = myhittime;
130  int nchildren = 0;
131  SCIP_Bool isCutNode = FALSE;
132  const SCIP_Bool nodeIsRoot = (parent == -1);
133 
134  nodes_hittime[node] = myhittime;
135  (cutnodes->curr_hittime)++;
136  StpVecPushBack(cutnodes->scip, cutnodes->biconn_stack, node);
137 
138  for( int e = g->outbeg[node]; e != EAT_LAST; e = g->oeat[e] )
139  {
140  const int head = g->head[e];
141 
142  if( !g->mark[head] )
143  continue;
144 
145  /* not visited? */
146  if( nodes_hittime[head] < 0 )
147  {
148  const int stack_start = StpVecGetSize(cutnodes->biconn_stack);
149  assert(head != parent);
150 
151  cutNodesComputeDfs(g, head, node, cutnodes);
152 
153 #ifdef CUTTREE_PRINT_STATISTICS
154  childcount_nodes[node] += childcount_nodes[head] + 1;
155  childcount_terms[node] += childcount_terms[head] + (Is_term(g->term[head]) ? 1 : 0);
156 #endif
157  if( nodeIsRoot )
158  {
159  nchildren++;
160 
161  if( nchildren > 1 )
162  {
163  SCIPdebugMessage("mark new bi-connected component from root \n");
164 
165  cutNodesProcessComponent(node, stack_start, cutnodes);
166  }
167  }
168  else if( cutnodes->curr_lowpoint >= myhittime )
169  {
170  isCutNode = TRUE;
171 
172  SCIPdebugMessage("mark new bi-connected component from %d \n", node);
173 
174  cutNodesProcessComponent(node, stack_start, cutnodes);
175  }
176 
177  if( mylowpoint > cutnodes->curr_lowpoint )
178  mylowpoint = cutnodes->curr_lowpoint;
179  }
180  else if( head != parent )
181  {
182  assert(nodes_hittime[head] >= 0);
183  if( mylowpoint > nodes_hittime[head] )
184  mylowpoint = nodes_hittime[head];
185  }
186  }
187 
188  if( nodeIsRoot && nchildren > 1 )
189  {
190  assert(!isCutNode);
191  isCutNode = TRUE;
192  SCIPdebugMessage("found parent cut node: %d \n", node);
193  }
194 
195  if( isCutNode )
196  {
197  StpVecPushBack(cutnodes->scip, cutnodes->artpoints, node);
198  }
199 
200  cutnodes->curr_lowpoint = mylowpoint;
201 }
202 
203 
204 /** post-process */
205 static
207  const GRAPH* g, /**< graph data structure */
208  CUTNODES* cutnodes /**< cut nodes */
209  )
210 {
211  const int lastroot = cutnodes->artpoints[StpVecGetSize(cutnodes->artpoints) - 1];
212  assert(cutnodes->biconn_comproots[0] == -1);
213 
214  cutnodes->biconn_comproots[0] = lastroot;
215  cutnodes->biconn_ncomps++;
216 
217 #ifdef XXX_XXX
218  for( int i = 0; i < g->knots; i++ )
219  {
220  printf("%d in comp %d \n", i, cutnodes->biconn_nodesmark[i]);
221  }
222 
223  for( int i = 0; i < cutnodes->biconn_ncomps; i++ )
224  {
225  printf("comp-root[%d]=%d \n", i, cutnodes->biconn_comproots[i]);
226  }
227 #endif
228 
229 }
230 
231 #ifndef NDEBUG
232 /** builds CSR like arrays for biconnected components */
233 static
235  const CUTNODES* cutnodes, /**< cut nodes */
236  const GRAPH* g, /**< graph data structure */
237  const BIDECOMP* bidecomp /**< bi-decomposition structure */
238  )
239 {
240  const int* const nodes = bidecomp->nodes;
241  const int* const starts = bidecomp->starts;
242  const int* const biconn_nodesmark = cutnodes->biconn_nodesmark;
243  const int* const biconn_comproots = cutnodes->biconn_comproots;
244  const int ncomps = cutnodes->biconn_ncomps;
245 
246  for( int i = 0; i < ncomps; i++ )
247  {
248  const int comp_start = starts[i];
249  const int comp_end = starts[i + 1];
250  const int comp_root = biconn_comproots[i];
251 
252  assert(comp_start <= comp_end);
253 
254  SCIPdebugMessage("component %d is of size %d (root=%d); nodes: \n", i, comp_end - comp_start,
255  comp_root);
256 
257  for( int j = comp_start; j != comp_end; j++ )
258  {
259  const int comp_node = nodes[j];
260  assert(graph_knot_isInRange(g, comp_node));
261 
262 #ifdef SCIP_DEBUG
263  graph_knot_printInfo(g, comp_node);
264 #endif
265 
266  if( biconn_nodesmark[comp_node] != i )
267  {
268  int k = 0;
269  SCIP_Bool isCompRoot = FALSE;
270  for( k = 0; k < ncomps; k++ )
271  {
272  if( comp_node == biconn_comproots[k] )
273  {
274  isCompRoot = TRUE;
275  break;
276  }
277  }
278 
279  if( !isCompRoot )
280  {
281  printf("ERROR: no component root found \n");
282  return FALSE;
283  }
284  }
285  }
286  }
287 
288  return TRUE;
289 }
290 
291 #endif
292 
293 
294 /** builds CSR like arrays for biconnected components */
295 static
297  const CUTNODES* cutnodes, /**< cut nodes */
298  const GRAPH* g, /**< graph data structure */
299  BIDECOMP* bidecomp /**< bidecomposition data structure */
300  )
301 {
302  int* RESTRICT nodes = bidecomp->nodes;
303  int* RESTRICT starts = bidecomp->starts;
304  const int* const biconn_nodesmark = cutnodes->biconn_nodesmark;
305  const int* const biconn_comproots = cutnodes->biconn_comproots;
306  const int ncomps = cutnodes->biconn_ncomps;
307  const int nnodes = graph_get_nNodes(g);
308 
309  for( int i = 0; i <= ncomps; i++ )
310  starts[i] = 0;
311 
312  for( int i = 0; i < nnodes; i++ )
313  {
314  if( g->mark[i] && g->grad[i] > 0 )
315  {
316  const int compid = biconn_nodesmark[i];
317  assert(0 <= compid && compid < ncomps);
318 
319  starts[compid]++;
320  }
321  }
322 
323  /* we also need to count the component roots */
324  for( int i = 0; i < ncomps; i++ )
325  {
326  const int comproot = biconn_comproots[i];
327  if( biconn_nodesmark[comproot] != i && g->grad[comproot] > 0 )
328  starts[i]++;
329  }
330 
331  for( int i = 1; i <= ncomps; i++ )
332  starts[i] += starts[i - 1];
333 
334  assert(starts[ncomps] == starts[ncomps - 1]);
335 
336  /* now fill the values in */
337  for( int i = 0; i < nnodes; i++ )
338  {
339  if( g->mark[i] && g->grad[i] > 0 )
340  {
341  const int compid = biconn_nodesmark[i];
342  assert(0 <= compid && compid < ncomps);
343 
344  starts[compid]--;
345  nodes[starts[compid]] = i;
346 
347  assert(compid == 0 || starts[compid - 1] <= starts[compid]);
348  }
349  }
350 
351  for( int i = 0; i < ncomps; i++ )
352  {
353  const int comproot = biconn_comproots[i];
354  if( biconn_nodesmark[comproot] != i && g->grad[comproot] > 0 )
355  {
356  starts[i]--;
357  nodes[starts[i]] = comproot;
358  }
359  }
360 
361  assert(starts[0] == 0);
362  assert(starts[ncomps] <= nnodes + ncomps);
363 
364  assert(decomposeCsrIsValid(cutnodes, g, bidecomp));
365 }
366 
367 
368 /** gets first marked component */
369 static
371  SCIP* scip, /**< SCIP data structure */
372  const GRAPH* orggraph, /**< graph data structure */
373  int* subroot /**< the new root (out) */
374  )
375 {
376  const int* const gMark = orggraph->mark;
377  STP_Bool* nodes_isVisited;
378  STP_Vectype(int) stack = NULL;
379  const int nnodes = graph_get_nNodes(orggraph);
380  const int root = orggraph->source;
381  SCIP_Bool markedIsFound = FALSE;
382 
383  if( gMark[root] )
384  {
385  *subroot = root;
386  return SCIP_OKAY;
387  }
388 
389  SCIP_CALL( SCIPallocBufferArray(scip, &nodes_isVisited, nnodes) );
390 
391  for( int i = 0; i < nnodes; i++ )
392  nodes_isVisited[i] = FALSE;
393 
394  nodes_isVisited[root] = TRUE;
395  StpVecPushBack(scip, stack, root);
396 
397  /* DFS loop */
398  while( !StpVecIsEmpty(stack) && !markedIsFound )
399  {
400  const int node = stack[StpVecGetSize(stack) - 1];
401  assert(StpVecGetSize(stack) >= 1);
402  StpVecPopBack(stack);
403 
404  assert(graph_knot_isInRange(orggraph, node));
405 
406  for( int a = orggraph->outbeg[node]; a != EAT_LAST; a = orggraph->oeat[a] )
407  {
408  const int head = orggraph->head[a];
409 
410  if( !nodes_isVisited[head] )
411  {
412  if( gMark[head] )
413  {
414  assert(!markedIsFound);
415 
416  markedIsFound = TRUE;
417  *subroot = head;
418  break;
419  }
420  StpVecPushBack(scip, stack, head);
421  nodes_isVisited[head] = TRUE;
422  }
423  }
424  }
425 
426  assert(markedIsFound);
427 
428  StpVecFree(scip, stack);
429  SCIPfreeBufferArray(scip, &nodes_isVisited);
430 
431  return SCIP_OKAY;
432 }
433 
434 
435 /*
436  * Interface methods
437  */
438 
439 
440 /** initializes */
442  SCIP* scip, /**< SCIP data structure */
443  const GRAPH* g, /**< graph data structure */
444  CUTNODES** cutnodes /**< cut nodes */
445  )
446 {
447  CUTNODES* cn;
448  int* nodes_hittime;
449  int* biconn_nodesmark;
450  int* biconn_comproots;
451  const int nnodes = graph_get_nNodes(g);
452 
453  assert(scip);
454 
455  SCIP_CALL( SCIPallocMemory(scip, cutnodes) );
456  cn = *cutnodes;
457 
458 #ifdef CUTTREE_PRINT_STATISTICS
459  {
460  int* childcount_nodes;
461  int* childcount_terms;
462 
463  SCIP_CALL( SCIPallocMemoryArray(scip, &childcount_nodes, nnodes) );
464  SCIP_CALL( SCIPallocMemoryArray(scip, &childcount_terms, nnodes) );
465 
466  for( int k = 0; k < nnodes; k++ )
467  childcount_nodes[k] = 0;
468 
469  for( int k = 0; k < nnodes; k++ )
470  childcount_terms[k] = 0;
471 
472  cn->childcount_nodes = childcount_nodes;
473  cn->childcount_terms = childcount_terms;
474  }
475 #endif
476 
477  SCIP_CALL( SCIPallocMemoryArray(scip, &biconn_comproots, nnodes) );
478  SCIP_CALL( SCIPallocMemoryArray(scip, &biconn_nodesmark, nnodes) );
479  SCIP_CALL( SCIPallocMemoryArray(scip, &nodes_hittime, nnodes) );
480 
481  for( int k = 0; k < nnodes; k++ )
482  nodes_hittime[k] = -1;
483 
484 #ifndef NDEBUG
485  for( int k = 0; k < nnodes; k++ )
486  biconn_comproots[k] = -1;
487 #endif
488 
489  for( int k = 0; k < nnodes; k++ )
490  biconn_nodesmark[k] = 0;
491 
492  cn->scip = scip;
493  cn->artpoints = NULL;
494  cn->biconn_stack = NULL;
495  cn->biconn_comproots = biconn_comproots;
496  cn->biconn_nodesmark = biconn_nodesmark;
497  cn->nodes_hittime = nodes_hittime;
498  cn->biconn_ncomps = 0;
499  cn->dfsroot = -1;
500  cn->curr_lowpoint = -1;
501  cn->curr_hittime = -1;
502 
503  cutNodesSetDfsRoot(g, cn);
504 
505  StpVecReserve(scip, cn->biconn_stack, nnodes);
506 
507  return SCIP_OKAY;
508 }
509 
510 
511 /** exits */
513  SCIP* scip, /**< SCIP data structure */
514  CUTNODES** cutnodes /**< cut nodes */
515  )
516 {
517  CUTNODES* cn;
518 
519  assert(scip && cutnodes);
520  cn = *cutnodes;
521  assert(cn);
522 
523  StpVecFree(scip, cn->artpoints);
524  StpVecFree(scip, cn->biconn_stack);
525 
526  SCIPfreeMemoryArray(scip, &(cn->nodes_hittime));
529 
530 #ifdef CUTTREE_PRINT_STATISTICS
531  SCIPfreeMemoryArray(scip, &(cn->childcount_terms));
532  SCIPfreeMemoryArray(scip, &(cn->childcount_nodes));
533 #endif
534 
535  SCIPfreeMemory(scip, cutnodes);
536 }
537 
538 
539 /** computes cut-nodes and (implicitly) bi-connected components */
541  const GRAPH* g, /**< graph data structure */
542  CUTNODES* cutnodes /**< cut nodes */
543  )
544 {
545  assert(StpVecGetSize(cutnodes->biconn_stack) == 0);
546  assert(StpVecGetSize(cutnodes->artpoints) == 0);
547 
548  cutnodes->curr_hittime = 0;
549  /* NOTE: we assume the graph to be connected, so we only do the DFS once */
550  /* todo make it non-recursive, otherwise it might crash for big graphs! */
551  SCIPdebugMessage("starting DFS from %d \n", cutnodes->dfsroot);
552  cutNodesComputeDfs(g, cutnodes->dfsroot, -1, cutnodes);
553 
554  SCIPdebugMessage("number of cut nodes: %d \n", StpVecGetSize(cutnodes->artpoints));
555  assert(cutnodes->biconn_ncomps >= StpVecGetSize(cutnodes->artpoints));
556 
557  if( cutnodes->biconn_ncomps > 0 )
558  {
559  assert(StpVecGetSize(cutnodes->artpoints) > 0);
560  cutNodesComputePostProcess(g, cutnodes);
561 
562  SCIPdebugMessage("%d bi-connected components found! \n", cutnodes->biconn_ncomps);
563  }
564 }
565 
566 /** initializes */
568  SCIP* scip, /**< SCIP data structure */
569  const CUTNODES* cutnodes, /**< cut nodes */
570  const GRAPH* g, /**< graph data structure */
571  BIDECOMP** bidecomposition /**< bidecomposition data structure */
572  )
573 {
574  BIDECOMP* bidecomp;
575  int* nodes;
576  int* starts;
577  const int nnodes = graph_get_nNodes(g);
578  const int ncomps = cutnodes->biconn_ncomps;
579 
580  assert(scip && cutnodes);
581  assert(ncomps >= 2);
582 
583  SCIP_CALL( SCIPallocMemory(scip, bidecomposition) );
584  bidecomp = *bidecomposition;
585 
586  SCIP_CALL( SCIPallocMemoryArray(scip, &nodes, nnodes + ncomps) );
587  SCIP_CALL( SCIPallocMemoryArray(scip, &starts, ncomps + 1) );
588  bidecomp->subinout = NULL;
589  bidecomp->nodes = nodes;
590  bidecomp->starts = starts;
591  bidecomp->nbicomps = ncomps;
592 
593  decomposeBuildCsr(cutnodes, g, bidecomp);
594 
595  return SCIP_OKAY;
596 }
597 
598 
599 /** initializes */
601  SCIP* scip, /**< SCIP data structure */
602  const GRAPH* g, /**< graph data structure */
603  BIDECOMP* bidecomposition /**< bidecomposition data structure */
604  )
605 {
606  assert(scip && g && bidecomposition);
607  assert(!bidecomposition->subinout);
608 
609  SCIP_CALL( graph_subinoutInit(scip, g, &(bidecomposition->subinout)) );
610 
611  return SCIP_OKAY;
612 }
613 
614 
615 /** frees */
617  SCIP* scip, /**< SCIP data structure */
618  BIDECOMP** bidecomposition /**< bidecomposition data structure */
619  )
620 {
621  BIDECOMP* bidecomp;
622 
623  assert(scip && bidecomposition);
624 
625  bidecomp = *bidecomposition;
626  assert(bidecomp);
627 
628  if( bidecomp->subinout )
629  graph_subinoutFree(scip, &(bidecomp->subinout));
630 
631  SCIPfreeMemoryArray(scip, &(bidecomp->starts));
632  SCIPfreeMemoryArray(scip, &(bidecomp->nodes));
633 
634  SCIPfreeMemory(scip, bidecomposition);
635 }
636 
637 
638 /** marks subgraph of given component index */
640  const BIDECOMP* bidecomp, /**< all-components storage */
641  int compindex, /**< component index */
642  GRAPH* g /**< graph data structure */
643  )
644 {
645  int* const gMark = g->mark;
646  const SUBINOUT* const subinout = bidecomp->subinout;
647  const int* const contractionRecord = graph_subinoutGetContractionRecord(subinout);
648  const int* const compnodes = bidecomp->nodes;
649  const int compstart = bidecomp->starts[compindex];
650  const int compend = bidecomp->starts[compindex + 1];
651  const int nnodes = graph_get_nNodes(g);
652 
653  for( int i = 0; i < nnodes; i++ )
654  gMark[i] = FALSE;
655 
656  SCIPdebugMessage("marking subgraph: \n");
657 
658  for( int i = compstart; i != compend; i++ )
659  {
660  const int compnode = compnodes[i];
661  int realnode;
662 
663  assert(graph_knot_isInRange(g, compnode));
664 
665  if( contractionRecord[compnode] != -1 )
666  {
667  realnode = graph_knot_getContractionRecordAncestor(compnode, subinout);
668 
669  SCIPdebugMessage("(taking contracted node %d instead of %d:) \n", contractionRecord[compnode], compnode);
670  }
671  else
672  {
673  realnode = compnode;
674  }
675 #ifdef SCIP_DEBUG
676  graph_knot_printInfo(g, realnode);
677 #endif
678 
679  assert(graph_knot_isInRange(g, realnode));
680  gMark[realnode] = TRUE;
681  }
682 }
683 
684 
685 /** gets root of marked sub-component
686  * bidecomposition_markSub needs to be called before! */
688  SCIP* scip, /**< SCIP data structure */
689  const BIDECOMP* bidecomp, /**< all-components storage */
690  const GRAPH* orggraph, /**< graph data structure */
691  const GRAPH* subgraph, /**< graph data structure */
692  int* subroot /**< the new root (out) */
693  )
694 {
695  const int* nodemap_OrgToSub;
696 
697  assert(bidecomp && orggraph && subroot);
698  assert(bidecomp->subinout);
699 
700  *subroot = -1;
701 
702  SCIP_CALL( decomposeGetFirstMarked(scip, orggraph, subroot) );
703 
704  assert(graph_knot_isInRange(orggraph, *subroot));
705  assert(Is_term(orggraph->term[*subroot]));
706 
707  nodemap_OrgToSub = graph_subinoutGetOrgToSubNodeMap(bidecomp->subinout);
708  *subroot = nodemap_OrgToSub[*subroot];
709 
710  assert(graph_knot_isInRange(subgraph, *subroot));
711  assert(Is_term(subgraph->term[*subroot]));
712 
713  return SCIP_OKAY;
714 }
715 
716 
717 /** component consisting of at most one node? */
719  const BIDECOMP* bidecomp, /**< all-components storage */
720  int compindex /**< component index */
721  )
722 {
723  assert(bidecomp);
724  assert(0 <= compindex && compindex < bidecomp->nbicomps);
725 
726  {
727  const int compstart = bidecomp->starts[compindex];
728  const int compend = bidecomp->starts[compindex + 1];
729 
730  assert(compstart <= compend);
731 
732  if( compend - compstart <= 1 )
733  {
734  SCIPdebugMessage("component %d is of size %d, SKIP! \n", compindex, compend - compstart);
735  return TRUE;
736  }
737  }
738 
739  return FALSE;
740 }
741 
742 
743 /** todo remove once bigger graphs can be handled */
745  const GRAPH* g /**< graph data structure */
746  )
747 {
748  int nnodes_real = 0;
749  const int nnodes = graph_get_nNodes(g);
750  const int* const isMarked = g->mark;
751 
752  assert(graph_isMarked(g));
753 
754  for( int i = 0; i < nnodes; i++ )
755  {
756  if( isMarked[i] )
757  nnodes_real++;
758  }
759 
760  return (nnodes_real < 75000);
761 }
762 
763 
764 /** returns nodes ratio of component and the remaining graph */
766  const BIDECOMP* bidecomp, /**< bidecomposition data structure */
767  int compindex /**< component index */
768  )
769 {
770  const int* const starts = bidecomp->starts;
771  SCIP_Real ratio;
772  const int ncomps = bidecomp->nbicomps;
773  const int nallnodes = starts[ncomps] - starts[0];
774  int compnnodes;
775 
776  assert(bidecomp);
777  assert(0 <= compindex && compindex < ncomps);
778  assert(nallnodes > 0);
779 
780  compnnodes = starts[compindex + 1] - starts[compindex];
781  ratio = (SCIP_Real) compnnodes / (SCIP_Real) nallnodes;
782 
783  SCIPdebugMessage("component nodes ratio: %f \n", ratio);
784  assert(GE(ratio, 0.0));
785 
786  return (ratio);
787 }
788 
789 
790 /** returns ratio of nodes of maximum component and the remaining graph */
792  const BIDECOMP* bidecomp /**< bidecomposition data structure */
793  )
794 {
795  const int* const starts = bidecomp->starts;
796  SCIP_Real maxratio;
797  const int ncomps = bidecomp->nbicomps;
798  const int ncompnodes = starts[ncomps] - starts[0];
799  int maxcompnnodes = 0;
800 
801  assert(bidecomp);
802  assert(0 < ncompnodes);
803 
804  SCIPdebugMessage("all component nodes=%d \n", ncompnodes);
805 
806  for( int i = 0; i < ncomps; i++ )
807  {
808  const int compnnodes = starts[i + 1] - starts[i];
809  if( maxcompnnodes < compnnodes )
810  maxcompnnodes = compnnodes;
811  }
812 
813  maxratio = (SCIP_Real) maxcompnnodes / (SCIP_Real) ncompnodes;
814 
815  SCIPdebugMessage("max. component number of nodes=%d \n", maxcompnnodes);
816  SCIPdebugMessage("maxratio=%f \n", maxratio);
817 
818  assert(GT(maxratio, 0.0));
819 
820  return (maxratio);
821 }
#define STP_Vectype(type)
Definition: stpvector.h:44
#define StpVecGetSize(vec)
Definition: stpvector.h:139
int graph_knot_getContractionRecordAncestor(int, const SUBINOUT *)
Definition: graph_sub.c:895
int *RESTRICT head
Definition: graphdefs.h:224
int * biconn_comproots
int source
Definition: graphdefs.h:195
SCIP_Bool graph_pc_isRootedPcMw(const GRAPH *)
SCIP_Bool bidecomposition_isPossible(const GRAPH *g)
#define Is_term(a)
Definition: graphdefs.h:102
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip_mem.h:71
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:55
static void cutNodesComputePostProcess(const GRAPH *g, CUTNODES *cutnodes)
const int * graph_subinoutGetContractionRecord(const SUBINOUT *)
Definition: graph_sub.c:837
void graph_knot_printInfo(const GRAPH *, int)
Definition: graph_stats.c:151
#define FALSE
Definition: def.h:87
void graph_subinoutFree(SCIP *, SUBINOUT **)
Definition: graph_sub.c:859
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
void bidecomposition_free(SCIP *scip, BIDECOMP **bidecomposition)
#define StpVecPopBack(vec)
Definition: stpvector.h:178
#define EAT_LAST
Definition: graphdefs.h:58
#define StpVecReserve(scip, vec, _size_)
Definition: stpvector.h:182
#define SCIPdebugMessage
Definition: pub_message.h:87
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
static void cutNodesSetDfsRoot(const GRAPH *g, CUTNODES *cutnodes)
header only, simple implementation of an STL like vector
several decomposition methods for Steiner tree problems
int *RESTRICT mark
Definition: graphdefs.h:198
SCIP_Real bidecomposition_getCompNodeRatio(const BIDECOMP *bidecomp, int compindex)
int *RESTRICT oeat
Definition: graphdefs.h:231
int * nodes_hittime
#define GE(a, b)
Definition: portab.h:85
static void decomposeBuildCsr(const CUTNODES *cutnodes, const GRAPH *g, BIDECOMP *bidecomp)
int * biconn_nodesmark
SCIP_Bool extended
Definition: graphdefs.h:267
void bidecomposition_markSub(const BIDECOMP *bidecomp, int compindex, GRAPH *g)
void bidecomposition_cutnodesCompute(const GRAPH *g, CUTNODES *cutnodes)
int *RESTRICT grad
Definition: graphdefs.h:201
static SCIP_Bool decomposeCsrIsValid(const CUTNODES *cutnodes, const GRAPH *g, const BIDECOMP *bidecomp)
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_Real bidecomposition_getMaxcompNodeRatio(const BIDECOMP *bidecomp)
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
unsigned char STP_Bool
Definition: portab.h:34
SCIP_RETCODE bidecomposition_cutnodesInit(SCIP *scip, const GRAPH *g, CUTNODES **cutnodes)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define GT(a, b)
Definition: portab.h:84
#define SCIP_Bool
Definition: def.h:84
SCIP_RETCODE bidecomposition_initSubInOut(SCIP *scip, const GRAPH *g, BIDECOMP *bidecomposition)
SCIP_Bool graph_isMarked(const GRAPH *)
Definition: graph_base.c:1165
const int * graph_subinoutGetOrgToSubNodeMap(const SUBINOUT *)
Definition: graph_sub.c:825
static void cutNodesProcessComponent(int root, int stack_start, CUTNODES *cutnodes)
int *RESTRICT term
Definition: graphdefs.h:196
void bidecomposition_cutnodesFree(SCIP *scip, CUTNODES **cutnodes)
#define StpVecIsEmpty(vec)
Definition: stpvector.h:144
Portable definitions.
#define SCIPfreeMemory(scip, ptr)
Definition: scip_mem.h:69
SCIP_Bool graph_pc_knotIsDummyTerm(const GRAPH *, int)
SCIP_RETCODE graph_subinoutInit(SCIP *, const GRAPH *, SUBINOUT **)
Definition: graph_sub.c:733
static SCIP_RETCODE decomposeGetFirstMarked(SCIP *scip, const GRAPH *orggraph, int *subroot)
static void cutNodesComputeDfs(const GRAPH *g, int node, int parent, CUTNODES *cutnodes)
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
SCIP_VAR * a
Definition: circlepacking.c:57
#define SCIP_Real
Definition: def.h:177
#define StpVecFree(scip, vec)
Definition: stpvector.h:149
int *RESTRICT outbeg
Definition: graphdefs.h:204
int graph_get_nNodes(const GRAPH *)
Definition: graph_stats.c:536
#define SCIPallocMemory(scip, ptr)
Definition: scip_mem.h:51
SCIP_Bool graph_knot_isInRange(const GRAPH *, int)
Definition: graph_node.c:52
#define nnodes
Definition: gastrans.c:65
#define StpVecPushBack(scip, vec, value)
Definition: stpvector.h:163
SCIP_Bool bidecomposition_componentIsTrivial(const BIDECOMP *bidecomp, int compindex)
SCIP_RETCODE bidecomposition_getMarkedSubRoot(SCIP *scip, const BIDECOMP *bidecomp, const GRAPH *orggraph, const GRAPH *subgraph, int *subroot)
SCIP_RETCODE bidecomposition_init(SCIP *scip, const CUTNODES *cutnodes, const GRAPH *g, BIDECOMP **bidecomposition)