/****************************************************************************** * Create Cluster Graph * ******************************************************************************/ static void create_cluster_graph(Graph::Graph& g, std::vector<int> clusters, int nCluster, std::vector<WgtType>& radii, Graph::Graph& cg) { // Steps // 1. get the linkage between cluster // 2. link the edge using namespace std; vector< vector<int> > cls_connection(nCluster, vector<int>(nCluster, 0)); vector<int> cls_nodes; vector<int> nbors; // Step 1 for (int c=0; c<nCluster; ++c) { cls_nodes.clear(); cls_nodes.resize(0); for (int i=0; i<g.get_num_vtxs(); ++i) if (clusters.at(i) == c) cls_nodes.push_back(i); for (int i=0; i<cls_nodes.size(); ++i) { nbors = g.adj(cls_nodes.at(i)); for (int n=0; n<nbors.size(); ++n) { if (clusters.at(nbors.at(n)) != c) cls_connection.at(c).at(clusters.at(nbors.at(n))) += 1; } } } // Step 2 for (int i=0; i<nCluster; ++i) { for (int j=i+1; j<nCluster; ++j) if (cls_connection.at(i).at(j) != 0) cg.add_edge(i, j, radii.at(i) + radii.at(j)); } }
static void force_direct_with_torque(char* outfilePath, Graph::Graph& g, Graph::Graph& cg, std::vector< std::pair<int, int> > c_edges, DenseMat& cluster_dist_mat, std::vector<int>& clusters, std::vector< std::vector<CoordType> >& center_coord, std::vector< WgtType >& radii, std::vector< std::vector<CoordType> >& coord, int iteration, double initStep) { // Iteration Steps // 1. calculate repulsive displacement // 2. calculate attractive displacement // 3. calculate rotate angle // 4. shift and rotate the cluster nodes and corresponding nodes using namespace std; using namespace boost::posix_time; // algorithm declaration double step = initStep; double curr_energy = INFINITY_ENERGY; double pre_energy; // for iteration dumping fstream fo; // [modified!] clusters_nodes vector<VtxType> cluster_nodes; // id: vtx id of clustered graph // val: vtx id in whole graph // force equilibrium declaration vector< pair<WgtType, WgtType> > node_disp(cg.get_num_vtxs()); vector< WgtType > rotate_angles(cg.get_num_vtxs()); pair<WgtType, WgtType> pos_diff; double rep_force; double att_force; double disp_x; double disp_y; double disp_val; int e_u; // u in c-edge (u, v) int e_v; // v in c-edge (u, v) double disp_u_x; double disp_u_y; double disp_v_x; double disp_v_y; CoordType c_x; // center of u's x coord CoordType c_y; CoordType new_x; // relative to center nodes' x coordinates CoordType new_y; // relative to center nodes' x coordinates double angle; // perform rotation for current node // dump before force process fo.open("out/"+string(outfilePath)+"_start.coord", fstream::out); for (int i=0; i<coord.size(); ++i) { fo << coord.at(i).at(0) << " " << coord.at(i).at(1) << endl; } fo.close(); // center coord fo.open("out/"+string(outfilePath)+"_start.center", fstream::out); for (int i=0; i<center_coord.size(); ++i) { fo << center_coord.at(i).at(0) << " " << center_coord.at(i).at(1) << endl; } fo.close(); // angle fo.open("out/"+string(outfilePath)+"_start.angle", fstream::out); for (int i=0; i<rotate_angles.size(); ++i) { fo << rotate_angles.at(i) << endl; } fo.close(); for (int t=0; t<iteration; t++) { pre_energy = curr_energy; curr_energy = 0; // step 1: repulsive force placement for (int i=0; i<cg.get_num_vtxs(); ++i) { node_disp.at(i) = make_pair(0, 0); for (int j=0; j<cg.get_num_vtxs(); ++j) { if (i != j) { pos_diff = make_pair(center_coord.at(i).at(0)-center_coord.at(j).at(0), center_coord.at(i).at(1)-center_coord.at(j).at(1)); rep_force = repulsive_force(pos_diff, radii.at(i), radii.at(j)); disp_x = node_disp.at(i).first + pos_diff.first/pos_diff_dist(pos_diff)*rep_force; disp_y = node_disp.at(i).second + pos_diff.second/pos_diff_dist(pos_diff)*rep_force; node_disp.at(i) = make_pair(disp_x+node_disp.at(i).first, disp_y+node_disp.at(i).second); if (t==0) { cout << "pos diff of cv_" << i << " = " << pos_diff.first << ", " << pos_diff.second << endl; cout << "repulsive_force of cv_" << i << " = " << rep_force << endl; cout << "disp = " << disp_x << ", " << disp_y << endl; cout << "node disp = " << node_disp.at(i).first << ", " << node_disp.at(i).second << endl; } } } } // step 2: attractive force placement for (int e=0; e<c_edges.size(); ++e) { e_u = c_edges.at(e).first; e_v = c_edges.at(e).second; // \delta <- e.u.pos - e.v.pos pos_diff = make_pair(center_coord.at(e_u).at(0)-center_coord.at(e_v).at(0), center_coord.at(e_u).at(1)-center_coord.at(e_v).at(1)); att_force = attractive_force(pos_diff, radii.at(e_u), radii.at(e_v)); // e.u.disp <- e.u.disp - unit-direction * att_force(abs(\delta)) disp_u_x = node_disp.at(e_u).first - pos_diff.first/pos_diff_dist(pos_diff)*att_force; disp_u_y = node_disp.at(e_u).second - pos_diff.second/pos_diff_dist(pos_diff)*att_force; node_disp.at(e_u) = make_pair(disp_u_x+node_disp.at(e_u).first, disp_u_y+node_disp.at(e_u).second); // e.v.disp <- e.v.disp - unit-direction * att_force(abs(\delta)) disp_v_x = node_disp.at(e_v).first + pos_diff.first/pos_diff_dist(pos_diff)*att_force; disp_v_y = node_disp.at(e_v).second + pos_diff.second/pos_diff_dist(pos_diff)*att_force; node_disp.at(e_v) = make_pair(disp_v_x+node_disp.at(e_v).first, disp_v_y+node_disp.at(e_v).second); if (t==0) { cout << "pos diff of cv_" << e << " = " << pos_diff.first << ", " << pos_diff.second << endl; cout << "attractive_force of cv_" << e << " = " << att_force << endl; cout << "disp = " << disp_v_x << ", " << disp_v_y << endl; } } // step 3: torque equilibrium fill(rotate_angles.begin(), rotate_angles.end(), 0); for (int i=0; i<cg.get_num_vtxs(); ++i) { cluster_nodes.resize(0); for (int c=0; c<clusters.size(); ++c) if (clusters.at(c) == i) cluster_nodes.push_back(c); calculate_rotate_angle(g, i, cluster_nodes, clusters, coord, center_coord, radii, rotate_angles); } // step 4: shift and rotate the cluster nodes and corresponding nodes for (int i=0; i<cg.get_num_vtxs(); ++i) { cluster_nodes.resize(0); for (int c=0; c<clusters.size(); ++c) if (clusters.at(c) == i) cluster_nodes.push_back(c); disp_val = sqrt(pow(node_disp.at(i).first, 2) + pow(node_disp.at(i).second, 2)); c_x = center_coord.at(i).at(0); c_y = center_coord.at(i).at(1); c_x += step * node_disp.at(i).first/disp_val; c_y += step * node_disp.at(i).second/disp_val; for (int j=0; j<cluster_nodes.size(); ++j) { angle = rotate_angles.at(i); // shift nodes coord.at(cluster_nodes.at(j)).at(0) -= center_coord.at(i).at(0); coord.at(cluster_nodes.at(j)).at(1) -= center_coord.at(i).at(1); // rotate nodes new_x = coord.at(cluster_nodes.at(j)).at(0); new_y = coord.at(cluster_nodes.at(j)).at(1); coord.at(cluster_nodes.at(j)).at(0) = new_x*cos(angle) + new_y*sin(angle); coord.at(cluster_nodes.at(j)).at(1) = -new_x*sin(angle) + new_y*cos(angle); // match to new center coord.at(cluster_nodes.at(j)).at(0) += c_x; coord.at(cluster_nodes.at(j)).at(1) += c_y; } center_coord.at(i).at(0) = c_x; center_coord.at(i).at(1) = c_y; } // update step calculate_energy(cluster_dist_mat, center_coord, curr_energy); update_step(step, pre_energy, curr_energy); cout << "curr_energy=" << curr_energy << endl; cout << "step=" << step << endl; // check convergence // dump information of each iteration if (t < 5) { // coordinates fo.open("out/"+string(outfilePath)+"_"+to_string(t)+".coord", fstream::out); for (int i=0; i<coord.size(); ++i) { fo << coord.at(i).at(0) << " " << coord.at(i).at(1) << endl; } fo.close(); // center coord fo.open("out/"+string(outfilePath)+"_"+to_string(t)+".center", fstream::out); for (int i=0; i<center_coord.size(); ++i) { fo << center_coord.at(i).at(0) << " " << center_coord.at(i).at(0) << endl; } fo.close(); // angle fo.open("out/"+string(outfilePath)+"_"+to_string(t)+".angle", fstream::out); for (int i=0; i<rotate_angles.size(); ++i) { fo << rotate_angles.at(i) << endl; } fo.close(); } } }