Ejemplo n.º 1
0
void init() {
    mst(head, -1);
    ecnt = 0;
    mst(dfn, 0);
    mst(low, 0);
    cnt = 0;
    nblock = 0;
    mst(evis, 0);
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
Archivo: mst.c Proyecto: BelfordZ/cAlgs
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;
}
Ejemplo n.º 4
0
void main()
{
	clrscr();
	read();
	mst();
	out();
}
Ejemplo n.º 5
0
  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;

  }
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
/**
	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];
}
Ejemplo n.º 9
0
Archivo: wrap.c Proyecto: kahrs/cda
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);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
/*
 * 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;
}
Ejemplo n.º 12
0
//#################### 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();
}
Ejemplo n.º 13
0
/** 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;
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
/**
 * 测试最小生成树
 */
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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
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;

}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
Archivo: host.cpp Proyecto: funkey/host
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;
}