//#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; }
//#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; }