Scippy

SCIP

Solving Constraint Integer Programs

reduce_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 reduce_util.c
17  * @brief utility methods for Steiner tree reductions
18  * @author Daniel Rehfeldt
19  *
20  * This file implements utility methods for Steiner tree problem reduction techniques.
21  *
22  * A list of all interface methods can be found in reduce.h.
23  *
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 
28 //#define SCIP_DEBUG
29 #include "reduce.h"
30 #include "portab.h"
31 
32 
33 /** storage for edge on complete graph */
34 typedef struct complete_edge
35 {
36  int tail; /**< tail vertex */
37  int head; /**< head vertex */
38  SCIP_Real cost; /**< edge cost */
39 } CEDGE;
40 
41 
42 /** lightweight minimum spanning tree structure that allows to add vertices to given MST on complete graph (in CSR format) */
44 {
45  CEDGE* edgestore; /**< storage for edges (of size maxnnodes) */
46  SCIP_Real* adjcost_buffer; /**< distances buffer (of size maxnnodes) */
47  SCIP_Bool* nodemark; /**< array for marking nodes (of size maxnnodes) */
48  int maxnnodes; /**< maximum number of nodes that can be handled */
49 };
50 
51 
52 /** see reduce.h */
54 {
55  SCIP_Bool* edgeIsFailed; /**< marker for each adjacent edge of current node (of size maxNodeDegree) */
56  int* edgeId; /**< IDs for each adjacent edge of current node (of size maxNodeDegree) */
57  int* edgesPromising; /**< edges that might still be ruled out (of size maxNodeDegree) */
58  int* edgesSelected; /**< list of currently selected edges (of size maxNodeDegree) */
59  int* edgesSelectedPos; /**< list of position of currently selected edges w.r.t. edgeId (of size maxNodeDegree) */
60  int* edgesSelectedPosPrev; /**< list of position of previously selected edges w.r.t. edgeId (of size maxNodeDegree) */
61  int nodeDegree; /**< degree of current node */
62  int starDegree; /**< degree of current star */
63  int starDegreePrev; /**< degree of previous star */
64  int maxNodeDegree; /**< maximum allowed node degree */
65  int starcenter; /**< node for which the star is created */
66  int nedgesPromising; /**< edges that are promising */
67  SCIP_Bool allStarsChecked; /**< have all stars been checked? */
68 };
69 
70 
71 /** bottleneck link-cut tree node */
73 {
74  SCIP_Real dist_edgetail; /**< distance for edge tail */
75  SCIP_Real dist_edgehead; /**< distance for edge tail */
76  SCIP_Real edgecost; /**< edge cost */
77  SCIP_Real edgebottleneck; /**< restricted bottleneck of edge */
78  int head; /**< head of node in tree */
79  int edge; /**< edge of node (w.r.t original graph used for initialization) */
80 } BLCNODE;
81 
82 
83 /** see reduce.h */
85 {
86  BLCNODE* mst; /**< the actual tree, represented by its nodes */
87  int* nodes_curr2org; /**< map */
88  int* nodes_org2curr; /**< map */
89  SCIP_Bool* mstedges_isLink; /**< is the edge on a fundamental path between terminals? */
90  int root; /**< root of the tree */
91  int nnodes_org; /**< original number of graph nodes (before reductions) */
92  int nnodes_curr; /**< current number of graph nodes */
93 };
94 
95 
96 /*
97  * local methods
98  */
99 
100 
101 /** builds mapping */
102 static inline
104  SCIP* scip, /**< SCIP */
105  const GRAPH* graph, /**< the graph */
106  BLCTREE* RESTRICT blctree /**< the tree */
107 )
108 {
109  const int* nodes_isMarked = graph->mark;
110  int* RESTRICT nodes_curr2org;
111  int* RESTRICT nodes_org2curr;
112  int nodecount_curr;
113  const int nnodes_curr = blctree->nnodes_curr;
114  const int nnodes_org = blctree->nnodes_org;
115 
116  assert(0 < nnodes_curr && nnodes_curr <= nnodes_org);
117  assert(nnodes_org == graph->knots);
118 
119  SCIP_CALL( SCIPallocMemoryArray(scip, &(blctree->nodes_curr2org), nnodes_curr) );
120  SCIP_CALL( SCIPallocMemoryArray(scip, &(blctree->nodes_org2curr), nnodes_org) );
121 
122  nodes_curr2org = blctree->nodes_curr2org;
123  nodes_org2curr = blctree->nodes_org2curr;
124  nodecount_curr = 0;
125 
126  for( int i = 0; i < nnodes_org; ++i )
127  {
128  if( nodes_isMarked[i] )
129  {
130  assert(nodecount_curr < nnodes_curr);
131  nodes_org2curr[i] = nodecount_curr;
132  nodes_curr2org[nodecount_curr++] = i;
133  }
134  else
135  {
136  assert(graph_pc_isPc(graph) || graph->grad[i] == 0);
137  nodes_org2curr[i] = UNKNOWN;
138  }
139  }
140 
141  assert(nodecount_curr <= nnodes_curr);
142  assert(graph_pc_isPc(graph) || nodecount_curr == nnodes_curr);
143 
144  if( graph_pc_isPc(graph) )
145  {
146  blctree->nnodes_curr = nodecount_curr;
147  }
148 
149  return SCIP_OKAY;
150 }
151 
152 
153 /** allocates BLC tree memory and builds mapping */
154 static
156  SCIP* scip, /**< SCIP */
157  const GRAPH* graph, /**< the graph */
158  BLCTREE** blctree /**< to be initialized */
159 )
160 {
161  BLCTREE *tree;
162  int nnodes_curr;
163  const int nnodes = graph_get_nNodes(graph);
164 
165  graph_get_nVET(graph, &(nnodes_curr), NULL, NULL);
166 
167  SCIP_CALL( SCIPallocMemory(scip, blctree) );
168  tree = *blctree;
169 
170  tree->root = UNKNOWN;
171  tree->nnodes_org = nnodes;
172  tree->nnodes_curr = nnodes_curr;
173  SCIP_CALL( SCIPallocMemoryArray(scip, &(tree->mst), nnodes_curr) );
174  SCIP_CALL( SCIPallocMemoryArray(scip, &(tree->mstedges_isLink), nnodes_curr) );
175  SCIP_CALL( blctreeBuildNodeMap(scip, graph, tree) );
176 
177  return SCIP_OKAY;
178 }
179 
180 
181 /** resets given node */
182 static inline
184  int i, /**< the node */
185  BLCTREE* RESTRICT blctree /**< the tree */
186 )
187 {
188  BLCNODE* RESTRICT tree = blctree->mst;
189  assert(0 <= i && i < blctree->nnodes_curr);
190 
191  tree[i].dist_edgetail = 0.0;
192  tree[i].dist_edgehead = 0.0;
193  tree[i].edgebottleneck = FARAWAY;
194  tree[i].edgecost = -FARAWAY;
195  tree[i].edge = UNKNOWN;
196  tree[i].head = UNKNOWN;
197 }
198 
199 
200 /** sets new root*/
201 static inline
203  const GRAPH* graph, /**< the graph */
204  int newroot, /**< new root */
205  BLCTREE* blctree /**< tree */
206 )
207 {
208  BLCNODE blcnode_org;
209  BLCNODE* RESTRICT tree = blctree->mst;
210  int node;
211  const int oldroot = blctree->root;
212 
213  assert(tree);
214  assert(newroot != oldroot);
215  assert(0 <= newroot && newroot < blctree->nnodes_org);
216  assert(0 <= tree[newroot].head && newroot < blctree->nnodes_org);
217 
218  node = newroot;
219  blcnode_org = tree[newroot];
220  while( node != oldroot )
221  {
222  const SCIP_Real dist_tail = blcnode_org.dist_edgetail;
223  const SCIP_Real dist_head = blcnode_org.dist_edgehead;
224  const SCIP_Real edgecost = blcnode_org.edgecost;
225  const SCIP_Real edgebottleneck = blcnode_org.edgebottleneck;
226  const int head = blcnode_org.head;
227  const int edge = blcnode_org.edge;
228 
229  assert(edge != UNKNOWN);
230  assert(head != UNKNOWN);
231  assert(graph->tail[edge] == blctree->nodes_curr2org[node]);
232 
233  blcnode_org = tree[head];
234 
235  /* swap! */
236  tree[head].dist_edgetail = dist_head;
237  tree[head].dist_edgehead = dist_tail;
238  tree[head].edgecost = edgecost;
239  tree[head].edgebottleneck = edgebottleneck;
240  tree[head].head = node;
241  tree[head].edge = flipedge_Uint(edge);
242 
243  node = head;
244  }
245 
246  blctreeResetNode(newroot, blctree);
247  blctree->root = newroot;
248 }
249 
250 
251 /** gets cost of path */
252 static inline
254  int startnode, /**< node to start from */
255  const BLCTREE* blctree /**< tree */
256 )
257 {
258  const BLCNODE* const tree = blctree->mst;
259  SCIP_Real pathcost = 0.0;
260  int node = startnode;
261  const int root = blctree->root;
262 
263  assert(0 <= startnode && startnode < blctree->nnodes_org);
264 
265  while( node != root )
266  {
267  const int head = tree[node].head;
268  assert(head != UNKNOWN);
269 
270  SCIPdebugMessage("%d ", node);
271 
272  pathcost += tree[node].edgecost;
273  node = head;
274  }
275 
276  return pathcost;
277 }
278 
279 
280 /** updates path to root */
281 static inline
283  int startnode, /**< node to start from */
284  SCIP_Real bottleneck, /**< bottleneck */
285  BLCTREE* blctree /**< tree */
286 )
287 {
288  BLCNODE* RESTRICT tree = blctree->mst;
289  SCIP_Real nodedist_tail = 0.0;
290  const SCIP_Real pathcost = blctreeGetRootPathCost(startnode, blctree);
291  int node = startnode;
292  const int root = blctree->root;
293 
294  SCIPdebugMessage(" .... blctreeUpdateRootPath %d->%d pathcost=%f \n", startnode, root, pathcost);
295 
296  assert(0 <= startnode && startnode < blctree->nnodes_org);
297 
298  while( node != root )
299  {
300  SCIP_Real nodedist_head;
301  const int head = tree[node].head;
302  assert(head != UNKNOWN);
303 
304  /* take the MIN */
305  if( tree[node].edgebottleneck > bottleneck )
306  {
307  tree[node].edgebottleneck = bottleneck;
308  }
309 
310  /* take the MAX */
311  if( tree[node].dist_edgetail < nodedist_tail )
312  {
313  tree[node].dist_edgetail = nodedist_tail;
314  }
315 
316  nodedist_tail += tree[node].edgecost;
317 
318  nodedist_head = pathcost - nodedist_tail;
319  assert(GE(nodedist_head, 0.0));
320 
321  /* take the MAX */
322  if( tree[node].dist_edgehead < nodedist_head )
323  {
324  tree[node].dist_edgehead = nodedist_head;
325  }
326 
327  SCIPdebugMessage("node=%d dist_tail=%f dist_head=%f edge %d->%d: \n", node, tree[node].dist_edgetail,
328  tree[node].dist_edgehead, node, head);
329 
330 
331  node = head;
332  }
333 }
334 
335 
336 /** computes bottlenecks */
337 static
339  const GRAPH* graph, /**< the graph */
340  BLCTREE* blctree /**< to be built */
341 )
342 {
343  BLCNODE* RESTRICT mst = blctree->mst;
344  const int* nodes_curr2org = blctree->nodes_curr2org;
345  const int* nodes_org2curr = blctree->nodes_org2curr;
346  const int* nodes_isMarked = graph->mark;
347  const int nnodes_curr = blctree->nnodes_curr;
348 
349  assert(mst);
350  assert(0 <= blctree->root && blctree->root < nnodes_curr);
351  assert(graph_isMarked(graph));
352 
353  for( int node = 0; node < nnodes_curr; node++ )
354  {
355  const int node_org = nodes_curr2org[node];
356 
357  assert(graph_knot_isInRange(graph, node_org));
358  assert(graph->grad[node_org] > 0);
359  assert(!graph_pc_isPc(graph) || !graph_pc_knotIsDummyTerm(graph, node_org));
360 
361  if( blctree->root != node )
362  {
363  /* make i the new root */
364  blctreeEvert(graph, node, blctree);
365  }
366 
367  for( int e = graph->outbeg[node_org]; e != EAT_LAST; e = graph->oeat[e] )
368  {
369  const int head_org = graph->head[e];
370 
371  if( nodes_isMarked[head_org] )
372  {
373  const int head = nodes_org2curr[head_org];
374  assert(0 <= head && head < nnodes_curr);
375 
376  /* is the edge in the tree or already checked? */
377  if( mst[head].head == node || head < node )
378  continue;
379 
380  assert(mst[head].edge != e || mst[head].edge != flipedge(e));
381 
382  SCIPdebugMessage("---CHECK EDGE: %d->%d root=%d \n", node_org, head_org, node);
383 
384  blctreeUpdateRootPath(head, graph->cost[e], blctree);
385  }
386  }
387  }
388 
389  /* NOTE necessary for correct computation of edge state! */
390  if( blctree->root != nodes_org2curr[graph->source] )
391  {
392  blctreeEvert(graph, nodes_org2curr[graph->source], blctree);
393  }
394 }
395 
396 
397 
398 /** sets stage of MST edges */
399 static
401  const GRAPH* graph, /**< the graph */
402  BLCTREE* blctree /**< to be built */
403 )
404 {
405  BLCNODE* RESTRICT mst = blctree->mst;
406  SCIP_Bool* RESTRICT isTermLink = blctree->mstedges_isLink;
407  const int* nodes_curr2org = blctree->nodes_curr2org;
408  const int nnodes_curr = blctree->nnodes_curr;
409  const int blcroot = blctree->root;
410 
411  assert(mst);
412  assert(0 <= blctree->root && blctree->root < nnodes_curr);
413  assert(graph_isMarked(graph));
414  assert(blctree->root == blctree->nodes_org2curr[graph->source]);
415 
416  for( int i = 0; i < nnodes_curr; i++ )
417  isTermLink[i] = FALSE;
418 
419  /* mark all edges from terminals to root */
420  for( int i = 0; i < nnodes_curr; i++ )
421  {
422  const int node_org = nodes_curr2org[i];
423  assert(graph_knot_isInRange(graph, node_org));
424  assert(!graph_pc_isPc(graph) || !graph_pc_knotIsDummyTerm(graph, node_org));
425 
426  if( Is_term(graph->term[node_org]) )
427  {
428  assert(graph->grad[node_org] > 0);
429 
430  for( int node = i; node != blcroot; node = mst[node].head )
431  {
432  assert(0 <= node && node < nnodes_curr);
433 
434  isTermLink[node] = TRUE;
435  }
436  }
437  }
438 
439  assert(!isTermLink[blcroot]);
440 
441 }
442 
443 /** builds MST and sets BLC tree accordingly */
444 static
446  SCIP* scip, /**< SCIP */
447  GRAPH* graph, /**< the graph */
448  BLCTREE* blctree /**< to be built */
449 )
450 {
451  PATH* pmst;
452  BLCNODE* RESTRICT tree = blctree->mst;
453  const int* nodes_curr2org = blctree->nodes_curr2org;
454  const int* nodes_org2curr = blctree->nodes_org2curr;
455  const int nnodes_org = graph_get_nNodes(graph);
456  const int nnodes_curr = blctree->nnodes_curr;
457  blctree->root = nodes_org2curr[graph->source];
458 
459  assert(tree);
460  assert(nnodes_org == blctree->nnodes_org);
461  assert(nnodes_curr > 0);
462  assert(graph->grad[graph->source] > 0);
463  assert(!graph_pc_isMw(graph));
464  assert(!graph_pc_isPcMw(graph) || !graph->extended);
465  assert(!graph_pc_isPcMw(graph) || graph_pc_isRootedPcMw(graph));
466 
467  SCIP_CALL( SCIPallocBufferArray(scip, &pmst, nnodes_org) );
468  graph_path_exec(scip, graph, MST_MODE, graph->source, graph->cost, pmst);
469 
470  /* fill the tree */
471  for( int k_curr = 0; k_curr < nnodes_curr; k_curr++ )
472  {
473  const int k_org = nodes_curr2org[k_curr];
474  const int mstedge = pmst[k_org].edge;
475 
476  assert(graph_knot_isInRange(graph, k_org));
477 
478  if( mstedge >= 0 )
479  {
480  const int revedge = flipedge(mstedge);
481  const int head_curr = nodes_org2curr[graph->head[revedge]];
482 
483  SCIPdebugMessage("MST edge %d->%d \n", k_org, graph->head[revedge]);
484 
485  tree[k_curr].edge = revedge;
486  tree[k_curr].edgecost = graph->cost[revedge];
487  tree[k_curr].head = head_curr;
488  tree[k_curr].dist_edgetail = 0.0;
489  tree[k_curr].dist_edgehead = 0.0;
490  tree[k_curr].edgebottleneck = FARAWAY;
491 
492  assert(k_org != graph->source);
493  assert(k_curr != blctree->root);
494  assert(0 <= head_curr && head_curr < nnodes_curr);
495  assert(graph->tail[tree[k_curr].edge] == k_org);
496  }
497 #ifndef NDEBUG
498  else
499  {
500  assert(k_curr == blctree->root);
501  assert(k_org == graph->source);
502  }
503 #endif
504  }
505 
506  blctreeResetNode(blctree->root, blctree);
507 
508  SCIPfreeBufferArray(scip, &pmst);
509 
510  return SCIP_OKAY;
511 }
512 
513 
514 /** builds BLC tree */
515 static
517  SCIP* scip, /**< SCIP */
518  GRAPH* graph, /**< the graph */
519  BLCTREE* blctree /**< to be built */
520 )
521 {
522  SCIP_CALL( blctreeBuildMst(scip, graph, blctree) );
523  blctreeComputeBottlenecks(graph, blctree);
524  blctreeComputeEdgesState(graph, blctree);
525 
526  return SCIP_OKAY;
527 }
528 
529 
530 /** recursive method for adding node to MST */
531 static
533  const CSR* org_mst, /**< the base MST */
534  const SCIP_Real adjcosts[], /**< (undirected) adjacency costs for new node */
535  int root, /**< the current root */
536  CEDGE new_mst[], /**< new MST */
537  SCIP_Bool new_nodemarked[], /**< array */
538  CEDGE* max_path_edge, /**< pointer to maximum edge on path to new node */
539  int* new_nedges /**< pointer to current number of edges */
540 )
541 {
542  CEDGE root2new = { .tail = root, .head = org_mst->nnodes, .cost = adjcosts[root] };
543  const int* const org_start = org_mst->start;
544  const int* const org_head = org_mst->head;
545  const SCIP_Real* const org_cost = org_mst->cost;
546 
547  assert(new_nodemarked[root]);
548 
549  /* visit all neighbors or root in the original MST */
550  for( int i = org_start[root]; i != org_start[root + 1]; ++i )
551  {
552  const int w = org_head[i];
553 
554  /* node not visited yet? */
555  if( !new_nodemarked[w] )
556  {
557  const SCIP_Real costroot2w = org_cost[i];
558 
559  new_nodemarked[w] = TRUE;
560  dcmstInsert(org_mst, adjcosts, w, new_mst, new_nodemarked, max_path_edge, new_nedges);
561 
562  assert(max_path_edge->tail >= 0);
563  assert(*new_nedges >= 0 && *new_nedges < org_mst->nnodes);
564 
565  if( max_path_edge->cost < costroot2w )
566  {
567  new_mst[(*new_nedges)++] = *max_path_edge;
568 
569  if( costroot2w < root2new.cost )
570  {
571  root2new.tail = root;
572  root2new.head = w;
573  root2new.cost = costroot2w;
574  }
575  }
576  else
577  {
578  const int nedges = (*new_nedges);
579 
580  new_mst[nedges].tail = root;
581  new_mst[nedges].head = w;
582  new_mst[nedges].cost = costroot2w;
583 
584  (*new_nedges)++;
585 
586  if( max_path_edge->cost < root2new.cost )
587  {
588  root2new = *max_path_edge;
589  }
590  }
591  }
592  }
593 
594  *max_path_edge = root2new;
595 }
596 
597 
598 /** add node to MST */
599 static inline
601  const CSR* mst_in, /**< source */
602  const SCIP_Real* adjcosts, /**< (undirected) adjacency costs for new node */
603  DCMST* dmst /**< underlying structure */
604 )
605 {
606  CEDGE max_path_edge = { .tail = -1, .head = -1, .cost = -1.0 };
607  CEDGE* const edgestore = dmst->edgestore;
608  SCIP_Bool* const nodemark = dmst->nodemark;
609  int nedges_new = 0;
610  const int nnodes_in = mst_in->nnodes;
611 
612  assert(nnodes_in >= 1);
613 
614  nodemark[0] = TRUE;
615 
616  for( int i = 1; i < nnodes_in; ++i )
617  nodemark[i] = FALSE;
618 
619  dcmstInsert(mst_in, adjcosts, 0, edgestore, nodemark, &max_path_edge, &nedges_new);
620 
621  assert(nedges_new == nnodes_in - 1);
622 
623  edgestore[nedges_new] = max_path_edge;
624 }
625 
626 
627 /** transforms edge-store to CSR */
628 static inline
630  const DCMST* dmst, /**< underlying structure */
631  CSR* mst_out /**< target */
632 )
633 {
634  const CEDGE* const edgestore = dmst->edgestore;
635  int* const mst_start = mst_out->start;
636  int* const mst_head = mst_out->head;
637  SCIP_Real* const mst_cost = mst_out->cost;
638  const int mst_nnodes = mst_out->nnodes;
639 
640  /* undirected edges */
641  const int mst_nedges = mst_nnodes - 1;
642 
643  assert(mst_nnodes <= dmst->maxnnodes);
644  assert(2 * mst_nedges == mst_out->nedges_max);
645 
646  BMSclearMemoryArray(mst_start, mst_nnodes + 1);
647 
648  for( int i = 0; i < mst_nedges; ++i )
649  {
650  const int v1 = edgestore[i].tail;
651  const int v2 = edgestore[i].head;
652 
653  assert(v1 >= 0 && v1 < mst_nnodes);
654  assert(v2 >= 0 && v2 < mst_nnodes);
655 
656  mst_start[v1]++;
657  mst_start[v2]++;
658  }
659 
660  assert(mst_start[mst_nnodes] == 0);
661 
662  for( int i = 1; i <= mst_nnodes; ++i )
663  {
664  mst_start[i] += mst_start[i - 1];
665  }
666 
667  assert(mst_start[mst_nnodes] == mst_out->nedges_max);
668 
669  for( int i = 0; i < mst_nedges; ++i )
670  {
671  const int v1 = edgestore[i].tail;
672  const int v2 = edgestore[i].head;
673  const SCIP_Real cost = edgestore[i].cost;
674 
675  assert(mst_start[v1] >= 1);
676  assert(mst_start[v2] >= 1);
677 
678  mst_head[--mst_start[v1]] = v2;
679  mst_cost[mst_start[v1]] = cost;
680 
681  mst_head[--mst_start[v2]] = v1;
682  mst_cost[mst_start[v2]] = cost;
683  }
684 }
685 
686 
687 /** gets weight of MST from DCMST store */
688 static inline
690  SCIP* scip, /**< SCIP */
691  int mst_nedges, /**< number of edges */
692  const DCMST* dmst /**< underlying structure */
693 )
694 {
695  const CEDGE* const edgestore = dmst->edgestore;
696  SCIP_Real weight = 0.0;
697 
698  assert(mst_nedges < dmst->maxnnodes);
699 
700  for( int i = 0; i < mst_nedges; ++i )
701  {
702 #ifndef NDEBUG
703  const int v1 = edgestore[i].tail;
704  const int v2 = edgestore[i].head;
705 
706  assert(v1 >= 0 && v1 < dmst->maxnnodes);
707  assert(v2 >= 0 && v2 < dmst->maxnnodes);
708  assert(GE(dmst->edgestore[i].cost, 0.0));
709  assert(LE(dmst->edgestore[i].cost, FARAWAY));
710 #endif
711 
712  weight += edgestore[i].cost;
713  }
714 
715  return weight;
716 }
717 
718 
719 /** sets star position array to initial setting for current star degree */
720 static inline
722  STAR* star /**< the star */
723 )
724 {
725  int* RESTRICT edgesSelectedPos = star->edgesSelectedPos;
726  const int starDegree = star->starDegree;
727 
728  for( int i = 0; i < starDegree; i++ )
729  {
730  edgesSelectedPos[i] = i;
731  }
732 }
733 
734 
735 /** fills array star->edgesSelected by using the current positions */
736 static inline
738  STAR* star /**< the star (in/out) */
739 )
740 {
741  int* const edgesSelected = star->edgesSelected;
742  const int* const edgesSelectedPos = star->edgesSelectedPos;
743  const int* const edgeId = star->edgeId;
744  const int starDegree = star->starDegree;
745 
746  assert(starDegree >= 3);
747 
748  for( int i = 0; i < starDegree; i++ )
749  {
750  const int pos = edgesSelectedPos[i];
751  edgesSelected[i] = edgeId[pos];
752  }
753 }
754 
755 /** copies selected positions into given array */
756 static inline
758  const STAR* star, /**< the star (in/out) */
759  int* posStorage /**< to copy into */
760 )
761 {
762  const int* const edgesSelectedPos = star->edgesSelectedPos;
763  const int starDegree = star->starDegree;
764 
765  assert(starDegree >= 3);
766 
767  for( int i = 0; i < starDegree; i++ )
768  {
769  const int pos = edgesSelectedPos[i];
770  assert(0 <= pos && pos < star->nodeDegree);
771 
772  posStorage[i] = pos;
773  }
774 }
775 
776 
777 /** moves to next star */
778 static inline
780  STAR* star /**< the star (in/out) */
781 )
782 {
783  int pos;
784  const int nodeDegree = star->nodeDegree;
785  const int starDegree = star->starDegree;
786  int* const edgesSelectedPos = star->edgesSelectedPos;
787 
788  assert(3 <= starDegree && starDegree <= nodeDegree);
789 
790  star->starDegreePrev = starDegree;
791  BMScopyMemoryArray(star->edgesSelectedPosPrev, edgesSelectedPos, starDegree);
792 
793 #ifndef NDEBUG
794  for( int i = starDegree; i < nodeDegree; i++ )
795  star->edgesSelectedPosPrev[i] = -1;
796 #endif
797 
798  /* all current positions are stored in edgesSelectedPos[0,...,starDegree-1] */
799 
800  /* check for each position, bottom-up, whether it can be increased without it hitting the border */
801  for( pos = starDegree - 1; pos >= 0; pos-- )
802  {
803  const SCIP_Bool isLastPos = (pos == (starDegree - 1));
804  const int border = isLastPos ? nodeDegree : edgesSelectedPos[pos + 1];
805 
806  /* still space? */
807  if( edgesSelectedPos[pos] < border - 1 )
808  {
809  break;
810  }
811  }
812 
813  if( pos >= 0 )
814  {
815  edgesSelectedPos[pos]++;
816 
817  /* adapt all following positions */
818  for( int i = pos + 1; i < starDegree; i++ )
819  {
820  edgesSelectedPos[i] = edgesSelectedPos[i - 1] + 1;
821  }
822  }
823  else
824  {
825  assert(pos == -1);
826  star->starDegree--;
828  }
829 }
830 
831 
832 /** have we just move past the last star? */
833 static inline
835  const STAR* star /**< the star (in/out) */
836 )
837 {
838  if( star->starDegree <= 2 )
839  {
840  assert(star->starDegree == 2);
841  return TRUE;
842  }
843 
844  return FALSE;
845 }
846 
847 
848 /** adds implication for terminal */
849 static inline
851  SCIP* scip, /**< SCIP data structure */
852  const GRAPH* graph, /**< graph data structure */
853  int term, /**< term */
854  STP_Vectype(int)* nodes_implications /**< array of size |V|; returned with implications per node or NULL */
855 )
856 {
857  SCIP_Real min1 = FARAWAY;
858  SCIP_Real min2 = FARAWAY;
859  const SCIP_Bool isPc = (graph->stp_type == STP_RPCSPG);
860  int min_edge = -1;
861 
862  assert(isPc == graph_pc_isPcMw(graph));
863  assert(Is_term(graph->term[term]));
864 
865  if( isPc )
866  {
867  min1 = graph->prize[term];
868  min2 = graph->prize[term];
869  }
870 
871  for( int e = graph->inpbeg[term]; e != EAT_LAST; e = graph->ieat[e] )
872  {
873  if( graph->cost[e] < min1 )
874  {
875  min_edge = e;
876  min2 = min1;
877  min1 = graph->cost[e];
878  }
879  else if( graph->cost[e] < min2 )
880  {
881  min2 = graph->cost[e];
882  }
883  }
884 
885  assert(min_edge >= 0 || isPc);
886  assert(LE(min1, min2));
887  assert(min_edge == -1 || EQ(graph->cost[min_edge], min1));
888 
889  if( LT(min1, min2) )
890  {
891  const int min_neighbor = graph->tail[min_edge];
892  assert(!isPc || !graph_pc_knotIsDummyTerm(graph, min_neighbor));
893 
894  StpVecPushBack(scip, nodes_implications[min_neighbor], term);
895  SCIPdebugMessage("add implied terminal %d to node %d \n", term, min_neighbor);
896  }
897 }
898 
899 
900 /** removes implication for terminal from neighbor (if implication exists) */
901 static inline
903  const GRAPH* graph, /**< graph data structure */
904  int neighbor, /**< neighbor of term */
905  int term, /**< term */
906  STP_Vectype(int)* nodes_implications, /**< array of size |V|; returned with implications per node or NULL */
907  SCIP_Bool* removed /**< was removed? */
908 )
909 {
910  STP_Vectype(int) neighbor_implications = nodes_implications[neighbor];
911  const int nimps = StpVecGetSize(neighbor_implications);
912  assert(Is_term(graph->term[term]));
913 
914  *removed = FALSE;
915 
916  for( int i = 0; i < nimps; i++ )
917  {
918  const int node = neighbor_implications[i];
919  assert(graph_knot_isInRange(graph, node));
920 
921  if( node == term )
922  {
923  neighbor_implications[i] = neighbor_implications[nimps - 1];
924  StpVecPopBack(neighbor_implications);
925  *removed = TRUE;
926  break;
927  }
928  }
929 }
930 
931 
932 /*
933  * Interface methods
934  */
935 
936 /** gets implied nodes for each node */
938  SCIP* scip, /**< SCIP data structure */
939  const GRAPH* graph, /**< graph data structure */
940  STP_Vectype(int)* nodes_implications /**< array of size |V|; returned with implications per node or NULL */
941 )
942 {
943  const int nnodes = graph_get_nNodes(graph);
944  assert(!graph_pc_isPcMw(graph) || !graph->extended);
945 
946  for( int i = 0; i < nnodes; i++ )
947  {
948  nodes_implications[i] = NULL;
949  }
950 
951  for( int i = 0; i < nnodes; i++ )
952  {
953  if( Is_term(graph->term[i]) )
954  {
955  impliedNodesAddTerm(scip, graph, i, nodes_implications);
956  }
957  }
958 }
959 
960 
961 /** repairs implied nodes list AFTER edge elimination */
963  SCIP* scip, /**< SCIP data structure */
964  const GRAPH* graph, /**< graph data structure */
965  int tail, /**< tail of eliminated edge */
966  int head, /**< head of eliminated edge */
967  STP_Vectype(int)* nodes_implications /**< initialized array of size |V| */
968 )
969 {
970  assert(scip && graph && nodes_implications);
971  assert(graph_knot_isInRange(graph, tail));
972  assert(graph_knot_isInRange(graph, head));
973  assert(!graph_pc_isPcMw(graph) || !graph->extended);
974 
975  if( Is_term(graph->term[tail]) )
976  {
977  SCIP_Bool removed;
978  impliedNodesRemoveTerm(graph, head, tail, nodes_implications, &removed);
979 
980  if( removed )
981  impliedNodesAddTerm(scip, graph, tail, nodes_implications);
982  }
983 
984  if( Is_term(graph->term[head]) )
985  {
986  SCIP_Bool removed;
987  impliedNodesRemoveTerm(graph, tail, head, nodes_implications, &removed);
988 
989  if( removed )
990  impliedNodesAddTerm(scip, graph, head, nodes_implications);
991  }
992 }
993 
994 
995 /** implied nodes list is valid */
997  const GRAPH* graph, /**< graph data structure */
998  const STP_Vectype(int)* nodes_implications /**< initialized array of size |V| */
999 )
1000 {
1001  const int nnodes = graph_get_nNodes(graph);
1002 
1003  assert(nodes_implications);
1004 
1005  for( int i = 0; i < nnodes; i++ )
1006  {
1007  if( graph->grad[i] > 0 )
1008  {
1009  const STP_Vectype(int) implications = nodes_implications[i];
1010  const int nimps = StpVecGetSize(implications);
1011 
1012  for( int j = 0; j < nimps; j++ )
1013  {
1014  SCIP_Bool found = FALSE;
1015  const int impnode = implications[j];
1016  assert(graph_knot_isInRange(graph, impnode));
1017 
1018  for( int e = graph->outbeg[i]; e != EAT_LAST; e = graph->oeat[e] )
1019  {
1020  if( graph->head[e] == impnode )
1021  {
1022  found = TRUE;
1023  break;
1024  }
1025  }
1026 
1027  if( !found )
1028  {
1029  printf("implied node %d from base %d not connected \n", impnode, i);
1030  return FALSE;
1031  }
1032  }
1033 
1034  }
1035  }
1036 
1037  return TRUE;
1038 }
1039 
1040 
1041 /** apply pseudo eliminations provided */
1043  SCIP* scip, /**< SCIP data structure */
1044  const SCIP_Bool* pseudoDelNodes, /**< node with pseudo deletable nodes */
1045  REDCOST* redcostdata, /**< reduced cost data */
1046  GRAPH* graph, /**< graph data structure */
1047  SCIP_Real* offsetp, /**< offset pointer (for PC) */
1048  int* nelims /**< number of eliminations */
1049 )
1050 {
1051  int adjvert[STP_DELPSEUDO_MAXGRAD];
1053  SCIP_Real cutoffsrev[STP_DELPSEUDO_MAXNEDGES];
1054  const PATH* nodeToTermsPaths = redcosts_getNodeToTermsPathsTop(redcostdata);
1055  const SCIP_Real* rootToNodeDist = redcosts_getRootToNodeDistTop(redcostdata);
1056  SCIP_Real* redcost = redcosts_getEdgeCostsTop(redcostdata);
1057  const SCIP_Real cutoffbound = redcosts_getCutoffTop(redcostdata);
1058  const int nnodes = graph_get_nNodes(graph);
1059  SCIP_Bool success;
1060  const SCIP_Bool isPc = graph_pc_isPc(graph);
1061  const SCIP_Bool isExtendedOrg = graph->extended;
1062 
1063  assert(GE(cutoffbound, 0.0));
1064  assert(nodeToTermsPaths && rootToNodeDist && redcost);
1065 
1066  if( isPc )
1067  graph_pc_2orgcheck(scip, graph);
1068 
1069  *nelims = 0;
1070 
1071  for( int degree = 3; degree <= STP_DELPSEUDO_MAXGRAD; degree++ )
1072  {
1073  for( int k = 0; k < nnodes; k++ )
1074  {
1075  SCIP_Real prize = -1.0;
1076  int edgecount = 0;
1077  SCIP_Bool rpc3term = FALSE;
1078 
1079  if( !pseudoDelNodes[k] )
1080  continue;
1081 
1082  if( isPc && degree == 3 && graph_pc_knotIsNonLeafTerm(graph, k) && graph->grad[k] == 3 )
1083  {
1084  rpc3term = TRUE;
1085  prize = graph->prize[k];
1086  }
1087  else if( (degree != graph->grad[k] || Is_anyTerm(graph->term[k])) )
1088  {
1089  continue;
1090  }
1091 
1092  if( rpc3term )
1093  {
1094  for( int e = graph->outbeg[k]; e != EAT_LAST; e = graph->oeat[e] )
1095  {
1096  const int head = graph->head[e];
1097  if( !graph_pc_knotIsDummyTerm(graph, head) )
1098  adjvert[edgecount++] = head;
1099  }
1100  }
1101  else
1102  {
1103  for( int e = graph->outbeg[k]; e != EAT_LAST; e = graph->oeat[e] )
1104  adjvert[edgecount++] = graph->head[e];
1105  }
1106 
1107  assert(edgecount == degree);
1108 
1109  edgecount = 0;
1110  for( int i = 0; i < degree - 1; i++ )
1111  {
1112  const int vert = adjvert[i];
1113  for( int i2 = i + 1; i2 < degree; i2++ )
1114  {
1115  const int vert2 = adjvert[i2];
1116 
1117  assert(edgecount < STP_DELPSEUDO_MAXNEDGES);
1118 
1119  /* NOTE: the new arc vert->ver2 is cut off if its (combined) reduced cost
1120  * is greater than cutoffs[edgecount].
1121  * Analogously for the reverse arc. */
1122  cutoffs[edgecount] = cutoffbound - (rootToNodeDist[vert] + nodeToTermsPaths[vert2].dist);
1123  cutoffsrev[edgecount] = cutoffbound - (rootToNodeDist[vert2] + nodeToTermsPaths[vert].dist);
1124 
1125  edgecount++;
1126  }
1127  }
1128 
1129  assert(edgecount > 0);
1130 
1131 #ifdef SCIP_DEBUG
1132  SCIPdebugMessage("try pseudo-deletion of ");
1133  graph_knot_printInfo(graph, k);
1134 #endif
1135 
1136  /* now try to eliminate */
1137  SCIP_CALL( graph_knot_delPseudo(scip, graph, redcost, cutoffs, cutoffsrev, k, redcostdata, &success) );
1138 
1139  if( success )
1140  {
1141  (*nelims)++;
1142  graph->mark[k] = FALSE;
1143 
1144  SCIPdebugMessage("deletion successful! \n");
1145 
1146  if( rpc3term )
1147  {
1148  assert(isPc);
1149  assert(offsetp);
1150  assert(GE(prize, 0.0));
1151 
1152  *offsetp += prize;
1153  }
1154  }
1155  }
1156  }
1157 
1158  assert(graph_valid(scip, graph));
1159 
1160  if( isPc && isExtendedOrg != graph->extended )
1161  graph_pc_2trans(scip, graph);
1162 
1163  return SCIP_OKAY;
1164 }
1165 
1166 
1167 /** initializes BLC tree */
1169  SCIP* scip, /**< SCIP */
1170  GRAPH* graph, /**< the graph */
1171  BLCTREE** blctree /**< to be initialized */
1172 )
1173 {
1174  assert(scip && graph && blctree);
1175 
1176  graph_mark(graph);
1177 
1178  SCIP_CALL( blctreeInitPrimitives(scip, graph, blctree) );
1179  SCIP_CALL( blctreeInitBottlenecks(scip, graph, *blctree) );
1180 
1181  return SCIP_OKAY;
1182 }
1183 
1184 
1185 /** rebuilds BLC tree (needs to be initializes) */
1187  SCIP* scip, /**< SCIP */
1188  GRAPH* graph, /**< the graph */
1189  BLCTREE* blctree /**< to be initialized */
1190 )
1191 {
1192  assert(scip && graph && blctree);
1193 
1194  SCIP_CALL( blctreeInitBottlenecks(scip, graph, blctree) );
1195 
1196  return SCIP_OKAY;
1197 }
1198 
1199 
1200 /** frees BLC tree */
1202  SCIP* scip, /**< SCIP */
1203  BLCTREE** blctree /**< to be freed */
1204 )
1205 {
1206  assert(scip && blctree);
1207 
1208  SCIPfreeMemoryArray(scip, &((*blctree)->nodes_org2curr));
1209  SCIPfreeMemoryArray(scip, &((*blctree)->nodes_curr2org));
1210  SCIPfreeMemoryArray(scip, &((*blctree)->mstedges_isLink));
1211  SCIPfreeMemoryArray(scip, &((*blctree)->mst));
1212 
1213  SCIPfreeMemory(scip, blctree);
1214 }
1215 
1216 
1217 /** gets number of BLC MST edges */
1219  const BLCTREE* blctree /**< BLC tree */
1220 )
1221 {
1222  assert(blctree);
1223  assert(blctree->nnodes_curr > 0);
1224 
1225  return blctree->nnodes_curr - 1;
1226 }
1227 
1228 
1229 /** gets BLC MST edges */
1231  const GRAPH* graph, /**< graph */
1232  const BLCTREE* blctree, /**< BLC tree */
1233  int* edgelist /**< of size nodes - 1 */
1234 )
1235 {
1236  const BLCNODE* mst;
1237  int nodecount;
1238  const int nnodes_curr = blctree->nnodes_curr;
1239 
1240  assert(edgelist);
1241  assert(graph_get_nNodes(graph) == blctree->nnodes_org);
1242 
1243  mst = blctree->mst;
1244  nodecount = 0;
1245 
1246  for( int i = 0; i < nnodes_curr; ++i )
1247  {
1248  const int edge = mst[i].edge;
1249 
1250  if( edge >= 0 )
1251  {
1252  edgelist[nodecount++] = edge;
1253  }
1254  else
1255  {
1256  assert(i == blctree->root);
1257  assert(edge == UNKNOWN);
1258  }
1259  }
1260 
1261  assert(nodecount == nnodes_curr - 1);
1262 }
1263 
1264 
1265 /** gets BLC MST edges (maximum) distances from tail to cut */
1267  const GRAPH* graph, /**< graph */
1268  const BLCTREE* blctree, /**< BLC tree */
1269  SCIP_Real* RESTRICT tails2CutDist, /**< of size nodes - 1 */
1270  SCIP_Real* RESTRICT heads2CutDist /**< of size nodes - 1 */
1271 )
1272 {
1273  const BLCNODE* mst;
1274  int nodecount;
1275  const int nnodes_curr = blctree->nnodes_curr;
1276 
1277  assert(tails2CutDist && heads2CutDist);
1278  assert(graph_get_nNodes(graph) == blctree->nnodes_org);
1279 
1280  mst = blctree->mst;
1281  nodecount = 0;
1282 
1283  for( int i = 0; i < nnodes_curr; ++i )
1284  {
1285  const int edge = mst[i].edge;
1286 
1287  if( edge >= 0 )
1288  {
1289  const SCIP_Real taildist = mst[i].dist_edgetail;
1290  const SCIP_Real headdist = mst[i].dist_edgehead;
1291  assert(GE(taildist, 0.0));
1292  assert(GE(headdist, 0.0));
1293 
1294 #ifdef SCIP_DEBUG
1295  graph_edge_printInfo(graph, edge);
1296  printf("taildist=%f headdist=%f \n", taildist, headdist);
1297 #endif
1298 
1299  tails2CutDist[nodecount] = taildist;
1300  heads2CutDist[nodecount++] = headdist;
1301  }
1302  else
1303  {
1304  assert(i == blctree->root);
1305  assert(edge == UNKNOWN);
1306  }
1307  }
1308 
1309  assert(nodecount == nnodes_curr - 1);
1310 }
1311 
1312 
1313 /** returns BLC MST edges state.
1314  * I.e. whether the ede is between two terminal or not */
1316  const GRAPH* graph, /**< graph */
1317  const BLCTREE* blctree, /**< BLC tree */
1318  SCIP_Bool* statelist /**< of size nodes - 1 */
1319 )
1320 {
1321  const BLCNODE* mst = blctree->mst;
1322  int nodecount = 0;
1323  const int nnodes_curr = blctree->nnodes_curr;
1324 
1325  assert(graph && blctree && statelist);
1326  assert(graph_get_nNodes(graph) == blctree->nnodes_org);
1327  assert(blctree->mstedges_isLink);
1328 
1329  for( int i = 0; i < nnodes_curr; ++i )
1330  {
1331  const int edge = mst[i].edge;
1332 
1333  if( edge >= 0 )
1334  {
1335  statelist[nodecount++] = blctree->mstedges_isLink[i];
1336  }
1337  else
1338  {
1339  assert(i == blctree->root);
1340  assert(edge == UNKNOWN);
1341  }
1342  }
1343 
1344  assert(nodecount == nnodes_curr - 1);
1345 }
1346 
1347 
1348 /** gets BLC MST bottleneck costs */
1350  const GRAPH* graph, /**< graph */
1351  const BLCTREE* blctree, /**< BLC tree */
1352  SCIP_Real* costlist /**< of size nodes - 1 */
1353 )
1354 {
1355  const BLCNODE* mst;
1356  int nodecount;
1357  const int nnodes_curr = blctree->nnodes_curr;
1358 
1359  assert(blctree && costlist);
1360  assert(graph_get_nNodes(graph) == blctree->nnodes_org);
1361 
1362  mst = blctree->mst;
1363  nodecount = 0;
1364 
1365  for( int i = 0; i < nnodes_curr; ++i )
1366  {
1367  const int edge = mst[i].edge;
1368 
1369  if( edge >= 0 )
1370  {
1371  costlist[nodecount++] = mst[i].edgebottleneck;
1372  }
1373  else
1374  {
1375  assert(i == blctree->root);
1376  assert(edge == UNKNOWN);
1377  }
1378  }
1379 
1380  assert(nodecount == nnodes_curr - 1);
1381 }
1382 
1383 
1384 /** initializes dynamic MST structure */
1386  SCIP* scip, /**< SCIP */
1387  int maxnnodes, /**< maximum number of nodes that can be handled */
1388  DCMST** dcmst /**< to be initialized */
1389 )
1390 {
1391  DCMST* mst;
1392 
1393  assert(scip && dcmst);
1394  assert(maxnnodes >= 1);
1395 
1396  SCIP_CALL( SCIPallocMemory(scip, dcmst) );
1397 
1398  mst = *dcmst;
1399 
1400  mst->maxnnodes = maxnnodes;
1401  SCIP_CALL( SCIPallocMemoryArray(scip, &(mst->edgestore), maxnnodes) );
1402  SCIP_CALL( SCIPallocMemoryArray(scip, &(mst->adjcost_buffer), maxnnodes) );
1403  SCIP_CALL( SCIPallocMemoryArray(scip, &(mst->nodemark), maxnnodes) );
1404 
1405 
1406  return SCIP_OKAY;
1407 }
1408 
1409 
1410 /** adds node to CSR "mst_in" and saves result in "mst_out" */
1412  SCIP* scip, /**< SCIP */
1413  const CSR* mst_in, /**< source */
1414  const SCIP_Real* adjcosts, /**< (undirected) adjacency costs for new node */
1415  DCMST* dmst, /**< underlying structure */
1416  CSR* mst_out /**< target */
1417 )
1418 {
1419  assert(mst_in && adjcosts && dmst && mst_out);
1420 
1421  assert(reduce_dcmstMstIsValid(scip, mst_in));
1422 
1423  assert(mst_out->nnodes == mst_in->nnodes + 1);
1424  assert(mst_out->nedges_max == mst_in->nedges_max + 2);
1425  assert(mst_in->nnodes < dmst->maxnnodes);
1426 
1427  dcmstAddNode(mst_in, adjcosts, dmst);
1428 
1429  dcmstGetCSRfromStore(dmst, mst_out);
1430 
1431  assert(mst_out->nnodes == mst_in->nnodes + 1);
1432  assert(reduce_dcmstMstIsValid(scip, mst_out));
1433 }
1434 
1435 
1436 /** Adds node to CSR "mst".
1437  * NOTE: There needs to be enough space in CSR arrays for one more node! */
1439  SCIP* scip, /**< SCIP */
1440  const SCIP_Real* adjcosts, /**< (undirected) adjacency costs for new node */
1441  DCMST* dmst, /**< underlying structure */
1442  CSR* mst /**< source/target */
1443 )
1444 {
1445  assert(mst && adjcosts && dmst);
1446 
1447  assert(reduce_dcmstMstIsValid(scip, mst));
1448  assert(mst->nnodes < dmst->maxnnodes);
1449 
1450  dcmstAddNode(mst, adjcosts, dmst);
1451 
1452  mst->nnodes += 1;
1453  mst->nedges_max += 2;
1454 
1455  dcmstGetCSRfromStore(dmst, mst);
1456 
1457  assert(reduce_dcmstMstIsValid(scip, mst));
1458 }
1459 
1460 /** computes MST on 0 node */
1462  SCIP* scip, /**< SCIP */
1463  CSR* mst /**< MST */
1464 )
1465 {
1466  int* const start = mst->start;
1467 
1468  assert(mst->nnodes == 0);
1469  assert(mst->nedges_max == 0);
1470 
1471  start[0] = 0;
1472 
1473  assert(reduce_dcmstMstIsValid(scip, mst));
1474  assert(EQ(0.0, reduce_dcmstGetWeight(scip, mst)));
1475 }
1476 
1477 
1478 /** computes MST on 1 node */
1480  SCIP* scip, /**< SCIP */
1481  CSR* mst /**< MST */
1482 )
1483 {
1484  int* const start = mst->start;
1485 
1486  assert(mst->nnodes == 1);
1487  assert(mst->nedges_max == 0);
1488 
1489  start[0] = 0;
1490  start[1] = 0;
1491 
1492  assert(reduce_dcmstMstIsValid(scip, mst));
1493  assert(EQ(0.0, reduce_dcmstGetWeight(scip, mst)));
1494 }
1495 
1496 
1497 /** computes MST on 2 nodes */
1499  SCIP* scip, /**< SCIP */
1500  SCIP_Real edgecost, /**< edge cost */
1501  CSR* mst /**< MST */
1502 )
1503 {
1504  SCIP_Real* const cost = mst->cost;
1505  int* const start = mst->start;
1506  int* const head = mst->head;
1507 
1508  assert(edgecost > 0.0);
1509  assert(mst->nnodes == 2);
1510  assert(mst->nedges_max == 2);
1511 
1512  start[0] = 0;
1513  start[1] = 1;
1514  start[2] = 2;
1515 
1516  head[0] = 1;
1517  head[1] = 0;
1518 
1519  cost[0] = edgecost;
1520  cost[1] = edgecost;
1521 
1522  assert(reduce_dcmstMstIsValid(scip, mst));
1523  assert(EQ(edgecost, reduce_dcmstGetWeight(scip, mst)));
1524 }
1525 
1526 
1527 /** computes MST on 3 nodes */
1529  SCIP* scip, /**< SCIP */
1530  SCIP_Real edgecost01, /**< edge cost */
1531  SCIP_Real edgecost02, /**< edge cost */
1532  SCIP_Real edgecost12, /**< edge cost */
1533  CSR* mst /**< MST */
1534 )
1535 {
1536  assert(0 && "implement me");
1537 }
1538 
1539 
1540 /** gets weight of MST extended along given vertex */
1542  SCIP* scip, /**< SCIP */
1543  const CSR* mst, /**< MST for which to compute extended weight */
1544  const SCIP_Real* adjcosts, /**< (undirected) adjacency costs for new node */
1545  DCMST* dmst /**< underlying structure */
1546 )
1547 {
1548  SCIP_Real weight;
1549 #ifndef NDEBUG
1550  /* since we have a tree, |E_{ext}| = |E| + 1 = |V| */
1551  const int nedges_ext = mst->nnodes;
1552 #endif
1553 
1554  assert(scip && adjcosts && dmst);
1555  assert(reduce_dcmstMstIsValid(scip, mst));
1556  assert(mst->nedges_max % 2 == 0);
1557  assert((mst->nedges_max / 2) + 1 == nedges_ext);
1558 
1559  dcmstAddNode(mst, adjcosts, dmst);
1560 
1561  weight = dcmstGetWeightFromStore(scip, mst->nnodes, dmst);
1562 
1563  if( GT(weight, FARAWAY) )
1564  weight = FARAWAY;
1565 
1566  assert(GE(weight, 0.0));
1567 
1568  return weight;
1569 }
1570 
1571 
1572 /** gets weight of MST */
1574  SCIP* scip, /**< SCIP */
1575  const CSR* mst_in /**< source */
1576 )
1577 {
1578  SCIP_Real weight = 0.0;
1579  const int nedges = mst_in->nedges_max;
1580  const SCIP_Real* cost = mst_in->cost;
1581 
1582  assert(scip);
1583  assert(reduce_dcmstMstIsValid(scip, mst_in));
1584 
1585  for( int i = 0; i < nedges; i++ )
1586  {
1587  assert(cost[i] >= 0.0);
1588 
1589  weight += cost[i];
1590  }
1591 
1592  weight /= 2.0;
1593 
1594  if( GT(weight, FARAWAY) )
1595  weight = FARAWAY;
1596 
1597  assert(GE(weight, 0.0));
1598 
1599  return weight;
1600 }
1601 
1602 
1603 /** returns maximum number of nodes */
1605  const DCMST* dmst /**< underlying structure */
1606 )
1607 {
1608  assert(dmst);
1609 
1610  return dmst->maxnnodes;
1611 }
1612 
1613 
1614 /** Returns buffer of size 'reduce_dcmstGetMaxnnodes'.
1615  * NOTE: buffer is never used within any other function, apart from allocation and freeing.
1616  * NOTE: in debug mode the array is initialized to -1.0 */
1618  const DCMST* dmst /**< underlying structure */
1619 )
1620 {
1621  assert(dmst);
1622  assert(dmst->adjcost_buffer);
1623 
1624 #ifndef NDEBUG
1625  for( int i = 0; i < dmst->maxnnodes; i++ )
1626  dmst->adjcost_buffer[i] = -1.0;
1627 #endif
1628 
1629  return dmst->adjcost_buffer;
1630 }
1631 
1632 
1633 /** frees dynamic MST structure */
1635  SCIP* scip, /**< SCIP */
1636  DCMST** dcmst /**< to be initialized */
1637 )
1638 {
1639  assert(scip && dcmst);
1640 
1641  SCIPfreeMemoryArray(scip, &((*dcmst)->nodemark));
1642  SCIPfreeMemoryArray(scip, &((*dcmst)->adjcost_buffer));
1643  SCIPfreeMemoryArray(scip, &((*dcmst)->edgestore));
1644 
1645  SCIPfreeMemory(scip, dcmst);
1646 }
1647 
1648 
1649 /** is the CSR a valid MST on any underlying graph (with number of nodes and edges of the CSR)? */
1651  SCIP* scip, /**< SCIP */
1652  const CSR* cmst /**< the MST candidate */
1653 )
1654 {
1655  SCIP_Bool* visited;
1656  const int* const head_csr = cmst->head;
1657  const int nnodes = cmst->nnodes;
1658  SCIP_Bool isValid = TRUE;
1659 
1660 #ifndef NDEBUG
1661  const int* const start_csr = cmst->start;
1662 #endif
1663 
1664  if( nnodes == 0 )
1665  {
1666  assert(cmst->nedges_max == 0);
1667  assert(start_csr[0] == 0);
1668 
1669  return TRUE;
1670  }
1671 
1672  assert(nnodes >= 1);
1673  assert(cmst->nedges_max % 2 == 0);
1674  assert(start_csr[0] == 0);
1675 
1676  if( !graph_csr_isValid(cmst, FALSE) )
1677  {
1678  SCIPdebugMessage("CSR is broken! \n");
1679  return FALSE;
1680  }
1681 
1682  if( cmst->nnodes != (cmst->nedges_max / 2) + 1 )
1683  {
1684  SCIPdebugMessage("wrong nodes/edges ratio \n");
1685  return FALSE;
1686  }
1687 
1688  if( nnodes == 1 )
1689  {
1690  return TRUE;
1691  }
1692 
1693  SCIP_CALL_ABORT( SCIPallocMemoryArray(scip, &visited, nnodes) );
1694 
1695  for( int i = 0; i < nnodes; i++ )
1696  visited[i] = FALSE;
1697 
1698  for( int i = 0; i < cmst->nedges_max; i++ )
1699  {
1700  const int head = head_csr[i];
1701 
1702  assert(head >= 0 && head < nnodes);
1703 
1704  visited[head] = TRUE;
1705  }
1706 
1707  for( int i = 0; i < nnodes; i++ )
1708  {
1709  if( !visited[i] )
1710  {
1711  SCIPdebugMessage("mst does not contain node %d \n", i);
1712 
1713  isValid = FALSE;
1714  break;
1715  }
1716  }
1717 
1718  SCIPfreeMemoryArray(scip, &visited);
1719 
1720  return isValid;
1721 }
1722 
1723 
1724 /** initializes STAR structure */
1726  SCIP* scip, /**< SCIP */
1727  int maxdegree, /**< maximum node degree that can be handled */
1728  STAR** star /**< the star */
1729 )
1730 {
1731  STAR* s;
1732 
1733  assert(scip && star);
1734  assert(maxdegree >= 3);
1735 
1736  SCIP_CALL( SCIPallocMemory(scip, star) );
1737 
1738  s = *star;
1739 
1740  s->starcenter = -1;
1741  s->nodeDegree = -1;
1742  s->starDegree = -1;
1743  s->nedgesPromising = -1;
1744  s->maxNodeDegree = maxdegree;
1745  s->allStarsChecked = FALSE;
1746  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgeId), maxdegree) );
1747  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgesSelected), maxdegree) );
1748  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgesSelectedPos), maxdegree) );
1749  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgesSelectedPosPrev), maxdegree) );
1750  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgeIsFailed), maxdegree) );
1751  SCIP_CALL( SCIPallocMemoryArray(scip, &(s->edgesPromising), maxdegree) );
1752 
1753  return SCIP_OKAY;
1754 }
1755 
1756 
1757 /** frees STAR structure */
1759  SCIP* scip, /**< SCIP */
1760  STAR** star /**< the star */
1761 )
1762 {
1763  STAR* s;
1764  assert(scip && star);
1765 
1766  s = *star;
1767  assert(s);
1768 
1769  SCIPfreeMemoryArray(scip, &(s->edgesPromising));
1770  SCIPfreeMemoryArray(scip, &(s->edgeIsFailed));
1773  SCIPfreeMemoryArray(scip, &(s->edgesSelected));
1774  SCIPfreeMemoryArray(scip, &(s->edgeId));
1775 
1776  SCIPfreeMemory(scip, star);
1777 }
1778 
1779 
1780 /** resets star data structure with new node data */
1782  const GRAPH* g, /**< graph */
1783  int node, /**< the node (degree <= STP_DELPSEUDO_MAXGRAD) */
1784  STAR* star /**< the star */
1785 )
1786 {
1787  assert(g && star);
1788  assert(0 <= node && node < g->knots);
1789  assert(g->grad[node] <= star->maxNodeDegree);
1790 
1791  star->nodeDegree = g->grad[node];
1792  star->starDegree = star->nodeDegree;
1793  star->starDegreePrev = -1;
1794  star->allStarsChecked = FALSE;
1795  star->starcenter = node;
1796  star->nedgesPromising = g->grad[node];
1797 
1798  for( int e = g->outbeg[node], i = 0; e != EAT_LAST; e = g->oeat[e], i++ )
1799  {
1800  assert(i < star->nodeDegree);
1801  star->edgeId[i] = e;
1802  star->edgeIsFailed[i] = FALSE;
1803  }
1804 
1805 #ifndef NDEBUG
1806  for( int i = 0; i < star->nodeDegree; i++ )
1807  star->edgesSelectedPosPrev[i] = -1;
1808 #endif
1809 
1810  /* initially, select the entire star */
1812 }
1813 
1814 
1815 /** resets star data structure with explicitely given edges */
1817  const GRAPH* g, /**< graph */
1818  const STP_Vectype(int) staredges, /**< the edges */
1819  STAR* star /**< the star */
1820 )
1821 {
1822  const int nedges = StpVecGetSize(staredges);
1823 
1824  assert(3 <= nedges && nedges <= star->maxNodeDegree);
1825 
1826  star->nodeDegree = nedges;
1827  star->starDegree = star->nodeDegree;
1828  star->starDegreePrev = -1;
1829  star->allStarsChecked = FALSE;
1830  star->starcenter = -1;
1831  star->nedgesPromising = nedges;
1832 
1833  for( int i = 0; i < nedges; i++ )
1834  {
1835  const int edge = staredges[i];
1836  assert(graph_edge_isInRange(g, edge));
1837 
1838  star->edgeId[i] = edge;
1839  star->edgeIsFailed[i] = FALSE;
1840  }
1841 
1842 #ifndef NDEBUG
1843  for( int i = 0; i < star->nodeDegree; i++ )
1844  star->edgesSelectedPosPrev[i] = -1;
1845 #endif
1846 
1847  /* initially, select the entire star */
1849 }
1850 
1851 
1852 /** gets center */
1854  const STAR* star /**< the star (in/out) */
1855 )
1856 {
1857  assert(star);
1858 
1859  return star->starcenter;
1860 }
1861 
1862 /** gets next star */
1864  STAR* star, /**< the star (in/out) */
1865  int* nedges /**< number of edges of next star (out) */
1866 )
1867 {
1868  assert(star && nedges);
1869  assert(!reduce_starAllAreChecked(star));
1870 
1871  *nedges = star->starDegree;
1874 
1875  /* just finished? */
1876  if( starIsDeg2(star) )
1877  star->allStarsChecked = TRUE;
1878 
1879  assert(3 <= *nedges && *nedges <= star->maxNodeDegree);
1880 
1881  return star->edgesSelected;
1882 }
1883 
1884 
1885 /** gets next star */
1887  STAR* star, /**< the star (in/out) */
1888  int* position, /**< array to store the positions */
1889  int* nedges /**< number of edges of next star (out) */
1890 )
1891 {
1892  assert(star);
1893  assert(!reduce_starAllAreChecked(star));
1894 
1895  if( nedges )
1896  {
1897  *nedges = star->starDegree;
1898  }
1899 
1901  starSelectedPositionsCopy(star, position);
1903 
1904  /* just finished? */
1905  if( starIsDeg2(star) )
1906  star->allStarsChecked = TRUE;
1907 
1908  if( nedges )
1909  {
1910  assert(3 <= *nedges && *nedges <= star->maxNodeDegree);
1911  }
1912 
1913  return star->edgesSelected;
1914 }
1915 
1916 
1917 /** gets ruled out edges after termination */
1919  STAR* star, /**< the star */
1920  int* nedges /**< number of ruled-out edges */
1921 )
1922 {
1923  int count = 0;
1924 
1925  assert(star);
1926  assert(star->nodeDegree >= 0);
1927  assert(reduce_starAllAreChecked(star));
1928 
1929  for( int i = 0; i < star->nodeDegree; i++ )
1930  {
1931  if( !star->edgeIsFailed[i] )
1932  {
1933  const int edge = star->edgeId[i];
1934  assert(edge >= 0);
1935 
1936  star->edgesPromising[count++] = edge;
1937  }
1938  }
1939 
1940  assert(count == star->nedgesPromising);
1941  *nedges = count;
1942 
1943  return star->edgesPromising;
1944 }
1945 
1946 
1947 /** sets current star to ruled-out */
1949  STAR* star /**< the star */
1950 )
1951 {
1952  assert(star);
1953  assert(!reduce_starAllAreChecked(star));
1954 
1955  /* do nothing ... */
1956 }
1957 
1958 
1959 /** sets current star to failed */
1961  STAR* star /**< the star */
1962 )
1963 {
1964  int nedges;
1965 
1966  assert(star);
1967 
1968  nedges = star->starDegreePrev;
1969  assert(nedges >= 0);
1970 
1971  for( int i = 0; i < nedges; i++ )
1972  {
1973  const int pos = star->edgesSelectedPosPrev[i];
1974 
1975  assert(pos >= 0);
1976  assert(pos < star->nodeDegree);
1977 
1978  if( !star->edgeIsFailed[pos] )
1979  {
1980  star->edgeIsFailed[pos] = TRUE;
1981  star->nedgesPromising--;
1982 
1983  assert(star->nedgesPromising >= 0);
1984  }
1985  }
1986 }
1987 
1988 
1989 /** are there edge that might still be ruled out? */
1991  const STAR* star /**< the star */
1992 )
1993 {
1994  assert(star);
1995  assert(star->nedgesPromising >= 0);
1996 
1997  return (star->nedgesPromising > 0);
1998 }
1999 
2000 
2001 /** have all stars been checked? */
2003  const STAR* star /**< the star */
2004 )
2005 {
2006  assert(star);
2007 
2008  return star->allStarsChecked;
2009 }
void reduce_blctreeGetMstEdgesToCutDist(const GRAPH *graph, const BLCTREE *blctree, SCIP_Real *RESTRICT tails2CutDist, SCIP_Real *RESTRICT heads2CutDist)
Definition: reduce_util.c:1266
#define STP_Vectype(type)
Definition: stpvector.h:44
SCIP_RETCODE reduce_blctreeInit(SCIP *scip, GRAPH *graph, BLCTREE **blctree)
Definition: reduce_util.c:1168
int * edgesSelectedPos
Definition: reduce_util.c:59
int reduce_starGetCenter(const STAR *star)
Definition: reduce_util.c:1853
#define STP_DELPSEUDO_MAXGRAD
Definition: graphdefs.h:79
#define StpVecGetSize(vec)
Definition: stpvector.h:139
SCIP_Bool graph_pc_isMw(const GRAPH *)
int *RESTRICT head
Definition: graphdefs.h:224
static void starSelectedPositionsCopy(const STAR *star, int *posStorage)
Definition: reduce_util.c:757
int * head
Definition: graphdefs.h:141
int source
Definition: graphdefs.h:195
SCIP_Bool graph_pc_isRootedPcMw(const GRAPH *)
#define Is_term(a)
Definition: graphdefs.h:102
void reduce_dcmstGet3NodeMst(SCIP *scip, SCIP_Real edgecost01, SCIP_Real edgecost02, SCIP_Real edgecost12, CSR *mst)
Definition: reduce_util.c:1528
SCIP_Bool * edgeIsFailed
Definition: reduce_util.c:55
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip_mem.h:71
signed int edge
Definition: graphdefs.h:287
SCIP_Bool graph_valid(SCIP *, const GRAPH *)
Definition: graph_base.c:1480
#define STP_DELPSEUDO_MAXNEDGES
Definition: graphdefs.h:80
void reduce_dcmstGet2NodeMst(SCIP *scip, SCIP_Real edgecost, CSR *mst)
Definition: reduce_util.c:1498
SCIP_Bool reduce_starAllAreChecked(const STAR *star)
Definition: reduce_util.c:2002
SCIP_Real redcosts_getCutoffTop(const REDCOST *redcostdata)
Definition: redcosts.c:300
const int * reduce_starGetNextAndPosition(STAR *star, int *position, int *nedges)
Definition: reduce_util.c:1886
static void starSelectedEdgesUpdate(STAR *star)
Definition: reduce_util.c:737
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:55
void graph_path_exec(SCIP *, const GRAPH *, int, int, const SCIP_Real *, PATH *)
Definition: graph_path.c:541
void graph_mark(GRAPH *)
Definition: graph_base.c:1130
SCIP_RETCODE reduce_starInit(SCIP *scip, int maxdegree, STAR **star)
Definition: reduce_util.c:1725
SCIP_Bool reduce_impliedNodesIsValid(const GRAPH *graph, const STP_Vectype(int) *nodes_implications)
Definition: reduce_util.c:996
static SCIP_RETCODE blctreeBuildMst(SCIP *scip, GRAPH *graph, BLCTREE *blctree)
Definition: reduce_util.c:445
SCIP_Real reduce_dcmstGetWeight(SCIP *scip, const CSR *mst_in)
Definition: reduce_util.c:1573
void graph_knot_printInfo(const GRAPH *, int)
Definition: graph_stats.c:151
static void blctreeUpdateRootPath(int startnode, SCIP_Real bottleneck, BLCTREE *blctree)
Definition: reduce_util.c:282
static SCIP_RETCODE blctreeBuildNodeMap(SCIP *scip, const GRAPH *graph, BLCTREE *RESTRICT blctree)
Definition: reduce_util.c:103
#define FALSE
Definition: def.h:87
struct bottleneck_link_cut_node BLCNODE
SCIP_Real * reduce_dcmstGetAdjcostBuffer(const DCMST *dmst)
Definition: reduce_util.c:1617
void reduce_blctreeGetMstEdgesState(const GRAPH *graph, const BLCTREE *blctree, SCIP_Bool *statelist)
Definition: reduce_util.c:1315
int *RESTRICT inpbeg
Definition: graphdefs.h:202
SCIP_Bool reduce_starHasPromisingEdges(const STAR *star)
Definition: reduce_util.c:1990
SCIP_Real * cost
Definition: graphdefs.h:142
#define TRUE
Definition: def.h:86
SCIP_Real reduce_dcmstGetExtWeight(SCIP *scip, const CSR *mst, const SCIP_Real *adjcosts, DCMST *dmst)
Definition: reduce_util.c:1541
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
struct complete_edge CEDGE
#define StpVecPopBack(vec)
Definition: stpvector.h:182
#define EAT_LAST
Definition: graphdefs.h:58
#define SCIPdebugMessage
Definition: pub_message.h:87
#define FARAWAY
Definition: graphdefs.h:89
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
int * start
Definition: graphdefs.h:140
void reduce_blctreeGetMstEdges(const GRAPH *graph, const BLCTREE *blctree, int *edgelist)
Definition: reduce_util.c:1230
int reduce_dcmstGetMaxnnodes(const DCMST *dmst)
Definition: reduce_util.c:1604
void reduce_starCurrentSetFailed(STAR *star)
Definition: reduce_util.c:1960
const int * reduce_starGetNext(STAR *star, int *nedges)
Definition: reduce_util.c:1863
int *RESTRICT mark
Definition: graphdefs.h:198
int reduce_blctreeGetMstNedges(const BLCTREE *blctree)
Definition: reduce_util.c:1218
SCIP_RETCODE reduce_blctreeRebuild(SCIP *scip, GRAPH *graph, BLCTREE *blctree)
Definition: reduce_util.c:1186
void reduce_dcmstGet1NodeMst(SCIP *scip, CSR *mst)
Definition: reduce_util.c:1479
void reduce_starResetWithEdges(const GRAPH *g, const STP_Vectype(int) staredges, STAR *star)
Definition: reduce_util.c:1816
SCIP_VAR * w
Definition: circlepacking.c:58
int *RESTRICT oeat
Definition: graphdefs.h:231
#define LE(a, b)
Definition: portab.h:83
#define GE(a, b)
Definition: portab.h:85
void graph_pc_2trans(SCIP *, GRAPH *)
SCIP_Bool extended
Definition: graphdefs.h:267
int stp_type
Definition: graphdefs.h:264
void graph_get_nVET(const GRAPH *, int *, int *, int *)
Definition: graph_stats.c:571
void reduce_dcmstGet0NodeMst(SCIP *scip, CSR *mst)
Definition: reduce_util.c:1461
void reduce_dcmstFree(SCIP *scip, DCMST **dcmst)
Definition: reduce_util.c:1634
SCIP_Real * redcosts_getEdgeCostsTop(const REDCOST *redcostdata)
Definition: redcosts.c:202
int * edgesSelectedPosPrev
Definition: reduce_util.c:60
SCIP_Real * prize
Definition: graphdefs.h:210
static SCIP_RETCODE blctreeInitPrimitives(SCIP *scip, const GRAPH *graph, BLCTREE **blctree)
Definition: reduce_util.c:155
int nedges_max
Definition: graphdefs.h:144
SCIP_Real dist
Definition: graphdefs.h:286
int *RESTRICT grad
Definition: graphdefs.h:201
static SCIP_Bool starIsDeg2(const STAR *star)
Definition: reduce_util.c:834
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE graph_knot_delPseudo(SCIP *, GRAPH *, const SCIP_Real *, const SCIP_Real *, const SCIP_Real *, int, REDCOST *, SCIP_Bool *)
static SCIP_Real blctreeGetRootPathCost(int startnode, const BLCTREE *blctree)
Definition: reduce_util.c:253
#define EQ(a, b)
Definition: portab.h:79
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
#define MST_MODE
Definition: graphdefs.h:98
SCIP_RETCODE reduce_applyPseudoDeletions(SCIP *scip, const SCIP_Bool *pseudoDelNodes, REDCOST *redcostdata, GRAPH *graph, SCIP_Real *offsetp, int *nelims)
Definition: reduce_util.c:1042
static void blctreeComputeBottlenecks(const GRAPH *graph, BLCTREE *blctree)
Definition: reduce_util.c:338
#define LT(a, b)
Definition: portab.h:81
SCIP_Bool reduce_dcmstMstIsValid(SCIP *scip, const CSR *cmst)
Definition: reduce_util.c:1650
static void starSelectedPositionsSetNext(STAR *star)
Definition: reduce_util.c:779
void reduce_starCurrentSetRuledOut(STAR *star)
Definition: reduce_util.c:1948
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define GT(a, b)
Definition: portab.h:84
void reduce_blctreeFree(SCIP *scip, BLCTREE **blctree)
Definition: reduce_util.c:1201
SCIP_Bool graph_csr_isValid(const CSR *, SCIP_Bool verbose)
Definition: graph_util.c:1637
#define SCIP_Bool
Definition: def.h:84
int *RESTRICT ieat
Definition: graphdefs.h:230
SCIP_Bool graph_isMarked(const GRAPH *)
Definition: graph_base.c:1165
static void blctreeResetNode(int i, BLCTREE *RESTRICT blctree)
Definition: reduce_util.c:183
int *RESTRICT tail
Definition: graphdefs.h:223
static void blctreeComputeEdgesState(const GRAPH *graph, BLCTREE *blctree)
Definition: reduce_util.c:400
PATH * redcosts_getNodeToTermsPathsTop(const REDCOST *redcostdata)
Definition: redcosts.c:253
const int * reduce_starGetRuledOutEdges(STAR *star, int *nedges)
Definition: reduce_util.c:1918
#define flipedge(edge)
Definition: graphdefs.h:84
void reduce_dcmstAddNode(SCIP *scip, const CSR *mst_in, const SCIP_Real *adjcosts, DCMST *dmst, CSR *mst_out)
Definition: reduce_util.c:1411
void reduce_blctreeGetMstBottlenecks(const GRAPH *graph, const BLCTREE *blctree, SCIP_Real *costlist)
Definition: reduce_util.c:1349
SCIP_Real cost
Definition: reduce_util.c:38
SCIP_Bool allStarsChecked
Definition: reduce_util.c:67
int *RESTRICT term
Definition: graphdefs.h:196
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:127
#define flipedge_Uint(edge)
Definition: graphdefs.h:85
void graph_edge_printInfo(const GRAPH *, int)
Definition: graph_stats.c:133
static void impliedNodesRemoveTerm(const GRAPH *graph, int neighbor, int term, STP_Vectype(int) *nodes_implications, SCIP_Bool *removed)
Definition: reduce_util.c:902
SCIP_Bool graph_pc_knotIsNonLeafTerm(const GRAPH *, int)
SCIP_Bool graph_pc_isPc(const GRAPH *)
void reduce_impliedNodesGet(SCIP *scip, const GRAPH *graph, STP_Vectype(int) *nodes_implications)
Definition: reduce_util.c:937
Portable definitions.
void reduce_dcmstAddNodeInplace(SCIP *scip, const SCIP_Real *adjcosts, DCMST *dmst, CSR *mst)
Definition: reduce_util.c:1438
#define SCIPfreeMemory(scip, ptr)
Definition: scip_mem.h:69
void reduce_impliedNodesRepair(SCIP *scip, const GRAPH *graph, int tail, int head, STP_Vectype(int) *nodes_implications)
Definition: reduce_util.c:962
static SCIP_Real dcmstGetWeightFromStore(SCIP *scip, int mst_nedges, const DCMST *dmst)
Definition: reduce_util.c:689
void graph_pc_2orgcheck(SCIP *, GRAPH *)
SCIP_Bool graph_pc_knotIsDummyTerm(const GRAPH *, int)
SCIP_Real * cost
Definition: graphdefs.h:221
SCIP_Bool graph_edge_isInRange(const GRAPH *, int)
Definition: graph_stats.c:110
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
SCIP_RETCODE reduce_dcmstInit(SCIP *scip, int maxnnodes, DCMST **dcmst)
Definition: reduce_util.c:1385
void reduce_starReset(const GRAPH *g, int node, STAR *star)
Definition: reduce_util.c:1781
#define SCIP_Real
Definition: def.h:177
void reduce_starFree(SCIP *scip, STAR **star)
Definition: reduce_util.c:1758
int *RESTRICT outbeg
Definition: graphdefs.h:204
SCIP_Real * redcosts_getRootToNodeDistTop(const REDCOST *redcostdata)
Definition: redcosts.c:228
static void impliedNodesAddTerm(SCIP *scip, const GRAPH *graph, int term, STP_Vectype(int) *nodes_implications)
Definition: reduce_util.c:850
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
static void dcmstAddNode(const CSR *mst_in, const SCIP_Real *adjcosts, DCMST *dmst)
Definition: reduce_util.c:600
#define UNKNOWN
Definition: sepa_mcf.c:4095
#define nnodes
Definition: gastrans.c:65
#define StpVecPushBack(scip, vec, value)
Definition: stpvector.h:167
static SCIP_RETCODE blctreeInitBottlenecks(SCIP *scip, GRAPH *graph, BLCTREE *blctree)
Definition: reduce_util.c:516
static void starSelectedPositionsReset(STAR *star)
Definition: reduce_util.c:721
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:123
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
#define Is_anyTerm(a)
Definition: graphdefs.h:105
includes various reduction methods for Steiner tree problems
#define STP_RPCSPG
Definition: graphdefs.h:45
static void dcmstGetCSRfromStore(const DCMST *dmst, CSR *mst_out)
Definition: reduce_util.c:629
static void dcmstInsert(const CSR *org_mst, const SCIP_Real adjcosts[], int root, CEDGE new_mst[], SCIP_Bool new_nodemarked[], CEDGE *max_path_edge, int *new_nedges)
Definition: reduce_util.c:532
static void blctreeEvert(const GRAPH *graph, int newroot, BLCTREE *blctree)
Definition: reduce_util.c:202