void test_transformations() { test_begin("flattening"); std::cout << "Reading the multilayer network..."; MLNetworkSharedPtr mnet = read_multilayer("test/io2.mpx","mlnet 2",','); ActorSharedPtr u1 = mnet->get_actor("U1"); ActorSharedPtr u2 = mnet->get_actor("U2"); ActorSharedPtr u3 = mnet->get_actor("U3"); std::unordered_set<LayerSharedPtr> layers; layers.insert(mnet->get_layer("l1")); layers.insert(mnet->get_layer("l2")); std::cout << "done!" << std::endl; std::cout << "Testing weighted flattening..."; LayerSharedPtr new_layer = flatten_weighted(mnet,"flat_weighted",layers,false,false); if (!mnet->is_directed(new_layer,new_layer)) throw FailedUnitTestException("Layer should be directed"); if (mnet->get_nodes(new_layer).size() != 6) throw FailedUnitTestException("Wrong number of nodes"); if (mnet->get_edges(new_layer,new_layer).size() != 10) throw FailedUnitTestException("Wrong number of edges"); NodeSharedPtr n1 = mnet->get_node(u1,new_layer); NodeSharedPtr n2 = mnet->get_node(u2,new_layer); NodeSharedPtr n3 = mnet->get_node(u3,new_layer); if (mnet->get_weight(n1,n2) != 1) throw FailedUnitTestException("Wrong weight, expected 1"); if (mnet->get_weight(n1,n3) != 2) throw FailedUnitTestException("Wrong weight, expected 2"); std::cout << "done!" << std::endl; std::cout << "Testing or flattening..."; new_layer = flatten_unweighted(mnet,"flat_or",layers,false,false); if (!mnet->is_directed(new_layer,new_layer)) throw FailedUnitTestException("Layer should be directed"); if (mnet->get_nodes(new_layer).size() != 6) throw FailedUnitTestException("Wrong number of nodes"); if (mnet->get_edges(new_layer,new_layer).size() != 10) throw FailedUnitTestException("Wrong number of edges"); std::cout << "done!" << std::endl; test_end("flattening"); test_begin("projection"); /* std::cout << "Reading the multilayer network..."; MLNetworkSharedPtr mnet_p = read_multilayer("test/io4.mln","interdependent",','); LayerSharedPtr A = mnet_p->get_layer("A"); LayerSharedPtr P = mnet_p->get_layer("P"); std::cout << "done!" << mnet_p->to_string() << std::endl; std::cout << "Testing clique projection..."; LayerSharedPtr projected_layer = project_unweighted(mnet_p,"flat_weighted",A,P); if (mnet_p->is_directed(projected_layer,projected_layer)) throw FailedUnitTestException("Layer should be undirected"); if (mnet_p->get_nodes(projected_layer).size() != 5) throw FailedUnitTestException("Wrong number of nodes"); if (mnet_p->get_edges(projected_layer,projected_layer).size() != 5) throw FailedUnitTestException("Wrong number of edges"); std::cout << "done!" << std::endl; */ test_end("projection"); }
property_matrix<ActorSharedPtr,LayerSharedPtr,bool> actor_existence_property_matrix(const MLNetworkSharedPtr& mnet) { property_matrix<ActorSharedPtr,LayerSharedPtr,bool> P(mnet->get_actors()->size(),mnet->get_layers()->size(),false); for (LayerSharedPtr layer: *mnet->get_layers()) for (NodeSharedPtr node: *mnet->get_nodes(layer)) { P.set(node->actor,layer,true); } return P; }
double relevance(const MLNetworkSharedPtr& mnet, const ActorSharedPtr& actor, const LayerSharedPtr& layer, edge_mode mode) { set<actor_id> neighbors_on_selected_layers; set<actor_id> all_neighbors; for (NodeSharedPtr node: *mnet->get_nodes(actor)) { for (NodeSharedPtr neighbor: *mnet->neighbors(node, mode)) { all_neighbors.insert(neighbor->actor->id); if (layer == neighbor->layer) neighbors_on_selected_layers.insert(neighbor->actor->id); } } if (all_neighbors.size()==0) return 0; // by definition else return (double)neighbors_on_selected_layers.size()/all_neighbors.size(); }
double xrelevance(const MLNetworkSharedPtr& mnet, const ActorSharedPtr& actor, const std::unordered_set<LayerSharedPtr>& layers, edge_mode mode) { set<actor_id> neighbors_on_selected_layers; set<actor_id> neighbors_on_other_layers; set<actor_id> all_neighbors; for (NodeSharedPtr node: *mnet->get_nodes(actor)) { for (NodeSharedPtr neighbor: *mnet->neighbors(node, mode)) { all_neighbors.insert(neighbor->actor->id); if (layers.count(neighbor->layer)>0) neighbors_on_selected_layers.insert(neighbor->actor->id); else neighbors_on_other_layers.insert(neighbor->actor->id); } } if (all_neighbors.size()==0) return 0; // by definition else { for (actor_id actor: neighbors_on_other_layers) neighbors_on_selected_layers.erase(actor); return (double)neighbors_on_selected_layers.size()/all_neighbors.size(); } }
hash_map<NodeSharedPtr,xyz_coordinates> circular(MLNetworkSharedPtr& mnet, double radius) { hash_map<NodeSharedPtr,xyz_coordinates> pos; double pi = 3.14159265358979323846; if (mnet->get_actors()->size()==0) return pos; double angle_offset = 360.0/mnet->get_actors()->size(); int i=0; for (ActorSharedPtr a: *mnet->get_actors()) { double degree = i*angle_offset; double radians = degree*pi/180; double x = std::cos(radians)*radius; double y = std::sin(radians)*radius; for (NodeSharedPtr n: *mnet->get_nodes(a)) { pos[n].x = x; pos[n].y = y; pos[n].z = mnet->get_layers()->get_index(n->layer); } i++; } return pos; }
// only works for multiplex networks (no inter-layer edges) property_matrix<triad,LayerSharedPtr,bool> triangle_existence_property_matrix(const MLNetworkSharedPtr& mnet) { long n = mnet->get_actors()->size(); property_matrix<triad,LayerSharedPtr,bool> P(n*(n-1)*(n-2)/6,mnet->get_layers()->size(),false); for (LayerSharedPtr layer: *mnet->get_layers()) { hash_set<NodeSharedPtr> processed1; for (NodeSharedPtr n1: *mnet->get_nodes(layer)) { processed1.insert(n1); hash_set<NodeSharedPtr> processed2; for (NodeSharedPtr n2: *mnet->neighbors(n1,INOUT)) { if (processed1.count(n2)>0) continue; processed2.insert(n2); for (NodeSharedPtr n3: *mnet->neighbors(n2,INOUT)) { if (processed1.count(n3)>0) continue; if (processed2.count(n3)>0) continue; if (mnet->get_edge(n3,n1)) { triad t(n1->actor,n2->actor,n3->actor); P.set(t,layer,true); } } } } } return P; }
hashtable<NodeSharedPtr,coordinates> multiforce(MLNetworkSharedPtr mnet, double width, double length, int iterations) { hashtable<NodeSharedPtr,coordinates> pos; hashtable<NodeSharedPtr,coordinates> disp; double t = std::sqrt(width*width+length*length); double area = width*length; double k = std::sqrt(area/mnet->get_actors().size()); for (ActorSharedPtr a: mnet->get_actors()) { double y = drand()*length-length/2; double x = drand()*width-width/2; for (NodeSharedPtr n: mnet->get_nodes(a)) { pos[n].y = x; pos[n].x = y; pos[n].z = mnet->get_layers().get_index(n->layer->id); } } for (int i=0; i<iterations; i++) { // calculate repulsive forces for (LayerSharedPtr l: mnet->get_layers()) { for (NodeSharedPtr v: mnet->get_nodes(l)) { disp[v].x = 0; disp[v].y = 0; for (NodeSharedPtr u: mnet->get_nodes(l)) { if (u == v) continue; coordinates Delta; Delta.x = pos[v].x - pos[u].x; Delta.y = pos[v].y - pos[u].y; double DeltaNorm = std::sqrt(Delta.x*Delta.x+Delta.y*Delta.y); disp[v].x = disp[v].x + Delta.x/DeltaNorm*fr(DeltaNorm,k); disp[v].y = disp[v].y + Delta.y/DeltaNorm*fr(DeltaNorm,k); } } } // calculate attractive forces inside each layer for ((u, v) ∈ E) do for (LayerSharedPtr l: mnet->get_layers()) { for (EdgeSharedPtr e: mnet->get_edges(l,l)) { NodeSharedPtr v = e->v1; NodeSharedPtr u = e->v2; coordinates Delta; Delta.x = pos[v].x - pos[u].x; Delta.y = pos[v].y - pos[u].y; double DeltaNorm = std::sqrt(Delta.x*Delta.x+Delta.y*Delta.y); disp[v].x = disp[v].x - Delta.x/DeltaNorm*fain(DeltaNorm,k); disp[v].y = disp[v].y - Delta.y/DeltaNorm*fain(DeltaNorm,k); disp[u].x = disp[u].x + Delta.x/DeltaNorm*fain(DeltaNorm,k); disp[u].y = disp[u].y + Delta.y/DeltaNorm*fain(DeltaNorm,k); } } // calculate attractive forces across layers for (ActorSharedPtr a: mnet->get_actors()) { for (NodeSharedPtr v: mnet->get_nodes(a)) { for (NodeSharedPtr u: mnet->get_nodes(a)) { if (v == u) continue; coordinates Delta; Delta.x = pos[v].x - pos[u].x; Delta.y = pos[v].y - pos[u].y; double DeltaNorm = std::sqrt(Delta.x*Delta.x+Delta.y*Delta.y); disp[v].x = disp[v].x - Delta.x/DeltaNorm*fainter(DeltaNorm,k); disp[v].y = disp[v].y - Delta.y/DeltaNorm*fainter(DeltaNorm,k); disp[u].x = disp[u].x + Delta.x/DeltaNorm*fainter(DeltaNorm,k); disp[u].y = disp[u].y + Delta.y/DeltaNorm*fainter(DeltaNorm,k); } } } // assign new positions for (NodeSharedPtr v: mnet->get_nodes()) { double dispNorm = std::sqrt(disp[v].x*disp[v].x+disp[v].y*disp[v].y); pos[v].x = pos[v].x + (disp[v].x/dispNorm);//*std::min(dispNorm,t); pos[v].y = pos[v].y + (disp[v].y/dispNorm);//*std::min(dispNorm,t); //pos[v].x = std::min(width/2, std::max(-width/2, pos[v].x)); //pos[v].y = std::min(length/2, std::max(-length/2, pos[v].y)); } // reduce the temperature t -= (t-1)/(iterations+1); } // DEBUG PRINT double min_x = 100000000; double min_y = 100000000; double max_x = -100000000; double max_y = -100000000; for (NodeSharedPtr v: mnet->get_nodes()) { if (pos[v].x < min_x) min_x = pos[v].x; if (pos[v].y < min_y) min_y = pos[v].y; if (pos[v].x > max_x) max_x = pos[v].x; if (pos[v].y > max_y) max_y = pos[v].y; } std::cout << "plot(c(),xlim=c(" << min_x << "," << max_x << "),ylim=c(" << min_y << "," << max_y << "))" << std::endl; //std::cout << "legend(4,4,0:" << (iterations-1) << ",fill=1:" << (iterations) << ")" << std::endl; for (NodeSharedPtr n: mnet->get_nodes()) { std::cout << "points(" << pos[n].x << "," << pos[n].y << ")" << std::endl; } for (EdgeSharedPtr e: mnet->get_edges()) { std::cout << "lines(c(" << pos[e->v1].x << "," << pos[e->v2].x << "),c(" << pos[e->v1].y << "," << pos[e->v2].y << "))" << std::endl; } // return pos; }