45 #define MARK_NONACTIVE 0 46 #define MARK_SUBNODE 1 47 #define MARK_SEPARATOR 2 94 assert(scip && soledges);
98 tbneck = *tbottleneck;
101 tbtree = tbneck->
tree;
104 for(
int i = 0; i <
nnodes; i++ )
125 for(
int e = 0; e < nedges; e++ )
129 const int tail = g->
tail[e];
130 const int head = g->
head[e];
139 tbtree[head].
parent = tail;
165 int cutstart = startnode;
172 assert(startnode != endnode);
173 assert(tbottleneck->
nnodes >= 2);
176 for( k = startnode; k != endnode; k = tbtree[k].
parent )
178 assert(0 <= k && k < tbottleneck->
nnodes);
180 if(
GE(max_local, maxlength) )
187 if( tbtree[k].
degree > 2 )
196 assert(
EQ(max_local, maxlength));
199 for( k = cutstart; k != cutend; k = tbtree[k].
parent )
201 assert(k == cutstart || tbtree[k].
degree <= 2);
211 assert(
EQ(max_debug, maxlength));
233 assert(node1 >= 0 && node2 >= 0);
234 assert(node1 != node2);
235 assert(
GT(*maxlength, 0.0));
240 assert(0 <= k && k < tbottleneck->
nnodes);
245 if( tbtree[k].
degree > 2 )
253 if( max_local > max1 )
262 assert(0 <= k && k < tbottleneck->
nnodes);
266 if( tbtree[k].
degree > 2 )
271 if( max_local > max2 )
282 maxtotal =
MAX(max1, max2);
285 if(
GT(maxtotal, *maxlength) )
287 SCIPdebugMessage(
"improved tree bottleneck %f -> %f \n", *maxlength, maxtotal);
289 *maxlength = maxtotal;
293 tbottleneckCut(node1, k, max1, tbottleneck);
295 tbottleneckCut(node2, k, max2, tbottleneck);
302 assert(0 <= k && k < tbottleneck->
nnodes);
316 tbneck = *tbottleneck;
332 const int*
const sepaterms = builder->
sepaterms;
342 assert(sepaterms && nodemap_orgToSub);
343 assert(nsepaterms >= 2 && nsepaterms < g->terms);
348 for(
int i = 0; i < nsepaterms; i++ )
350 const int term = sepaterms[i];
352 assert(!gmark[term]);
353 assert(nodemap_orgToSub[term] ==
UNKNOWN);
357 nodemap_orgToSub[term] = sub_n;
359 sub_e += g->
grad[term];
363 assert(!gmark[sourceterm]);
371 const int k = bfsqueue[i];
374 assert(nodemap_orgToSub[k] ==
UNKNOWN);
376 nodemap_orgToSub[k] = sub_n;
385 const int head = g->
head[e];
394 assert(termcomp->bfsqueue ==
NULL);
399 sub_e += (nsepaterms) * (nsepaterms - 1);
401 termcomp->bfsqueue = bfsqueue;
411 const GRAPH* orggraph,
421 int* nodemap_subToOrg;
422 int* edgemap_subToOrg;
423 const int*
const orgmark = termcomp->
nodes_mark;
424 const int*
const sepaterms = builder->
sepaterms;
426 const int nnodes_sub = termcomp->
subnnodes;
427 const int nedges_sub = termcomp->
subnedges;
430 assert(nsepaterms >= 2 && nsepaterms < orggraph->terms);
431 assert(nnodes_sub > 0 && nedges_sub > 0);
432 assert(nodemap_orgToSub && sepaterms);
434 assert((extperma !=
NULL) == useSd);
442 for(
int i = 0; i < nsepaterms; i++ )
445 assert(nodemap_orgToSub[sepaterms[i]] == subgraph->
knots);
448 nodemap_subToOrg[i] = sepaterms[i];
453 const int orgnode = bfsqueue[i];
454 assert(nodemap_orgToSub[orgnode] == subgraph->
knots);
456 nodemap_subToOrg[subgraph->
knots] = orgnode;
461 assert(nnodes_sub == subgraph->
knots);
462 for(
int i = 0; i < nnodes_sub; i++ )
464 assert(i == nodemap_orgToSub[nodemap_subToOrg[i]]);
468 for(
int subsepaterm = 0; subsepaterm < nsepaterms; subsepaterm++ )
470 const int orgsepaterm = sepaterms[subsepaterm];
473 assert(orgmark[orgsepaterm]);
474 assert(nodemap_subToOrg[subsepaterm] == orgsepaterm);
478 const int orghead = orggraph->
head[e];
481 if( orghead < orgsepaterm )
487 const int subnode = nodemap_orgToSub[orghead];
488 assert(subnode >= 0);
491 edgemap_subToOrg[subgraph->
edges] = e;
502 for(
int subsepaterm2 = subsepaterm + 1; subsepaterm2 < nsepaterms; subsepaterm2++ )
504 const int orgsepaterm2 = sepaterms[subsepaterm2];
511 edgemap_subToOrg[subgraph->
edges] = -1;
512 edgemap_subToOrg[subgraph->
edges + 1] = -1;
524 const int orgnode = bfsqueue[i];
525 const int subnode = nodemap_orgToSub[orgnode];
529 const int orghead = orggraph->
head[e];
531 if( orghead < orgnode )
534 if( orgmark[orghead] )
536 const int subhead = nodemap_orgToSub[orghead];
537 assert(subhead >= 0);
540 edgemap_subToOrg[subgraph->
edges] = e;
553 for(
int subsepaterm = 0; subsepaterm < nsepaterms; subsepaterm++ )
555 const int orgsepaterm = sepaterms[subsepaterm];
557 assert(orgmark[orgsepaterm]);
558 assert(nodemap_subToOrg[subsepaterm] == orgsepaterm);
560 for(
int orge = orggraph->
outbeg[orgsepaterm]; orge !=
EAT_LAST; orge = orggraph->
oeat[orge] )
562 const int orghead = orggraph->
head[orge];
563 if( orghead < orgsepaterm )
568 const int subhead = nodemap_orgToSub[orghead];
569 assert(subhead >= 0);
574 if( subgraph->
head[e] == subhead )
577 assert(edgemap_subToOrg[e] == -1);
579 edgemap_subToOrg[e] = orge;
582 subgraph->
cost[e] = newcost;
626 int tempnode = term1;
628 assert(mst && mstsdist);
631 assert(term1 != term2);
633 mstsdist[tempnode] = 0.0;
635 while( tempnode != mstsource )
637 const int ne = mst[tempnode].
edge;
640 assert(g->
head[ne] == tempnode);
641 tempnode = g->
tail[ne];
643 if( g->
cost[ne] > bdist )
646 mstsdist[tempnode] = bdist;
647 if( tempnode == term2 )
652 if( tempnode == term2 )
654 tempnode = mstsource;
662 while( tempnode != mstsource )
664 const int ne = mst[tempnode].
edge;
667 tempnode = g->
tail[ne];
669 if( g->
cost[ne] > bdist )
673 if( mstsdist[tempnode] > -0.5 )
675 if( mstsdist[tempnode] > bdist )
676 bdist = mstsdist[tempnode];
680 assert(
EQ(mstsdist[tempnode], -1.0));
685 mstsdist[tempnode] = -1.0;
686 while( tempnode != mstsource )
688 const int ne = mst[tempnode].
edge;
689 tempnode = g->
tail[ne];
690 mstsdist[tempnode] = -1.0;
691 if( tempnode == term2 )
696 for(
int i = 0; i < g->
knots; i++ )
697 assert(
EQ(mstsdist[i], -1.0));
701 if( subsolbottleneck )
726 builder = *compbuilder;
741 for(
int i = 0; i <
nnodes; i++ )
757 builder = *compbuilder;
771 assert(
GT(ratio, 0.0));
772 assert(
LE(ratio, 1.0));
780 const GRAPH* orggraph,
784 assert(orggraph && compbuilder);
786 printf(
"number of separator nodes=%d, nodes: \n", compbuilder->
nsepatterms);
788 for(
int i = 0; i < compbuilder->
nsepatterms; i++ )
790 const int sepaterm = compbuilder->
sepaterms[i];
808 assert(scip && orggraph && extperma && termcomp);
826 assert(scip && orggraph && termcomp);
847 const int*
const sepaterms = builder->
sepaterms;
850 const int*
const nodes_mark = termcomp->
nodes_mark;
853 const int mstroot = sepaterms[0];
858 for(
int i = 0; i <
nnodes; i++ )
864 for(
int i = 0; i < nsepaterms; i++ )
866 const int term = sepaterms[i];
867 if( term != mstroot && mst[term].edge == -1 )
877 for(
int i = 0; i < g->
knots; i++ )
881 assert(mst[i].edge != -1);
886 for(
int i = 0; i < subgraph->
knots; i++ )
889 for(
int i = 0; i < nsepaterms; i++ )
891 const int term = sepaterms[i];
892 const int term_sub = nodemap_orgToSub[term];
899 for(
int i = 0; i < nsepaterms; i++ )
901 const int term = sepaterms[i];
902 const int term_sub = nodemap_orgToSub[term];
906 const int head_sub = subgraph->
head[e];
910 const int head = nodemap_subToOrg[head_sub];
914 subgraph->
cost[e] =
b;
931 const GRAPH* orggraph,
940 assert(subgraph && orggraph);
941 assert(nsepaterms > 0);
945 for(
int subsepaterm = 0; subsepaterm < nsepaterms; subsepaterm++ )
947 for(
int sube = subgraph->
outbeg[subsepaterm]; sube !=
EAT_LAST; sube = subgraph->
oeat[sube] )
949 const int subhead = subgraph->
head[sube];
950 if( subhead < nsepaterms )
952 const int orge = edgemap_subToOrg[sube];
962 subgraph->
cost[sube] = orggraph->
cost[orge];
973 for(
int e = 0; e < subgraph->
edges; e += 2 )
975 assert(
EQ(subgraph->
cost[e], subgraph->
cost[e + 1]));
999 comp->bfsqueue =
NULL;
1009 for(
int i = 0; i < g->
knots; i++ )
1021 const int* subsoledges,
1025 const GRAPH* subgraph;
1027 assert(scip && subsoledges && termcomp);
1080 const int* sepaterms =
NULL;
1085 *compWasFound =
FALSE;
1087 assert(nsepaterms >= 2);
1092 SCIPdebugMessage(
"maximum number of components reached, stopping sepaDualAscent reductions \n");
1096 for( ; nsepaterms <= builder->
maxsepasize; nsepaterms++ )
1100 if( sepaterms !=
NULL )
1102 *compWasFound =
TRUE;
1109 const int nsourcenodes = builder->
ngraphnodes - nsinknodes;
1111 assert(nsinknodes > 0);
1112 assert(nsourcenodes > 0);
1138 SCIPdebugMessage(
"no further components available, stopping sepaDualAscent reductions \n");
#define STP_Vectype(type)
int graph_get_nEdges(const GRAPH *)
#define StpVecGetSize(vec)
static void subgraphIdentify(SCIP *scip, GRAPH *g, TERMCOMP *termcomp)
SCIP_RETCODE reduce_termcompInitTbottleneck(SCIP *scip, const int *subsoledges, TERMCOMP *termcomp)
#define SCIPfreeMemoryArrayNull(scip, ptr)
SCIP_Real extreduce_distDataGetSdDouble(SCIP *, const GRAPH *, int, int, DISTDATA *)
SCIP_RETCODE reduce_compbuilderInit(SCIP *scip, const GRAPH *g, COMPBUILDER **compbuilder)
#define SCIPfreeMemoryArray(scip, ptr)
void graph_edge_addBi(SCIP *, GRAPH *, int, int, double)
SCIP_RETCODE reduce_termcompInit(SCIP *scip, const GRAPH *g, COMPBUILDER *builder, TERMCOMP **termcomp)
#define SCIPallocMemoryArray(scip, ptr, num)
void graph_path_exec(SCIP *, const GRAPH *, int, int, const SCIP_Real *, PATH *)
SCIP_RETCODE reduce_termcompBuildSubgraph(SCIP *scip, GRAPH *orggraph, TERMCOMP *termcomp)
void reduce_termsepaGetNextComp(SCIP *scip, const GRAPH *g, TERMSEPAS *termsepas, COMPBUILDER *builder, SCIP_Bool *compWasFound)
includes methods for Steiner tree problem solutions
void graph_knot_printInfo(const GRAPH *, int)
void graph_free(SCIP *, GRAPH **, SCIP_Bool)
SCIP_RETCODE graph_path_init(SCIP *, GRAPH *)
int mincut_termsepasGetSource(const TERMSEPAS *termsepas)
DISTDATA * distdata_default
enum SCIP_Retcode SCIP_RETCODE
includes various files containing graph methods used for Steiner tree problems
#define StpVecReserve(scip, vec, _size_)
#define SCIPfreeBufferArray(scip, ptr)
void graph_printInfo(const GRAPH *)
header only, simple implementation of an STL like vector
void reduce_compbuilderFree(SCIP *scip, COMPBUILDER **compbuilder)
This file implements extended reduction techniques for several Steiner problems.
void graph_get_nVET(const GRAPH *, int *, int *, int *)
void graph_knot_add(GRAPH *, int)
SCIP_RETCODE reduce_termcompBuildSubgraphWithSds(SCIP *scip, GRAPH *orggraph, EXTPERMA *extperma, TERMCOMP *termcomp)
SCIP_Real reduce_compbuilderGetSubNodesRatio(const COMPBUILDER *compbuilder)
#define SCIPallocBufferArray(scip, ptr, num)
SCIP_Bool rootcompIsProcessed
static SCIP_RETCODE tbottleneckInit(SCIP *scip, const GRAPH *g, const int *soledges, TBOTTLENECK **tbottleneck)
static SCIP_Real getExtBottleneckDist(const GRAPH *g, int term1, int term2, int term1_sub, int term2_sub, int mstsource, PATH *mst, TBOTTLENECK *subsolbottleneck, SCIP_Real *RESTRICT mstsdist)
void graph_edge_printInfo(const GRAPH *, int)
#define SCIPfreeMemory(scip, ptr)
SCIP_RETCODE reduce_termcompChangeSubgraphToBottleneck(SCIP *scip, GRAPH *g, TERMCOMP *termcomp, SCIP_Bool *success)
void reduce_termcompFree(SCIP *scip, TERMCOMP **termcomp)
static SCIP_RETCODE subgraphBuild(SCIP *scip, const GRAPH *orggraph, SCIP_Bool useSd, EXTPERMA *extperma, TERMCOMP *termcomp)
const int * mincut_termsepasGetNext(int sepasize, TERMSEPAS *termsepas, int *sinkterm, int *nsinknodes)
void reduce_termcompChangeSubgraphToOrgCosts(const GRAPH *orggraph, TERMCOMP *termcomp)
#define StpVecFree(scip, vec)
int graph_get_nNodes(const GRAPH *)
#define SCIPallocMemory(scip, ptr)
struct tree_bottleneck_node TBNODE
SCIP_Bool graph_knot_isInRange(const GRAPH *, int)
static void tbottleneckGetMax(int node1, int node2, TBOTTLENECK *tbottleneck, SCIP_Real *maxlength)
TBOTTLENECK * subsolbottleneck
#define StpVecPushBack(scip, vec, value)
SCIP_RETCODE graph_init(SCIP *, GRAPH **, int, int, int)
#define BMSclearMemoryArray(ptr, num)
SCIP_Bool solstp_isValid(SCIP *scip, const GRAPH *graph, const int *result)
Minimum cut routines for Steiner problems.
void reduce_compbuilderPrintSeparators(const GRAPH *orggraph, const COMPBUILDER *compbuilder)
includes various reduction methods for Steiner tree problems
static void tbottleneckFree(SCIP *scip, TBOTTLENECK **tbottleneck)