コード例 #1
0
ファイル: lowstretch2.cpp プロジェクト: jiecchen/LapSolver
//#undef __FUNCT__  
//#define __FUNCT__ "LowStretchSpanningTreeHelper"
void LowStretchSpanningTreeHelper(graph_t& g,const int root,const float alpha,
				 graph_t& h)//,int perm[])
{
    int n,i,j,k;
    std::vector<int> size,x,y;
    std::vector<std::vector<int> > idx;
    int ierr;

//  PetscFunctionBegin;
    
    weight_map_t edge_weight_g = get(edge_weight_t(),g);
//    VertexWeight vertex_weight_h = get(vertex_weight_t(),h);
    n = num_vertices(g);

    if (n > 2) {
	ierr = StarDecomp(g,root,1.0/3.0,alpha,k,size,idx,x,y);
	j = 0;
	for (i=1;i<=k;i++) {
	    graph_t& g1 = g.create_subgraph(idx[i].begin(),idx[i].end());
	    graph_t& h1 = h.create_subgraph(idx[i].begin(),idx[i].end());
	    LowStretchSpanningTreeHelper(g1,g1.global_to_local(g.local_to_global(x[i-1])),alpha,h1);//,perm+j);
	    j += size[i];
	}
	graph_t& g1 = g.create_subgraph(idx[0].begin(),idx[0].end());
	graph_t& h1 = h.create_subgraph(idx[0].begin(),idx[0].end());
	LowStretchSpanningTreeHelper(g1,g1.global_to_local(g.local_to_global(root)),alpha,h1);//,perm+j);
	for (i=0;i<k;i++) {
	    float w = get(edge_weight_g,edge(x[i],y[i],g).first);
	    add_edge(x[i],y[i],w,h);
//	    put(vertex_weight_h,x[i],get(vertex_weight_h,x[i])+w);
//	    put(vertex_weight_h,y[i],get(vertex_weight_h,y[i])+w);
	}
    } else if (n == 2) {
	graph_traits<graph_t>::edge_descriptor e = *(out_edges(root,g).first);
	int t = target(e,g);

	float w = get(edge_weight_g,e);
	add_edge(root,t,w,h);
//	put(vertex_weight_h,root,get(vertex_weight_h,root)+w);
//	put(vertex_weight_h,t,get(vertex_weight_h,t)+w);
//	perm[0] = g.local_to_global(t);
//	perm[1] = g.local_to_global(root);
    } else /* n == 1 */ {
//	perm[0] = g.local_to_global(root);
    }

  

    //return 0;
}
コード例 #2
0
ファイル: lowstretch2.cpp プロジェクト: jiecchen/LapSolver
//#undef __FUNCT__  
//#define __FUNCT__ "LowStretchSpanningTreeHelper"
int StarDecomp(graph_t g,const int root,const float delta,const float epsilon,
	       int& k,std::vector<int>& size,std::vector<std::vector<int> >& idx,
	       std::vector<int>& x,std::vector<int>& y)
{
    int n,m,edgesLeft;
    //PetscErrorCode ierr;
    //ShortestPathPriorityQueue pq;
//    float radius;

    std::vector<int> centerIdx;
    


    //PQNode node;

//  PetscFunctionBegin;

    //printf("going to into ball cut segment\n");

    graph_t& root_graph = g.is_root() ? g : g.root();
    weight_map_t edge_weight_g = get(edge_weight,root_graph);  // actually all property maps are same! so don't worry!
    f_edges_t f_edges_g = get(edge_index, g);
    vert_dist_t root_dist = get(vertex_distance, g);
    n = num_vertices(g);
    m = num_edges(g);
    edgesLeft = m;

//    std::vector<int> 
//    std::vector<int> pred(n,-1);
    //std::vector<int> succ[n]; 
    std::vector<int>::iterator i;
//    float dist[n];
//    std::vector<bool> taken(n,false);

    // running dijkstra
    float radius;
    std::vector<vertex_descriptor> ordered_nodes(n);
    int cntr = 0;
    //std::vector<float> root_dist(n);
    std::vector<int> pred(n, -1);
    std::vector<int> color_map(n, WHITE);
    //int num_root_edges = g.is_root() ? num_edges(g) : num_edges(g.root());
    //printf("num_root_edges: %d\n", num_root_edges);
    //std::vector<bool> fedges(num_root_edges);// turns out edge_index not local fedges(m, false);
    p_comp_min_class comp(&root_dist);
    identity_property_map ident;
    PropertyMinQueue pq(n, comp, ident);
    root_dist[root] = 0.0;
    pred[root] = root;
    pq.push(root);
    //printf("about to go to dijkstra while loop\n");
    while(!pq.empty())
    {
	//printf("top of while\n");
	vertex_descriptor u = pq.top();
	pq.pop();
	color_map[u] = BLACK;
	// put the edge that got us to u into fedges
	vertex_descriptor pred_u = pred[u];
	//radius = root_dist[u];
	ordered_nodes[cntr++] = u;
	if (pred_u != u)
	{
	    edge_descriptor e = edge(pred_u, u, g).first;
	    put(f_edges_g, e, true);
	}
	//printf("after fedges\n");
	adjacency_it i, i_end;
	for (tie(i, i_end) = adjacent_vertices(u, g); i != i_end; i++)
	{
	    vertex_descriptor v = *i;
	    if (color_map[v] == WHITE)
	    {
		//printf("before pred[v]\n");
		pred[v] = u;
		//printf("before edge_weight_g; pred_u: %d, u: %d\n", pred_u, u);
		root_dist[v] = root_dist[u] + 1.0/get(edge_weight_g, g.local_to_global(edge(u,v, g).first));
		//printf("before color_map\n");
		color_map[v] = GREY;
		pq.push(v);
	    }
	    else if (color_map[v] == GREY)
	    {
		float new_dist = root_dist[u] + 1.0/get(edge_weight_g, g.local_to_global(edge(u, v, g).first));
		if (new_dist < root_dist[v])
		{
		    root_dist[v] = new_dist;
		    pred[v] = u;
		    pq.update(v);
		}
	    }
	}
    }

    //printf("did dijkstra\n");

    radius = root_dist[ordered_nodes.back()];
    float min_radius = delta*radius;
    int center_size = 0;
    float boundary = 0.0;
    int edge_count = 0;
    
    // repurpose color_map to tell whether nodes are in ball or not
    color_map.clear();             // does clear cause mem alloc slowness
//    root_dist.clear();

    //color_map.resize(n, WHITE); 
    std::vector<int> partition_map(n, -1); // -1: not in a partition yet , 0 -> n: the partion number (0= center ball)
    int cur_part = 0;
    while (root_dist[ordered_nodes[center_size]] < min_radius
	|| boundary > (edge_count+1)*log(m)/(log(2.0)*(1.0-2.0*delta)*radius))
    {
	vertex_descriptor u = ordered_nodes[center_size++];
	partition_map[u] = cur_part;
	centerIdx.push_back(g.local_to_global(u));
	adjacency_it i, i_end;
	for (tie(i, i_end) = adjacent_vertices(u, g); i != i_end; i++)
	{
	    vertex_descriptor v = *i;
	    if (partition_map[v] != cur_part)
	    {
		edge_count++;
		boundary += get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
	    }
	    else
		boundary -= get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
	}
    }
    size.push_back(centerIdx.size());
    idx.push_back(centerIdx);
    
    // NOTE we found center region but have not done anything about returning it yet!

    // center region should now just be the first center_size nodes in ordered_nodes
    // find "shell" around ball that make up potential anchor
    std::queue<vertex_descriptor> anchor_q;
    for (int i = center_size; i < n; i++)
    {
	vertex_descriptor u = ordered_nodes[i];
	adjacency_it neighbor_i, neighbor_end;
	for (tie(neighbor_i, neighbor_end) = adjacent_vertices(u, g); neighbor_i != neighbor_end; neighbor_i++)
	{
	    vertex_descriptor v = *neighbor_i;
	    if (partition_map[v] == cur_part)
	    {
		anchor_q.push(u);
		break;
	    }
	}
    }

    //printf("done with ball cut segment\n");
    
    // now we make cones
    while (!anchor_q.empty())
    {
	vertex_descriptor anchor = anchor_q.front();
	anchor_q.pop();
	if (partition_map[anchor] >= 0)   // have we already included node in new cone
	    continue;

	cur_part++; // cones numbered 1,2,3,...

	std::vector<int> cone_idx;
	std::vector<int> cone_color_map(n, WHITE);
	//std::vector<float> cone_dist(n);
	vert_dist_t cone_dist = get(vertex_distance, g);
	//std::vector<vertex_descriptor> cone_ordered_nodes(n);
	int cone_edge_count = 0;
	int cone_internal_edge_count = 0;
	float cone_boundary = 0.0;
	
	p_comp_min_class cone_comp(&cone_dist);
	//identity_property_map cone_ident;
	PropertyMinQueue cone_pq(n, cone_comp, ident);

	
	cone_dist[anchor] = 0.0;
	cone_color_map[anchor] = GREY;
	cone_pq.push(anchor);
	
	//int node_cntr = 0;
	bool initialized_cone = false; // i.e. have we included all nodes within dist 0.0
	float cone_r = 0.0;
	float init_r_limit = 0.0;
	float boundary_limit = 0.0;
	while (!cone_pq.empty())
	{
	    vertex_descriptor u = cone_pq.top();
	    float new_r = cone_dist[u];
	    if (!initialized_cone && new_r > init_r_limit + SMIDGEN)
	    {
		initialized_cone = true;
		if (cone_edge_count == 0)
		    boundary_limit = log(m+1)*2.0/(log(2.0) * epsilon);
		else
		    boundary_limit = cone_edge_count * log(m / cone_internal_edge_count) / (log(2.0) * epsilon); // (edgeCount)*log(edgesLeft*1.0/initialInternalConeEdges)*2.0/(log(2.0)*epsilon*radius))
	    }

	    if (initialized_cone
		&& new_r > cone_r + SMIDGEN
		&& cone_boundary <= boundary_limit)
		break;
	    cone_r = new_r;

	    cone_pq.pop();
	    cone_color_map[u] = BLACK;
	    partition_map[u] = cur_part;
	    cone_idx.push_back(g.local_to_global(u));

	    adjacency_it i, i_end;
	    for (tie(i, i_end) = adjacent_vertices(u, g); i != i_end; i++)
	    {
		// calculate boundary/volume props
		vertex_descriptor v = *i;
		if (partition_map[v] != cur_part)
		{
		    cone_edge_count++;
		    cone_boundary += get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
		}
		else
		{
		    cone_boundary -= get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
		    cone_internal_edge_count++;
		}

		// consider more nodes
		if (partition_map[v] < 0)
		{
		    //int e_local_index = get(edge_index_g, g.global_to_local(edge(u,v,g).first));
		    //int e_index = get(edge_index_g, edge(u,v,g).first);
		    
		    //printf("e_index:%d  num_edges:%d  num_edges_root:%d \n", num_edges(g), num_edges(g.root()));
		    if (cone_color_map[v] == WHITE
			&& get(f_edges_g, edge(u,v,g).first))
		    {
			cone_color_map[v] = GREY;
			cone_dist[v] = cone_dist[u];
			cone_pq.push(v);
		    }
		    else if (cone_color_map[v] == WHITE
			     && !get(f_edges_g, edge(u,v,g).first))
		    {
			cone_color_map[v] = GREY;
			cone_dist[v] = cone_dist[u] + get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
			cone_pq.push(v);
		    }
		    else if (cone_color_map[v] == GREY
			     && get(f_edges_g, edge(u,v,g).first))
		    {
			float new_dist = cone_dist[u];  // note this should always be at least as small as old dist
			if (new_dist < cone_dist[v])
			{
			    cone_dist[v] = new_dist;
			    cone_pq.update(v);
			}
		    }
		    else if (cone_color_map[v] == GREY
			     && !get(f_edges_g, edge(u,v,g).first))
		    {
			float new_dist = cone_dist[u] + get(edge_weight_g, g.local_to_global(edge(u,v,g).first));
			if (new_dist < cone_dist[v])
			{
			    cone_dist[v] = new_dist;
			    cone_pq.update(v);
			}
		    }
		}		    
	    }
	}
	x.push_back(anchor);
	y.push_back(pred[anchor]);
	size.push_back(cone_idx.size());
	idx.push_back(cone_idx);
    }
    k = cur_part;
// still have to pass back the new partionings etc.




//     /** form tree of shortest paths to root **/
//     graph_traits<graph_t>::out_edge_iterator e, e_end;  
//     for (tie(e,e_end)=out_edges(root,g); e!=e_end; e++) {
// 	int t = target(*e,g);
// 	pq.push(PQNode(t,root,1.0/get(edge_weight_g,*e)));
//     }
//     pred[root] = root;
//     while (!pq.empty()) {
// 	node = pq.top();pq.pop();
// 	if (pred[node.vertex] == -1) {
// 	    succ[node.pred].push_back(node.vertex);
// 	    pred[node.vertex] = node.pred;
// 	    dist[node.vertex] = node.dist;
// 	    for (tie(e,e_end)=out_edges(node.vertex,g); e!=e_end; e++) {
// 		int t = target(*e,g);
// 		if (pred[t] == -1) {
// 		    pq.push(PQNode(t,node.vertex,node.dist+1.0/get(edge_weight_g,*e)));
// 		}
// 	    }
// 	    radius = node.dist;
// 	}
//     }

//     /** BALL CUT **/
//     for (i=succ[root].begin();i!=succ[root].end();i++) {
// 	pq.push(PQNode(*i,dist[*i]));
//     }
//     float boundary = 0;
//     int edgeCount = 0; // all edges not just edges on boundary?
//     centerIdx.push_back(g.local_to_global(root));
//     taken[root] = true;//PETSC_TRUE;
//     centerSize = 1;
//     for (tie(e,e_end)=out_edges(root,g); e!=e_end; e++) {
// 	boundary += get(edge_weight_g,*e);
// 	edgeCount++;
//     }
//     const float minRadius = delta*radius;
//     while (dist[pq.top().vertex] < minRadius) {
// 	assert(!pq.empty());
// 	node = pq.top();pq.pop();
// 	centerIdx.push_back(g.local_to_global(node.vertex));
// 	taken[node.vertex] = true;//PETSC_TRUE;
// 	centerSize++;
// 	for (tie(e,e_end)=out_edges(node.vertex,g); e!=e_end; e++) {
// 	    if (taken[target(*e,g)]) {
// 		boundary -= get(edge_weight_g,*e);
// 	    } else {
// 		boundary += get(edge_weight_g,*e);
// 		edgeCount++;
// 	    }
// 	}
// 	for (i=succ[node.vertex].begin();i!=succ[node.vertex].end();i++) {
// 	    pq.push(PQNode(*i,dist[*i]));
// 	}
//     }
//     while (boundary > (edgeCount+1)*log(m)/(log(2)*(1-2*delta)*radius)) {
// 	assert(!pq.empty());
// 	node = pq.top();pq.pop();
// 	centerIdx.push_back(g.local_to_global(node.vertex));
// 	taken[node.vertex] = true;//PETSC_TRUE;
// 	centerSize++;
// 	for (tie(e,e_end)=out_edges(node.vertex,g); e!=e_end; e++) {
// 	    if (taken[target(*e,g)]) {
// 		boundary -= get(edge_weight_g,*e);
// 	    } else {
// 		boundary += get(edge_weight_g,*e);
// 		edgeCount++;
// 	    }
// 	}
// 	for (i=succ[node.vertex].begin();i!=succ[node.vertex].end();i++) {
// 	    pq.push(PQNode(*i,dist[*i]));
// 	}
//     }
//     size.push_back(centerSize);
//     idx.push_back(centerIdx);
//     edgesLeft -= edgeCount;

//     k = 0;
//     assert(!pq.empty());
//     std::queue<int> anchor_q;
//     ShortestPathPriorityQueue cone_pq;
//     std::vector<int> cone_succ[n]; 
//     std::vector<bool> cone_found(n,false);//PETSC_FALSE);

//     /** form tree of shortest paths to an anchor **/
//     while (!pq.empty()) {
// 	node = pq.top();pq.pop();
// 	cone_found[node.vertex] = true;//PETSC_TRUE;
// 	anchor_q.push(node.vertex);
// 	for (tie(e,e_end)=out_edges(node.vertex,g); e!=e_end; e++) {
// 	    int t = target(*e,g);
// 	    if (!taken[t]) {
// 		cone_pq.push(PQNode(t,node.vertex,1.0/get(edge_weight_g,*e)));
// 	    }
// 	}
//     }
//     while (!cone_pq.empty()) {
// 	node = cone_pq.top();cone_pq.pop();
// 	if (!cone_found[node.vertex]) {
// 	    cone_succ[node.pred].push_back(node.vertex);
// 	    cone_found[node.vertex] = true;//PETSC_TRUE;
// 	    for (tie(e,e_end)=out_edges(node.vertex,g); e!=e_end; e++) {
// 		int t = target(*e,g);
// 		if (!taken[t] && !cone_found[t]) {
// 		    cone_pq.push(PQNode(t,node.vertex,node.dist+1.0/get(edge_weight_g,*e)));
// 		}
// 	    }
// 	}
//     }

//     while (!anchor_q.empty()) {
// 	/** CONE CUT **/
// 	int anchor = anchor_q.front();anchor_q.pop();
// 	if (!taken[anchor]) {
// 	    int v;
// 	    int thisSize = 0;
// 	    std::vector<int> thisIdx;
// 	    std::queue<int> q;
// 	    ShortestPathPriorityQueue mycone_pq;
// 	    std::vector<bool> mycone_taken(n,false);//);PETSC_FALSE);
// 	    int initialInternalConeEdges = 0;

// 	    boundary = 0;
// 	    edgeCount = 0;
// 	    q.push(anchor);
// 	    while (!q.empty()) {
// 		v = q.front();q.pop();
// 		taken[v] = true;//PETSC_TRUE;
// 		mycone_taken[v] = true;//PETSC_TRUE;
// 		thisIdx.push_back(g.local_to_global(v));
// 		thisSize++;
// 		for (i=cone_succ[v].begin();i!=cone_succ[v].end();i++) {
// 		    q.push(*i);
// 		}
// 		for (tie(e,e_end)=out_edges(v,g); e!=e_end; e++) {
// 		    int t = target(*e,g);
// 		    if (!taken[t]) {
// 			mycone_pq.push(PQNode(t,v,1.0/get(edge_weight_g,*e)));
// 			boundary += get(edge_weight_g,*e);
// 			edgeCount++;
// 		    } else if (mycone_taken[t]) {
// 			boundary -= get(edge_weight_g,*e);
// 			initialInternalConeEdges++;
// 		    }
// 		}
// 	    }
// 	    if (initialInternalConeEdges < edgesLeft) {
// 		while (initialInternalConeEdges == 0 ?
// 		       boundary > (edgeCount+1)*log(edgesLeft+1)*2.0/(log(2.0)*epsilon*radius) : 
// 		       boundary > (edgeCount)*log(edgesLeft*1.0/initialInternalConeEdges)*2.0/(log(2.0)*epsilon*radius))
// 		{
// 		    assert(!mycone_pq.empty());
// 		    node = mycone_pq.top();mycone_pq.pop();
// 		    if (!mycone_taken[node.vertex]) {
// 			q.push(node.vertex);
// 			while (!q.empty()) {
// 			    v = q.front();q.pop();
// 			    taken[v] = true;//PETSC_TRUE;
// 			    mycone_taken[v] = true;//PETSC_TRUE;
// 			    thisIdx.push_back(g.local_to_global(v));
// 			    thisSize++;
// 			    for (i=cone_succ[v].begin();i!=cone_succ[v].end();i++) {
// 				q.push(*i);
// 			    }
// 			    for (tie(e,e_end)=out_edges(v,g); e!=e_end; e++) {
// 				int t = target(*e,g);
// 				if (!taken[t]) {
// 				    mycone_pq.push(PQNode(t,v,node.dist+1.0/get(edge_weight_g,*e)));
// 				    boundary += get(edge_weight_g,*e);
// 				    edgeCount++;
// 				} else if (mycone_taken[t]) {
// 				    boundary -= get(edge_weight_g,*e);
// 				}
// 			    }
// 			}
// 		    }
// 		}
// 	    }
// 	    edgesLeft -= edgeCount;
// 	    size.push_back(thisSize);
// 	    idx.push_back(thisIdx);
// 	    x.push_back(anchor);
// 	    y.push_back(pred[anchor]);
// 	    k++;
// 	}
//     }
    
  

//     /*
//     // pseudo cone cut
//     while (!pq.empty()) {
//     node = pq.top();pq.pop();

//     PetscInt thisSize = 1;
//     std::vector<PetscInt> thisIdx;
//     std::queue<PetscInt> q;

//     thisIdx.push_back(g.local_to_global(node.vertex));
//     for (i=succ[node.vertex].begin();i!=succ[node.vertex].end();i++) {
//     q.push(*i);
//     }

//     PetscInt v;
//     while (!q.empty()) {
//     v = q.front();q.pop();
//     thisSize++;
//     thisIdx.push_back(g.local_to_global(v));
//     for (i=succ[v].begin();i!=succ[v].end();i++) {
//     q.push(*i);
//     }
//     }
//     size.push_back(thisSize);
//     idx.push_back(thisIdx);
//     x.push_back(node.vertex);
//     y.push_back(pred[node.vertex]);
//     k++;
//     }
//     */

  


    return 0;
}