void init() { mst(head, -1); ecnt = 0; mst(dfn, 0); mst(low, 0); cnt = 0; nblock = 0; mst(evis, 0); }
int main(int argc, char *argv[]) try { AdjacencyList adjacency; int num_nodes = ReadInputOrDie(argc, argv, &adjacency); std::cout << "Graph read from file: \n"; for (auto begin = adjacency.begin(); begin != adjacency.end(); begin++) { for (Edge edge : begin->second) { auto nodes = edge.GetNodes(); //don't print duplicates if (nodes[1] > nodes[0]) { edge.Print(); } } } std::cout << "Minimum Spanning Tree:\n"; SpanningTree mst(num_nodes, adjacency); if (mst.BuildMinSpanningTree()) { for (Edge edge : *mst.GetOptimalEdgeList()) { edge.Print(); } } std::cout << "MST Weight: " << mst.GetWeight() << "\n"; } catch (std::exception &e) { std::cerr << "Error: " << e.what() << "\n"; return -1; } catch (...) { std::cerr << "unknown error\n"; return -1; }
int main(void) { int index[MAX_N]; double x[MAX_N], y[MAX_N]; Edge elist[MAX_M]; int n, m, i, j, k, t; double w; scanf("%d", &n); for (i = 0; i < n; i++) { scanf("%lf %lf", x+i, y+i); } k = 0; for (i = 0; i < n; i++) { for (j = i+1; j < n; j++) { elist[k].v1 = i; elist[k].v2 = j; elist[k].w = hypot((x[i]-x[j]), (y[i]-y[j])); k++; } } w = mst(n, k, elist, index, &t); printf("%.2f\n", w); return 0; }
void main() { clrscr(); read(); mst(); out(); }
void work(Graph &g){ mst(g,1); cout << g.total_weight; int min=INT_MAX; /* for(int i=0;i<g.PI.size();i++) cout << "source = " << g.PI[i].source << " target = " << g.PI[i].target << " weight = " << g.PI[i].weight << endl; */ for(int i=0;i<g.PI.size();i++){ g.separate(g,g.PI[i].source,g.PI[i]); /* cout << "end "; for(int j=1;j<=g.num_node;j++){ cout << g.separated[j] << ' '; } cout << endl; */ for(int j=1;j<=g.num_node;j++) { if(g.separated[j]==0){ for(int k=1;k<=g.num_node;k++){ if(g.adjArray[j][k]==0) continue; if( (j==g.PI[i].source && k==g.PI[i].target) || (j==g.PI[i].target && k==g.PI[i].source) || g.separated[k]==0) continue; if(g.adjArray[j][k]-g.PI[i].weight < min) min = g.adjArray[j][k]-g.PI[i].weight; } } else if(g.separated[j]==1){ for(int k=1;k<=g.num_node;k++){ if(g.adjArray[j][k]==0) continue; if( (j==g.PI[i].source && k==g.PI[i].target) || (j==g.PI[i].target && k==g.PI[i].source) || g.separated[k]==1) continue; if(g.adjArray[j][k]-g.PI[i].weight < min) min = g.adjArray[j][k]-g.PI[i].weight; } } if(min==0) break; } if(min==0) break; for(int j=1;j<=g.num_node;j++) g.separated[j]=0; } cout << ' ' << g.total_weight+min << endl; }
int main() { ladj A(3); // Teste: insert_arc A.insert_arc( 0, 1, 0.1); A.insert_arc( 1, 2, 0.2); A.insert_arc( 2, 1, 0.3); // Teste: remove_arc A.remove_arc( 1, 2, 0.2); mst(&A); // Teste: print A.print(); return 0; }
/** first relaxation of tsp idea: take mst add shortest edge */ int TSPRelaxation::mstPlusOne() { // calculate mst MST mst(this->g, this->weight); int w = mst.prim(); // minimum edge found int min = numeric_limits<int>::max(); for (ListGraph::EdgeIt e(this->g); e != INVALID; ++e) { // edge is in mst, so do not take it if ((*mst.mst).count(e) != 0) continue; // edge is shorter than shortest found yet if (this->weight[e] < min) min = this->weight[e]; } // return weight of mst + shortest other one return w + min; }
/** second relaxation of tsp idea: remove some (random) node take mst add shortest two edges of the removed node */ int TSPRelaxation::mstOnSubgraph() { // create a copy of the graph ListGraph g; ListGraph::EdgeMap<int> weight(g); ListGraph::NodeMap<ListGraph::Node> nodemap(g); GraphCopy<ListGraph, ListGraph> copy(this->g, g); copy.edgeMap(this->weight, weight).nodeCrossRef(nodemap).run(); // remove a random node // removed will contain the node of this->g corresponding to the removed one afterwards int del = rand() % countNodes(g); ListGraph::Node removed; for (ListGraph::NodeIt n(g); n != INVALID; ++n) { if (del == 0) { removed = nodemap[n]; g.erase(n); break; } del--; } // calculate mst MST mst(g, weight); int w = mst.prim(); // search for two shortest edges incident to the removed node int mins[] = {numeric_limits<int>::max(), numeric_limits<int>::max()}; for (ListGraph::IncEdgeIt e(this->g, removed); e != INVALID; ++e) { // iterate over all incident nodes if (this->weight[e] < mins[0]) { // shortest found yet mins[1] = mins[0]; mins[0] = this->weight[e]; } // 2nd-shortest else if (this->weight[e] < mins[1]) mins[1] = this->weight[e]; } return w + mins[0] + mins[1]; }
void wrap(Signal *s) { if(s->alg == 0) s->alg = defroute; switch(s->alg) { case RTSP: tsp(s); s->prfn = prseq; break; case RTSPE: tspe(s); s->prfn = prseq; break; case RHAND: hand(s); s->prfn = prseq; break; case RMST: mst(s); s->prfn = prmst; break; case RMST3: mst3(s); s->prfn = prmst; break; default: f_major("Unknown routing algorithm %d", s->alg); abort(); return; } calclen(s); }
int* christofides(int* edges, int length){ vector_dll* n; vector_dll* MST = mst(edges,length); vector_dll* PM = perfect_matching(MST, length); int* solution = (int*)malloc((length+2)*sizeof(int)); int i; solution[0] = 0; while (MST) { n = MST; MST = MST->n; free(n); } while (PM) { n = PM; PM = PM->n; free(n); } return solution; }
/* * Prim's approximated TSP tour * See also [Cristophides'92] */ bool TSP::findEulerianPath() { Ids iorder(n); Ids mst(n); Ids arc(n); std::vector < double > dis(n); double d; #if 0 int n, *iorder, *jorder; DTYPE d; DTYPE maxd; DTYPE *dist; DTYPE *dis; jorder = tsp->jorder; iorder = tsp->iorder; dist = tsp->dist; maxd = tsp->maxd; n = tsp->n; if (!(mst = (int*) palloc(n * sizeof(int))) || !(arc = (int*) palloc(n * sizeof(int))) || !(dis = (DTYPE*) palloc(n * sizeof(DTYPE))) ) { elog(ERROR, "Failed to allocate memory!"); return -1; } #endif // PGR_DBG("findEulerianPath: 1"); size_t j(0); double curr_maxd = maxd; dis[0] = -1; for (size_t i = 1; i < n; ++i) { dis[i] = dist[i][0]; arc[i] = 0; if (curr_maxd > dis[i]) { curr_maxd = dis[i]; j = i; } } //PGR_DBG("findEulerianPath: j=%d", j); if (curr_maxd == maxd) { // PGR_DBG("Error TSP fail to findEulerianPath, check your distance matrix is valid."); return false; } /* * O(n^2) Minimum Spanning Trees by Prim and Jarnick * for graphs with adjacency matrix. */ for (size_t a = 0; a < n - 1; a++) { size_t k(0); mst[a] = j * n + arc[j]; /* join fragment j with MST */ dis[j] = -1; d = maxd; for (size_t i = 0; i < n; i++) { if (dis[i] >= 0) /* not connected yet */ { if (dis[i] > dist[i][j]) { dis[i] = dist[i][j]; arc[i] = j; } if (d > dis[i]) { d = dis[i]; k = i; } } } j = k; } //PGR_DBG("findEulerianPath: 3"); /* * Preorder Tour of MST */ #if 0 #define VISITED(x) jorder[x] #define NQ(x) arc[l++] = x #define DQ() arc[--l] #define EMPTY (l==0) #endif for (auto &val : jorder) { val = 0; } #if 0 for (i = 0; i < n; i++) VISITED(i) = 0; #endif size_t l = 0; size_t k = 0; d = 0; arc[l++] = 0; while (!(l == 0)) { size_t i = arc[--l]; if (!jorder[i]) { iorder[k++] = i; jorder[i] = 1; /* push all kids of i */ for (size_t j = 0; j < n - 1; j++) { if (i == mst[j] % n) arc[l++] = mst[j] % n; } } } #if 0 k = 0; l = 0; d = 0; NQ(0); while (!EMPTY) { i = DQ(); if (!VISITED(i)) { iorder[k++] = i; VISITED(i) = 1; for (j = 0; j < n - 1; j++) /* push all kids of i */ { if (i == mst[j]%n) NQ(mst[j]/n); } } } #endif //PGR_DBG("findEulerianPath: 4"); update(iorder); return true; }
//#################### PUBLIC METHODS #################### void CTIPFBuilder::execute() { typedef itk::Image<short,3> GradientMagnitudeImage; typedef itk::Image<int,3> HounsfieldImage; typedef itk::Image<float,3> RealImage; typedef itk::Image<unsigned char,3> WindowedImage; HounsfieldImage::Pointer hounsfieldImage = (*m_volume)->base_image(); //~~~~~~~ // STEP 1 //~~~~~~~ set_status("Preprocessing image..."); // Construct the windowed image. WindowedImage::Pointer windowedImage = (*m_volume)->windowed_image(m_segmentationOptions.windowSettings); if(is_aborted()) return; // Cast the input image (whether Hounsfield or windowed) to make its pixels real-valued. RealImage::Pointer realImage; switch(m_segmentationOptions.inputType) { case CTSegmentationOptions::INPUTTYPE_HOUNSFIELD: { typedef itk::CastImageFilter<HounsfieldImage,RealImage> CastFilter; CastFilter::Pointer castFilter = CastFilter::New(); castFilter->SetInput(hounsfieldImage); castFilter->Update(); realImage = castFilter->GetOutput(); break; } case CTSegmentationOptions::INPUTTYPE_WINDOWED: { typedef itk::CastImageFilter<WindowedImage,RealImage> CastFilter; CastFilter::Pointer castFilter = CastFilter::New(); castFilter->SetInput(windowedImage); castFilter->Update(); realImage = castFilter->GetOutput(); break; } default: { throw Exception("Unknown CT segmentation input type"); // this should never happen } } if(is_aborted()) return; // Smooth this real image using anisotropic diffusion filtering. typedef itk::GradientAnisotropicDiffusionImageFilter<RealImage,RealImage> ADFilter; for(int i=0; i<m_segmentationOptions.adfIterations; ++i) { ADFilter::Pointer adFilter = ADFilter::New(); adFilter->SetInput(realImage); adFilter->SetConductanceParameter(1.0); adFilter->SetNumberOfIterations(1); adFilter->SetTimeStep(0.0625); adFilter->Update(); realImage = adFilter->GetOutput(); if(is_aborted()) return; increment_progress(); } // Calculate the gradient magnitude of the smoothed image. typedef itk::GradientMagnitudeImageFilter<RealImage,GradientMagnitudeImage> GMFilter; GMFilter::Pointer gmFilter = GMFilter::New(); gmFilter->SetInput(realImage); gmFilter->SetUseImageSpacingOff(); gmFilter->Update(); GradientMagnitudeImage::Pointer gradientMagnitudeImage = gmFilter->GetOutput(); if(is_aborted()) return; increment_progress(); //~~~~~~~ // STEP 2 //~~~~~~~ set_status("Running watershed..."); // Run the watershed algorithm on the gradient magnitude image. typedef MeijsterRoerdinkWatershed<GradientMagnitudeImage::PixelType,3> WS; WS ws(gradientMagnitudeImage, ITKImageUtil::make_6_connected_offsets()); if(is_aborted()) return; increment_progress(); //~~~~~~~ // STEP 3 //~~~~~~~ set_status("Creating initial partition forest..."); boost::shared_ptr<CTImageLeafLayer> leafLayer(new CTImageLeafLayer(hounsfieldImage, windowedImage, gradientMagnitudeImage)); if(is_aborted()) return; boost::shared_ptr<CTImageBranchLayer> lowestBranchLayer = IPF::make_lowest_branch_layer(leafLayer, ws.calculate_groups()); if(is_aborted()) return; m_ipf.reset(new IPF(leafLayer, lowestBranchLayer)); increment_progress(); //~~~~~~~ // STEP 4 //~~~~~~~ set_status("Creating rooted MST for lowest branch layer..."); RootedMST<int> mst(*lowestBranchLayer); if(is_aborted()) return; increment_progress(); //~~~~~~~ // STEP 5 //~~~~~~~ set_status("Running waterfall..."); // Iteratively run a Nicholls waterfall pass on the MST until the forest is built. typedef WaterfallPass<int>::Listener WaterfallPassListener; NichollsWaterfallPass<int> waterfallPass; boost::shared_ptr<WaterfallPassListener> listener = make_forest_building_waterfall_pass_listener(m_ipf); waterfallPass.add_listener(listener); while(mst.node_count() != 1 && m_ipf->highest_layer() < m_segmentationOptions.waterfallLayerLimit) { m_ipf->clone_layer(m_ipf->highest_layer()); if(is_aborted()) return; waterfallPass.run(mst); if(is_aborted()) return; } set_finished(); }
/** The main program. */ int main(int argc, char *argv[]) { Parameters param(argc, argv); // parse the command-line arguments if(param.noOfNodes() == std::numeric_limits<unsigned int>::max() || param.noOfEdges() ==std::numeric_limits<unsigned int>::max()) { STXXL_MSG("Either number of vertices or edges is not speicifed. Exiting!!!"); return 0; } Graph inputGraph(param.noOfNodes(),param.noOfEdges()); if (param.randomGraph()) { STXXL_MSG("Generating random graph"); inputGraph.generateGraph(); inputGraph.printGraph(); } else if (param.importInputFilename() != "") { // import graph from file STXXL_MSG("Import graph" << std::endl ); if(param.otherGraph()) importFromFile(param.importInputFilename(),inputGraph ); else importEdgeVector( param.importInputFilename(),inputGraph ); } // export input graph if (param.outputFilename() != "") { STXXL_MSG("Export graph" << std::endl ); std::ofstream outFile(param.outputFilename().c_str()); exportEdgeVector(outFile, inputGraph); } stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); stxxl::timer Timer; MST mst(inputGraph.getNoVertices()); mst.clearMST(); float B = (float) BLOCK_SIZE/(float)(sizeof(Edge)); float M = (10 * 1024 * 1024)/(float)(sizeof(Edge)); float N = param.noOfNodes()+2*param.noOfEdges(); STXXL_MSG("N: "<<N<<" M: "<<M<<" B: "<<B<<" Sizeof Edge: "<<sizeof(Edge)); if(N > M) { stxxl::stats_data stats_begin(*stxxl::stats::get_instance()); Timer.reset(); Timer.start(); stage(inputGraph,mst); STXXL_MSG("Part-1 build elapsed time: " << (Timer.mseconds() / 1000.) <<" seconds : " << (double(inputGraph.getNoEdges()) / (Timer.mseconds() / 1000.)) << " edges per sec"); std::cout << stats_total; } if(inputGraph.getNoEdges() != 0) { stats_begin = *stxxl::stats::get_instance(); Timer.reset(); Timer.start(); ExternalPrim prim; prim.buildMST(inputGraph,mst); STXXL_MSG("MST build elapsed time: " << (Timer.mseconds() / 1000.) <<" seconds : " << (double(inputGraph.getNoEdges()) / (Timer.mseconds() / 1000.)) << " edges per sec"); std::cout << stxxl::stats_data(*stxxl::stats::get_instance()) - stats_begin; } mst.printMST(); return 0; }
int main(int argc, char **argv) { int i, j, k, ret; int nlines, type, ltype, afield, tfield, geo, cat; int sp, nsp, nspused, node, line; struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt, *term_opt, *nsp_opt; struct Flag *geo_f; struct GModule *module; struct Map_info Map, Out; int *testnode; /* array all nodes: 1 - should be tested as Steiner, * 0 - no need to test (unreachable or terminal) */ struct ilist *TList; /* list of terminal nodes */ struct ilist *StArcs; /* list of arcs on Steiner tree */ struct ilist *StNodes; /* list of nodes on Steiner tree */ struct boxlist *pointlist; double cost, tmpcost; struct cat_list *Clist; struct line_cats *Cats; struct line_pnts *Points; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("steiner tree")); module->label = _("Creates Steiner tree for the network and given terminals."); module->description = _("Note that 'Minimum Steiner Tree' problem is NP-hard " "and heuristic algorithm is used in this module so " "the result may be sub optimal."); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->key = "arc_type"; type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->label = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "node_layer"; tfield_opt->answer = "2"; tfield_opt->label = _("Node layer (used for terminals)"); afcol = G_define_option(); afcol->key = "acolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arcs' cost column (for both directions)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "terminal_cats"; term_opt->required = YES; term_opt->description = _("Categories of points on terminals (layer is specified by nlayer)"); nsp_opt = G_define_option(); nsp_opt->key = "npoints"; nsp_opt->type = TYPE_INTEGER; nsp_opt->required = NO; nsp_opt->multiple = NO; nsp_opt->answer = "-1"; nsp_opt->description = _("Number of Steiner points (-1 for all possible)"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); TList = Vect_new_list(); StArcs = Vect_new_list(); StNodes = Vect_new_list(); Clist = Vect_new_cat_list(); tfield = atoi(tfield_opt->answer); Vect_str_to_cat_list(term_opt->answer, Clist); G_debug(1, "Imput categories:\n"); for (i = 0; i < Clist->n_ranges; i++) { G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]); } if (geo_f->answer) geo = 1; else geo = 0; Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (Vect_open_old(&Map, map->answer, "") < 0) G_fatal_error(_("Unable to open vector map <%s>"), map->answer); nnodes = Vect_get_num_nodes(&Map); nlines = Vect_get_num_lines(&Map); /* Create list of terminals based on list of categories */ for (i = 1; i <= nlines; i++) { ltype = Vect_get_line_type(&Map, i); if (!(ltype & GV_POINT)) continue; Vect_read_line(&Map, Points, Cats, i); if (!(Vect_cat_get(Cats, tfield, &cat))) continue; node = Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0, 0); if (!node) { G_warning(_("Point is not connected to the network (cat=%d)"), cat); continue; } if (Vect_cat_in_cat_list(cat, Clist)) { Vect_list_append(TList, node); } } nterms = TList->n_values; /* GTC Terminal refers to an Steiner tree endpoint */ G_message(_("Number of terminals: %d\n"), nterms); if (nterms < 2) { /* GTC Terminal refers to an Steiner tree endpoint */ G_fatal_error(_("Not enough terminals (< 2)")); } /* Number of steiner points */ nsp = atoi(nsp_opt->answer); if (nsp > nterms - 2) { nsp = nterms - 2; G_warning(_("Requested number of Steiner points > than possible")); } else if (nsp == -1) { nsp = nterms - 2; } G_message(_("Number of Steiner points set to %d\n"), nsp); testnode = (int *)G_malloc((nnodes + 1) * sizeof(int)); for (i = 1; i <= nnodes; i++) testnode[i] = 1; /* Alloc arrays of costs for nodes, first node at 1 (0 not used) */ nodes_costs = (double **)G_malloc((nnodes) * sizeof(double *)); for (i = 0; i < nnodes; i++) { nodes_costs[i] = (double *)G_malloc((nnodes - i) * sizeof(double)); for (j = 0; j < nnodes - i; j++) nodes_costs[i][j] = -1; /* init, i.e. cost was not calculated yet */ } /* alloc memory from each to each other (not directed) terminal */ i = nterms + nterms - 2; /* max number of terms + Steiner points */ comps = (int *)G_malloc(i * sizeof(int)); i = i * (i - 1) / 2; /* number of combinations */ term_costs = (COST *) G_malloc(i * sizeof(COST)); /* alloc memory for costs from Stp to each other terminal */ i = nterms + nterms - 2 - 1; /* max number of terms + Steiner points - 1 */ sp_costs = (COST *) G_malloc(i * sizeof(COST)); terms = (int *)G_malloc((nterms + nterms - 2) * sizeof(int)); /* i.e. +(nterms - 2) St Points */ /* Create initial parts from list of terminals */ G_debug(1, "List of terminal nodes (%d):\n", nterms); for (i = 0; i < nterms; i++) { G_debug(1, "%d\n", TList->value[i]); terms[i] = TList->value[i]; testnode[terms[i]] = 0; /* do not test as Steiner */ } /* Build graph */ Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL, geo, 0); /* Init costs for all terminals */ for (i = 0; i < nterms; i++) init_node_costs(&Map, terms[i]); /* Test if all terminal may be connected */ for (i = 1; i < nterms; i++) { ret = get_node_costs(terms[0], terms[i], &cost); if (ret == 0) { /* GTC Terminal refers to an Steiner tree endpoint */ G_fatal_error(_("Terminal at node [%d] cannot be connected " "to terminal at node [%d]"), terms[0], terms[i]); } } /* Remove not reachable from list of SP candidates */ j = 0; for (i = 1; i <= nnodes; i++) { ret = get_node_costs(terms[0], i, &cost); if (ret == 0) { testnode[i] = 0; G_debug(2, "node %d removed from list of Steiner point candidates\n", i ); j++; } } G_message(_("[%d] (not reachable) nodes removed from list " "of Steiner point candidates"), j); /* calc costs for terminals MST */ ret = mst(&Map, terms, nterms, &cost, PORT_DOUBLE_MAX, NULL, NULL, 0, 1); /* no StP, rebuild */ G_message(_("MST costs = %f"), cost); /* Go through all nodes and try to use as steiner points -> find that which saves most costs */ nspused = 0; for (j = 0; j < nsp; j++) { sp = 0; G_verbose_message(_("Search for [%d]. Steiner point"), j + 1); for (i = 1; i <= nnodes; i++) { G_percent(i, nnodes, 1); if (testnode[i] == 0) { G_debug(3, "skip test for %d\n", i); continue; } ret = mst(&Map, terms, nterms + j, &tmpcost, cost, NULL, NULL, i, 0); G_debug(2, "cost = %f x %f\n", tmpcost, cost); if (tmpcost < cost) { /* sp candidate */ G_debug(3, " steiner candidate node = %d mst = %f (x last = %f)\n", i, tmpcost, cost); sp = i; cost = tmpcost; } } if (sp > 0) { G_message(_("Steiner point at node [%d] was added " "to terminals (MST costs = %f)"), sp, cost); terms[nterms + j] = sp; init_node_costs(&Map, sp); testnode[sp] = 0; nspused++; /* rebuild for nex cycle */ ret = mst(&Map, terms, nterms + nspused, &tmpcost, PORT_DOUBLE_MAX, NULL, NULL, 0, 1); } else { /* no steiner found */ G_message(_("No Steiner point found -> leaving cycle")); break; } } G_message(_("Number of added Steiner points: %d " "(theoretic max is %d).\n"), nspused, nterms - 2); /* Build lists of arcs and nodes for final version */ ret = mst(&Map, terms, nterms + nspused, &cost, PORT_DOUBLE_MAX, StArcs, StNodes, 0, 0); /* Calculate true costs, which may be lower than MST if steiner points were not used */ if (nsp < nterms - 2) { G_message(_("Spanning tree costs on complet graph = %f\n" "(may be higher than resulting Steiner tree costs!!!)"), cost); } else G_message(_("Steiner tree costs = %f"), cost); /* Write arcs to new map */ if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), output->answer); Vect_hist_command(&Out); G_debug(1, "Steiner tree:"); G_debug(1, "Arcs' categories (layer %d, %d arcs):", afield, StArcs->n_values); for (i = 0; i < StArcs->n_values; i++) { line = StArcs->value[i]; ltype = Vect_read_line(&Map, Points, Cats, line); Vect_write_line(&Out, ltype, Points, Cats); Vect_cat_get(Cats, afield, &cat); G_debug(1, "arc cat = %d", cat); } G_debug(1, "Nodes' categories (layer %d, %d nodes):", tfield, StNodes->n_values); k = 0; pointlist = Vect_new_boxlist(0); for (i = 0; i < StNodes->n_values; i++) { double x, y, z; struct bound_box box; node = StNodes->value[i]; Vect_get_node_coor(&Map, node, &x, &y, &z); box.E = box.W = x; box.N = box.S = y; box.T = box.B = z; Vect_select_lines_by_box(&Map, &box, GV_POINT, pointlist); nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < pointlist->n_values; j++) { line = pointlist->id[j]; ltype = Vect_read_line(&Map, Points, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; Vect_write_line(&Out, ltype, Points, Cats); G_debug(1, "node cat = %d", cat); k++; } } Vect_build(&Out); G_message(n_("A Steiner tree with %d arc has been built", "A Steiner tree with %d arcs has been built", StArcs->n_values), StArcs->n_values); /* Free, ... */ Vect_destroy_list(StArcs); Vect_destroy_list(StNodes); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
/** * 测试最小生成树 */ void test_mini_span_tree_from_graph() { Student s[] = { *studn_get_init(1, "a", 0, 22, 11), *studn_get_init(2, "b", 0, 22, 11), *studn_get_init(3, "c", 0, 22, 11), *studn_get_init(4, "d", 0, 22, 11), *studn_get_init(5, "e", 0, 22, 11), *studn_get_init(6, "f", 0, 22, 11), }; MstVertex m[] = { /*0*/*mst_vertex_get_init((void *)(&s[0]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[1]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 0, (int (*)(const void *, const void *))studn_match, NULL), /*a点延伸出去的边的连接节点*/ /*6*/*mst_vertex_get_init((void *)(&s[1]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 4, (int (*)(const void *, const void *))studn_match, NULL), /*b点延伸出去的边的连接节点*/ /*8*/*mst_vertex_get_init((void *)(&s[0]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 6, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 2, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 4, (int (*)(const void *, const void *))studn_match, NULL), /*c点延伸出去的边的连接节点*/ /*12*/*mst_vertex_get_init((void *)(&s[0]), 4, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[1]), 6, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 9, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 8, (int (*)(const void *, const void *))studn_match, NULL), /*d点延伸出去的边的连接节点*/ /*16*/*mst_vertex_get_init((void *)(&s[1]), 2, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 7, (int (*)(const void *, const void *))studn_match, NULL), /*e点延伸出去的边的连接节点*/ /*18*/*mst_vertex_get_init((void *)(&s[2]), 9, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 1, (int (*)(const void *, const void *))studn_match, NULL), /*f点延伸出去的边的连接节点*/ /*20*/*mst_vertex_get_init((void *)(&s[1]), 4, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 8, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 1, (int (*)(const void *, const void *))studn_match, NULL), }; Graph graph; graph_init(&graph, (int (*)(const void *, const void *))mst_vertex_match, NULL); int i; //插入所有的节点 for (i = 0; i < 6; ++i) { graph_ins_vertex(&graph, &m[i]); } printf("%s\n", "insert vertex success"); //插入所有的边 graph_ins_edge(&graph, &m[0], &m[6]); graph_ins_edge(&graph, &m[0], &m[7]); graph_ins_edge(&graph, &m[1], &m[8]); graph_ins_edge(&graph, &m[1], &m[9]); graph_ins_edge(&graph, &m[1], &m[10]); graph_ins_edge(&graph, &m[1], &m[11]); graph_ins_edge(&graph, &m[2], &m[12]); graph_ins_edge(&graph, &m[2], &m[13]); graph_ins_edge(&graph, &m[2], &m[14]); graph_ins_edge(&graph, &m[2], &m[15]); graph_ins_edge(&graph, &m[3], &m[16]); graph_ins_edge(&graph, &m[3], &m[17]); graph_ins_edge(&graph, &m[4], &m[18]); graph_ins_edge(&graph, &m[4], &m[19]); graph_ins_edge(&graph, &m[5], &m[20]); graph_ins_edge(&graph, &m[5], &m[21]); graph_ins_edge(&graph, &m[5], &m[22]); graph_ins_edge(&graph, &m[5], &m[23]); List span; mst(&graph, m, &span, (int (*)(const void *, const void *))mst_vertex_match); list_resetIterator(&span); while (list_hasNext(&span)) { list_moveToNext(&span); MstVertex *vertex = NULL; list_iterator(&span, (void **)(&vertex)); Student *s = (Student *)vertex->data; printf("key : %.0f", vertex->key); if (vertex->parent != NULL) { Student *sP = (Student *)(vertex->parent->data); printf(", parentid:%d, ", sP->_id); } studn_print(s); } return; }
int Steiner::steiner(const set<ListGraph::Node> terminals) { if (this->s != 0) delete this->s; this->s = new ListGraph(); if (this->sweight != 0) delete this->sweight; this->sweight = new ListGraph::EdgeMap<int>(*this->s); // perform dijkstra for every terminal ListGraph::NodeMap<Dijkstra*> dijk(this->g); for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { dijk[*it] = new Dijkstra(this->g, this->weight); dijk[*it]->dijkstra(*it); } // build intermediate graph ListGraph intermediate; ListGraph::EdgeMap<int> iweight(intermediate); map<ListGraph::Node, ListGraph::Node> imapper; for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { ListGraph::Node n = intermediate.addNode(); imapper[n] = *it; } for (ListGraph::NodeIt it1(intermediate); it1 != INVALID; ++it1) { ListGraph::NodeIt it2 = it1; for (++it2; it2 != INVALID; ++it2) { ListGraph::Edge e = intermediate.addEdge(it1, it2); iweight[e] = (*dijk[imapper[it1]]->dist)[imapper[it2]]; } } // compute mst MST mst(intermediate, iweight); mst.prim(); // Kruskal mst(intermediate, iweight); // mst.kruskal(); // build final graph map<ListGraph::Node, ListGraph::Node> smapper; for (set<ListGraph::Edge>::iterator it = mst.mst->begin(); it != mst.mst->end(); ++it) { // for each edge in the mst // add end nodes to graph ListGraph::Node u = imapper[intermediate.u(*it)]; if (smapper.count(u) == 0) smapper[u] = this->s->addNode(); ListGraph::Node v = imapper[intermediate.v(*it)]; if (smapper.count(v) == 0) smapper[v] = this->s->addNode(); ListGraph::Node last = v; ListGraph::Node cur = v; do { // walk through path cur = (*dijk[u]->pred)[cur]; if (smapper.count(cur) == 0) smapper[cur] = this->s->addNode(); // add edge to graph, if not already existing if (findEdge(*this->s, smapper[last], smapper[cur]) == INVALID) { ListGraph::Edge e = this->s->addEdge(smapper[last], smapper[cur]); (*this->sweight)[e] = (*dijk[u]->dist)[last] - (*dijk[u]->dist)[cur]; } last = cur; } while (cur != u); } // compute overall weight int overallw = 0; for (ListGraph::EdgeIt e(*this->s); e != INVALID; ++e) { overallw += (*this->sweight)[e]; } // clean up dijkstras for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it) { delete dijk[*it]; } return overallw; }
int main(int argc, char **argv) { Graph graph; MstVertex *mst_start, *mst_vertex, mst_vertex1, *mst_vertex2; PathVertex *pth_start, *pth_vertex, pth_vertex1, *pth_vertex2; TspVertex *tsp_start, *tsp_vertex; List span, paths, vertices, tour; ListElmt *element; double distance, total, x, y; int i; /***************************************************************************** * * * Compute a minimum spanning tree. * * * *****************************************************************************/ graph_init(&graph, match_mst, free); fprintf(stdout, "Computing a minimum spanning tree\n"); for (i = 0; i < MSTVCT; i++) { if ((mst_vertex = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; if (i == 0) mst_start = mst_vertex; mst_vertex->data = MstTestV[i]; if (graph_ins_vertex(&graph, mst_vertex) != 0) return 1; } for (i = 0; i < MSTECT; i++) { if ((mst_vertex2 = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; mst_vertex1.data = MstTestE[i].vertex1; mst_vertex2->data = MstTestE[i].vertex2; mst_vertex2->weight = MstTestE[i].weight; if (graph_ins_edge(&graph, &mst_vertex1, mst_vertex2) != 0) return 1; } print_graph_mst(&graph); if (mst(&graph, mst_start, &span, match_mst) != 0) return 1; for (element = list_head(&span); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s\n", (char *) mst_vertex->data, mst_vertex->parent != NULL ? (char *) mst_vertex->parent->data : "*"); } list_destroy(&span); graph_destroy(&graph); /***************************************************************************** * * * Compute shortest paths. * * * *****************************************************************************/ graph_init(&graph, match_pth, free); fprintf(stdout, "Computing shortest paths\n"); for (i = 0; i < PTHVCT; i++) { if ((pth_vertex = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; if (i == 0) pth_start = pth_vertex; pth_vertex->data = PthTestV[i]; if (graph_ins_vertex(&graph, pth_vertex) != 0) return 1; } for (i = 0; i < PTHECT; i++) { if ((pth_vertex2 = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; pth_vertex1.data = PthTestE[i].vertex1; pth_vertex2->data = PthTestE[i].vertex2; pth_vertex2->weight = PthTestE[i].weight; if (graph_ins_edge(&graph, &pth_vertex1, pth_vertex2) != 0) return 1; } print_graph_pth(&graph); if (shortest(&graph, pth_start, &paths, match_pth) != 0) return 1; for (element = list_head(&paths); element != NULL; element = list_next(element)) { pth_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s, d=%.1lf\n", (char *) pth_vertex->data, pth_vertex->parent != NULL ? (char *) pth_vertex->parent->data : "*", pth_vertex->d); } list_destroy(&paths); graph_destroy(&graph); /***************************************************************************** * * * Solve the traveling-salesman problem. * * * *****************************************************************************/ /*list_init(&vertices, free); fprintf(stdout, "Solving a traveling-salesman problem\n"); for (i = 0; i < TSPVCT; i++) { if ((tsp_vertex = (TspVertex *)malloc(sizeof(TspVertex))) == NULL) return 1; if (i == 0) tsp_start = tsp_vertex; tsp_vertex->data = TspTestV[i].vertex; tsp_vertex->x = TspTestV[i].x; tsp_vertex->y = TspTestV[i].y; if (list_ins_next(&vertices, list_tail(&vertices), tsp_vertex) != 0) return 1; } print_list_tsp(&vertices); if (tsp(&vertices, tsp_start, &tour, match_tsp) != 0) return 1; total = 0; for (element = list_head(&tour); element != NULL; element = list_next(element)) { tsp_vertex = list_data(element); if (!list_is_head(&tour, element)) { distance = sqrt(pow(tsp_vertex->x-x, 2.0) + pow(tsp_vertex->y-y, 2.0)); total = total + distance; } x = tsp_vertex->x; y = tsp_vertex->y; if (!list_is_head(&tour, element)) { fprintf(stdout, "vertex=%s, distance=%.2lf\n", (char *)tsp_vertex-> data, distance); } else fprintf(stdout, "vertex=%s\n", (char *)tsp_vertex->data); } fprintf(stdout, "total=%.2lf\n", total); list_destroy(&vertices); list_destroy(&tour);*/ return 0; }
int main (int argc, char **argv) { int r_bufid, info, bytes, msgtag, parent, endofprocess = 0; heur_prob *p = (heur_prob *) calloc(1, sizeof(heur_prob)); parent = receive(p); printf("\nWelcome, I am task %i\n\n", pvm_mytid()); while(!endofprocess){ printf("\nim gonna try to receive at parallel_process.\n"); PVM_FUNC(r_bufid, pvm_recv(-1, -1)); PVM_FUNC(info, pvm_bufinfo(r_bufid, &bytes, &msgtag, &parent)); printf("\nim still in parallel_process\n"); switch(msgtag){ case S_EXCHANGE: exchange(parent, p); break; case S_EXCHANGE2: exchange2(parent, p); break; case S_FARNEAR_INS: farnear_ins(parent, p); break; case S_FARTHEST_INS: farthest_ins(parent, p); break; case S_MST: mst(); break; case S_NEAREST_INS: nearest_ins(parent, p); break; case S_NEAR_CLUSTER: near_cluster(parent, p); break; case S_SAVINGS: savings(parent, p); break; case S_SAVINGS2: savings2(parent, p); break; case S_SAVINGS3: savings3(parent, p); break; case S_SWEEP: sweep(parent, p); break; case S_TSP_FI: tsp_fi(parent, p); break; case S_TSP_FINI: tsp_fini(parent, p); break; case S_TSP_NI: tsp_ni(parent, p); break; case STOP: endofprocess = 1; } } return 0; }
int gridSteinerFH(Graph *grid_graph, AdjList**** Edge2Adj, int width, int height, CoordData *term, int no_terminals, double *L,int net_num, int *edge_count_OUT, int **SteinerTree_OUT, int l, int K) { int i,j; /* globals */ int GRID_WIDTH, GRID_HEIGHT, NO_TERMINALS; Graph ND; /* distance network of terminals */ /*used to generate grid graph */ PathVertex *path_vertex; sPathData *sPath_vertex; CoordData *coord; /* used in shortest paths computations */ PathVertex **terminals; /* a (1D) array of terminal (pointers) */ List *tempPaths, /* tempporary */ **sPaths; /* 2d array of shortest path lists */ ListElmt *element; /* temp, used to traverse a list */ /* used in computing MST of ND */ MstVertex *mst_start, *mst_vertex, *mst_vertex1, *mst_vertex2; List TD; /* spanning tree of ND */ /* used in final steps of algorithm */ Graph NTD; /* complete distance network */ List T; /* spanning tree of NTD (eventually the steiner tree)*/ int isSteiner; /* boolean flag */ double tree_cost; /* total cost of the steiner tree (unused, this is computed after*/ GRID_WIDTH = width; GRID_HEIGHT = height; NO_TERMINALS = no_terminals; mst_start = NULL; /*-----------------------------------------------*/ /* If the number of terminals is two, then we */ /* only need to perform one call of Dijkstra to */ /* get the Steiner Tree */ /*-----------------------------------------------*/ if (NO_TERMINALS == 2) { PathVertex *v1,*v2; /* the two terminals*/ CoordData *c1,*c2; /* coordinates of the two terminals*/ List P; /* P-Array in Dijkstra's*/ ListElmt *e; /* list counter*/ List T; /* steiner tree*/ double tree_cost; int j; int first_edge,last_edge; PathVertex *u; u = NULL; /* allocate vertices */ v1 = (PathVertex*) malloc(sizeof(PathVertex)); v2 = (PathVertex*) malloc(sizeof(PathVertex)); c1 = (CoordData*) malloc(sizeof(CoordData)); c2 = (CoordData*) malloc(sizeof(CoordData)); /* set terminal data */ c1->x = term[0].x; c1->y = term[0].y; c1->z = term[0].z; c2->x = term[1].x; c2->y = term[1].y; c2->z = term[1].z; v1->data = c1; v2->data = c2; /* compute shortest path from v1 */ if (shortest(grid_graph, v1 , &P, match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* initialize the tree */ list_init(&T,NULL); /* find the end vertex (v2)*/ for (e = list_head(&P); e != NULL; e = list_next(e)) if ( match_coord(v2,list_data(e))) u = (PathVertex*)list_data(e); first_edge = 1; last_edge = 0; /* follow the end vertex back to the start vertex*/ while (u->parent != NULL) { int ux,uy,uz,upx,upy,upz; AdjList *a; ListElmt *ee; /*current vertex*/ ux = ((CoordData*)((PathVertex*)u)->data)->x; uy = ((CoordData*)((PathVertex*)u)->data)->y; uz = ((CoordData*)((PathVertex*)u)->data)->z; /*connecting vertex (parent)*/ upx = ((CoordData*)((PathVertex*)u->parent)->data)->x; upy = ((CoordData*)((PathVertex*)u->parent)->data)->y; upz = ((CoordData*)((PathVertex*)u->parent)->data)->z; /* get the index of the edge that connects (ux,uy,uz) and its parent*/ a = Edge2Adj[ux][uy][uz]; for (ee = list_head(&a->adjacent); ee != NULL; ee = list_next(ee)) { PathVertex *v; int *i; int vx,vy,vz; v = (PathVertex*)list_data(ee); vx = ((CoordData*)v->data)->x; vy = ((CoordData*)v->data)->y; vz = ((CoordData*)v->data)->z; /* found it*/ if (( vx == upx ) && ( vy == upy ) && ( vz == upz )) { /*don't insert if its a via*/ if (first_edge) { first_edge = 0; if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; } /*check if its the last edge*/ if (u->parent != NULL) if (u->parent->parent == NULL) last_edge = 1; /* don't insert if its a via*/ if (last_edge) if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; i = (int*) malloc(sizeof(int)); tree_cost += v->weight; *i = v->index; list_ins_next(&T, list_tail(&T),i); } } /* next */ u = u->parent; } /* count total edges*/ *edge_count_OUT = list_size(&T); /* write the solution (including vias)*/ if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T))))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } e = list_head(&T); for (j = 0; ((j < list_size(&T))&&(e!=NULL)); j++,e=list_next(e)) (*SteinerTree_OUT)[j] = *((int*)list_data(e)); /* free up some temps*/ free(v1->data); free(v1); free(v2->data); free(v2); list_destroy(&P); list_destroy(&T); return 0; } /*--------------------------------------------------------*/ /* General case of 3 or more terminals begins here. The */ /* above code for 2 terminals or less can be removed */ /* without affecting the block solution. However, it is */ /* faster with the special case */ /*--------------------------------------------------------*/ /* Create Path Vertices out of the original terminal set */ if ((terminals = (PathVertex**) malloc(sizeof(PathVertex*)*NO_TERMINALS))==NULL) { printf("gsFH.h : terminals mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) { int x,y,z; x = term[i].x; y = term[i].y; z = term[i].z; path_vertex = (PathVertex*) malloc(sizeof(PathVertex)); coord = (CoordData*) malloc(sizeof(CoordData)); if ((path_vertex == NULL)||(coord == NULL)) { printf("gsFH.h : terminal[i] mem allocation error\n"); fflush(stdout); exit(1); } coord->x = x; coord->y = y; coord->z = z; path_vertex->data = coord; terminals[i] = path_vertex; } /* inialize an array of list pointers used in extracting shortest paths from Dijkstra */ sPaths = (List**) malloc(sizeof(List*)*NO_TERMINALS); if (sPaths == NULL) { printf("gsFH.h : sPaths mem allocation error\n"); fflush(stdout); exit(1); } if ((tempPaths = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : tempPaths mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) if ((sPaths[i] = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : sPaths[i] mem allocation error\n"); fflush(stdout); exit(1); } /*--------------------------------------------------------------------------------------*/ /* COMPUTE THE SHORTEST PATHS */ /* Shortest paths are computed using O(EV^2) version of Dijkstras Algorithm */ /*--------------------------------------------------------------------------------------*/ /* for each terminal (stored as a path vertex), find the shortest path */ /* The shortest path for terminal[i] is stored in the List pointed to by */ /* paths[i]. */ for (i = 0; i < NO_TERMINALS; i++) { if (shortest(grid_graph, terminals[i], &tempPaths[i], match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* copy out the shortest path data, if we don't do this, it will get overwritten*/ for (j = 0; j < NO_TERMINALS; j++) if (i != j) copy_sPath(&tempPaths[i], &(sPaths[i][j]), (CoordData*)((PathVertex*)terminals[j])->data); } /*--------------------------------------------------------------------------------------------------*/ /* Generate complete distance network ND */ /*--------------------------------------------------------------------------------------------------*/ /* initialize the graph */ graph_init(&ND, match_coord, (void*)mst_vertex_free); /* insert the verticies. Verticies consist of all the terminals */ for (i = 0; i < NO_TERMINALS; i++) { /* allocate space for a MST vertex */ if ((mst_vertex = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("Error allocating space for mst_vertex\n"); printf("Terminating..\n"); return 1; } /* if it's the first, make it the start. It doesn't matter which one is the start */ if (i == 1) mst_start = mst_vertex; /* set the data */ if ((coord = (CoordData*) malloc(sizeof(CoordData)))==NULL) { printf("gsFH.h : coord mem allocation error\n"); fflush(stdout); exit(1); } coord->x = ((CoordData*)(((PathVertex*)terminals[i])->data))->x; coord->y = ((CoordData*)(((PathVertex*)terminals[i])->data))->y; coord->z = ((CoordData*)(((PathVertex*)terminals[i])->data))->z; mst_vertex->data = coord; /* insert */ if (graph_ins_vertex(&ND, mst_vertex) != 0) { printf("Error inserting vertex into mst_graph\n"); printf("Terminating...\n"); return 1; } } /* now we must insert the edges into the distance network graph ND. We do this by accessing the shortest path lists (sPath) computed in the previous step */ for (i = 0; i < NO_TERMINALS; i++) { int ux,uy,uz; ux = ((CoordData*)((PathVertex*)terminals[i])->data)->x; uy = ((CoordData*)((PathVertex*)terminals[i])->data)->y; uz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; for (j = 0; j < NO_TERMINALS; j++) { int vx,vy,vz; /* shouldn't be an edge from a terminal to itself */ if (i != j) { double weight; CoordData *v1,*v2; int eCode; vx = ((CoordData*)((PathVertex*)terminals[j])->data)->x; vy = ((CoordData*)((PathVertex*)terminals[j])->data)->y; vz = ((CoordData*)((PathVertex*)terminals[j])->data)->z; /* now we must find how far away vx is from vy. we do this by looking for at the head element in sPath[i][j] */ element = list_head(&(sPaths[i][j])); sPath_vertex = list_data(element); weight = ((sPathData*)sPath_vertex)->d; /* allocate an edge */ if ((v1 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v1 mem allocation error\n"); fflush(stdout); exit(1); } if ((v2 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v2 mem allocation error\n"); fflush(stdout); exit(1); } v1->x = ux; v1->y = uy; v1->z = uz; v2->x = vx; v2->y = vy; v2->z = vz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data =v1; mst_vertex2->data = v2; mst_vertex2->weight = weight; if ((eCode = graph_ins_edge(&ND, mst_vertex1, mst_vertex2)) != 0) { printf("Error inserting edge into ND\n"); printf("graph_ins_edge returned the value %d\n",eCode); return 1; } free(mst_vertex1->data); free(mst_vertex1); }/* endif i!=j */ }/* endfor j */ }/* endfor i */ /*--------------------------------------------------------------------------------------------------*/ /* Copmute TD (Min Span Tree of ND) */ /*--------------------------------------------------------------------------------------------------*/ if (mst(&ND, mst_start,&TD, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ /* initialize */ for ( element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------------------*/ /* Find N[TD] */ /*--------------------------------------------------------------------------------------------------*/ graph_init(&NTD,match_coord,(void*)mst_vertex_free); /* for each edge in TD */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { MstVertex *nextVertex; int v,p; p = -1; v = -1; nextVertex = list_data(element); /* if it is not the root */ if (nextVertex->parent != NULL) { int vx,vy,vz,px,py,pz; ListElmt *currentV, *nextV; int done; vx = ((CoordData*)((MstVertex*)nextVertex)->data)->x; vy = ((CoordData*)((MstVertex*)nextVertex)->data)->y; vz = ((CoordData*)((MstVertex*)nextVertex)->data)->z; px = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->x; py = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->y; pz = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->z; /* find terminal index of nextVertex and nextVertex->parent */ for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ((tx == vx)&&(ty == vy)&&(tz == vz)) v = i; if ((tx == px)&&(ty == py)&&(tz == pz)) p = i; } /* now, we must step through the list of sPathData elements found in sPaths[p][v]. For each element in the list, we must insert vertices for the vertex and parent, then make an edge with the appropriate weight and insert it */ currentV = list_head(&(sPaths[p][v])); nextV = list_next(currentV); done = 0; while ( !done ) { MstVertex *u,*v, *mst_vertex1, *mst_vertex2; CoordData *uc,*vc; sPathData *currentVData, *nextVData; int cvx,cvy,cvz,nvx,nvy,nvz; double weight; /*---------------------------------------*/ /* insert vertices u and v into NTD */ /*---------------------------------------*/ /* make a vertex for currentV and nextV */ u = (MstVertex*) malloc(sizeof(MstVertex)); v = (MstVertex*) malloc(sizeof(MstVertex)); uc = (CoordData*) malloc(sizeof(CoordData)); vc = (CoordData*) malloc(sizeof(CoordData)); if ((u == NULL)||(uc==NULL)||(v==NULL)||(vc==NULL)) { printf("gsFH.h : error allocating vertex for NTD\n"); fflush(stdout); exit(1); } /* get vertices from the sPaths list */ currentVData = list_data(currentV); nextVData = list_data(nextV); /* get vertex data */ cvx = ((CoordData*)((sPathData*)currentVData)->vertex)->x; cvy = ((CoordData*)((sPathData*)currentVData)->vertex)->y; cvz = ((CoordData*)((sPathData*)currentVData)->vertex)->z; nvx = ((CoordData*)((sPathData*)nextVData)->vertex)->x; nvy = ((CoordData*)((sPathData*)nextVData)->vertex)->y; nvz = ((CoordData*)((sPathData*)nextVData)->vertex)->z; /* set vertex data */ uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; u->data = uc; v->data = vc; /* calculate weight between u and v */ weight = currentVData->d - nextVData->d; /* try and insert u, if it exists, then delete the memory we allocated for it */ if ( graph_ins_vertex(&NTD, u) == 1 ) { free(uc); free(u); } else { /* doesnt' matter which one is the start */ mst_start = u; } /* try and insert v, if it exists, then delete the memorr we allocated for it */ if ( graph_ins_vertex(&NTD, v) == 1) { free(vc); free(v); } /* now the vertices u and v are in the graph. we now have to make an edge for uv */ /* make edge going forward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = uc; mst_vertex2->data = vc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(vc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* make edge going backward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = vc; mst_vertex2->data = uc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(uc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* follow pointers */ currentV = list_next(currentV); nextV = list_next(nextV); /* check to see if we're finished */ if (nextV == NULL) done = 1; } } } /*----------------------------------------------------------------------------------------------------------*/ /* Compute T (minimum spanning tree of NTD) */ /*----------------------------------------------------------------------------------------------------------*/ /* call minimum spanning tree subroutine */ if (mst(&NTD, mst_start,&T, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ for ( element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------*/ /* Compute Steiner Tree Sk */ /*--------------------------------------------------------------------------------------*/ isSteiner = 0; /* we remove all leaves that arent' terminals, when all leaves are terminals then we have a Steiner Tree */ while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int found; found = 0; for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ( (tx==mx)&&(ty==my)&&(tz==mz)) found = 1; } /* remove it if we can't find it */ if (!found) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* we can further eliminate vias that connect to a terminal leaf. These are not neccessary*/ isSteiner = 0; while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int remove; int px,py; remove = 0; px = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->x; py = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->y; if ((px == mx)&&(py == my)) remove = 1; /* remove it if neccessary */ if (remove) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* get the total cost of the tree */ tree_cost = 0; for (element = list_head(&T); element != NULL; element = list_next(element)) { CoordData *u, *v; mst_vertex = list_data(element); if (( mst_vertex->parent == NULL)) continue; else { double temp; u = (CoordData*)mst_vertex->data; v = (CoordData*)mst_vertex->parent->data; /* look up cost of edge uv */ temp = find_edge_weight(grid_graph,u,v); tree_cost += temp; } } *edge_count_OUT = list_size(&T)-1; if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T)-1)))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } i = 0; for ( element = list_head(&T); element != NULL; element = list_next(element)) { int vx,vy,vz,px,py,pz; int tx,ty,tz; AdjList *a; ListElmt *e; int edge_index; double edge_weight; mst_vertex = list_data(element); vx = ((CoordData*)mst_vertex->data)->x; vy = ((CoordData*)mst_vertex->data)->y; vz = ((CoordData*)mst_vertex->data)->z; if (mst_vertex->parent != NULL) { px = ((CoordData*)mst_vertex->parent->data)->x; py = ((CoordData*)mst_vertex->parent->data)->y; pz = ((CoordData*)mst_vertex->parent->data)->z; edge_weight = mst_vertex->weight; } else { px = -1; py = -1; pz = -1; } a = (AdjList*)Edge2Adj[vx][vy][vz]; tx = ((CoordData*)((PathVertex*)(a->vertex))->data)->x; ty = ((CoordData*)((PathVertex*)(a->vertex))->data)->y; tz = ((CoordData*)((PathVertex*)(a->vertex))->data)->z; for ( e = list_head(&(a->adjacent)); e != NULL; e = list_next(e) ) { PathVertex *p; p = (PathVertex*)list_data(e); tx = ((CoordData*)p->data)->x; ty = ((CoordData*)p->data)->y; tz = ((CoordData*)p->data)->z; if ((tx == px)&&(ty == py)&&(tz == pz)) { /*found*/ edge_index = p->index; (*SteinerTree_OUT)[i] = edge_index; i++; } } } /*-------------------------------------------------------------------------------------*/ /* Clean Up */ /*-------------------------------------------------------------------------------------*/ /* free our list of temporary paths*/ for (i = 0; i < NO_TERMINALS; i++) list_destroy(&tempPaths[i]); free(tempPaths); /* destroy distance network*/ graph_destroy(&ND); /* deystroy all the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) for (j = 0; j < NO_TERMINALS; j++) if ( i != j ) list_destroy(&sPaths[i][j]); /* destroy the pointers to the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) free(sPaths[i]); free(sPaths); /* destroy the minimum spanning tree*/ list_destroy(&TD); /* destroy grid spanning tree*/ graph_destroy(&NTD); /* destroy the terminal list*/ for (i = 0; i < NO_TERMINALS; i++) { path_vertex_free(terminals[i]); } free(terminals); /*destroy the steiner tree*/ list_destroy(&T); return 0; }
int main(int argc, char** argv) { util::ProgramOptions::init(argc, argv); logger::LogManager::init(); host::Graph graph; host::ArcWeights arcWeights(graph); host::ArcLabels arcLabels(graph); host::ArcTypes arcTypes(graph); host::MultiEdgeFactors multiEdgeFactors; if (optionGraphFile) { host::WeightedGraphReader graphReader(optionGraphFile.as<std::string>()); graphReader.fill(graph, arcWeights, arcLabels, arcTypes); } else { RandomWeightedGraphGenerator randomWeightedGraphGenerator( optionRandomGraphNodes, optionRandomGraphArcs, optionRandomGraphMinWeight, optionRandomGraphMaxWeight); randomWeightedGraphGenerator.fill(graph, arcWeights, arcLabels, arcTypes); std::cout << "generated a random graph with " << lemon::countNodes(graph) << " nodes" << std::endl; } if (optionMultiEdgeFactorFile) { host::MultiEdgeFactorReader factorReader(optionMultiEdgeFactorFile.as<std::string>()); factorReader.fill(graph, arcLabels, multiEdgeFactors); } if (lemon::countArcs(graph) <= 100) { for (host::Graph::ArcIt arc(graph); arc != lemon::INVALID; ++arc) std::cout << graph.id(graph.source(arc)) << " - " << graph.id(graph.target(arc)) << ": " << arcWeights[arc] << std::endl; } // the minimal spanning tree host::ArcSelection mst(graph); // search the minimal spanning tree under consideration of conflicting // candidates host::HostSearch hostSearch(graph); host::ExplicitWeightTerm weightTerm(graph, arcWeights); host::CandidateConflictTerm cctTerm(graph, arcTypes); host::MultiEdgeFactorTerm mefTerm(graph, multiEdgeFactors); hostSearch.addTerm(&weightTerm); hostSearch.addTerm(&cctTerm); hostSearch.addTerm(&mefTerm); double length; bool constraintsFulfilled = hostSearch.find(mst, length, optionNumIterations.as<unsigned int>()); if (constraintsFulfilled) std::cout << "found a minimal spanning tree that fulfills the constraints" << std::endl; if (lemon::countArcs(graph) <= 100) { std::cout << "minimal spanning tree is:" << std::endl; for (host::Graph::ArcIt arc(graph); arc != lemon::INVALID; ++arc) std::cout << graph.id(graph.source(arc)) << " - " << graph.id(graph.target(arc)) << ": " << mst[arc] << std::endl; } std::cout << "length of minimal spanning tree is " << length << std::endl; if (optionWriteResult) { host::WeightedGraphWriter graphWriter(optionWriteResult.as<std::string>()); graphWriter.write(graph, arcWeights, mst); std::cout << "wrote result to " << optionWriteResult.as<std::string>() << std::endl; } return 0; }