Esempio n. 1
0
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;
}
Esempio n. 2
0
std::string tau_transition::fire(MLNetworkSharedPtr& mnet, const NodeSharedPtr& node, long time) {
    std::string current_status = mnet->actor_features()->getString(node->actor->id,_S_current);
    if (current_status==status) {
        if (time - mnet->actor_features()->getNumeric(node->actor->id,_S_time)>=tau) {
            return new_status;
        }
    }
    return "";
}
Esempio n. 3
0
std::string beta_transition::fire(MLNetworkSharedPtr& mnet, const NodeSharedPtr& node, long time) {
    std::string current_status = mnet->actor_features()->getString(node->actor->id,_S_current);
    if (current_status==status) {
        for (NodeSharedPtr n: mnet->neighbors(node,IN)) {
            if (mnet->actor_features()->getString(n->actor->id,_S_current)==neighbor_status && test(beta)) {
                return new_status;
            }
        }
    }
    return "";
}
Esempio n. 4
0
 property_matrix<ActorSharedPtr,LayerSharedPtr,double> actor_cc_property_matrix(const MLNetworkSharedPtr& mnet) {
     property_matrix<ActorSharedPtr,LayerSharedPtr,double> P(mnet->get_actors()->size(),mnet->get_layers()->size(),0);
     for (ActorSharedPtr actor: *mnet->get_actors()) {
         for (LayerSharedPtr layer: *mnet->get_layers()) {
             NodeSharedPtr node = mnet->get_node(actor,layer);
             if (!node) P.set_na(actor,layer);
             else P.set(actor,layer,cc(mnet,node));
         }
     }
     return P;
 }
Esempio n. 5
0
// TODO document: does not consider self edges
property_matrix<dyad,LayerSharedPtr,bool> edge_existence_property_matrix(const MLNetworkSharedPtr& mnet) {
	long n = mnet->get_actors()->size();
	property_matrix<dyad,LayerSharedPtr,bool> P(n*(n-1)/2,mnet->get_layers()->size(),false);
	for (LayerSharedPtr layer: *mnet->get_layers()) {
		for (EdgeSharedPtr e: *mnet->get_edges(layer,layer)) {
			dyad d(e->v1->actor,e->v2->actor);
			P.set(d,layer,true);
		}
	}
	return P;
}
void test_community_single_layer() {

	test_begin("Label propagation, single layer");

	MLNetworkSharedPtr mnet = read_multilayer("toy.mpx","cpm",',');
    CommunityStructureSharedPtr c = label_propagation_single(mnet, mnet->get_layer("Work"));

    std::cout << c->to_string() << std::endl;

	test_end("Label propagation, single layer");

}
Esempio n. 7
0
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();
}
Esempio n. 8
0
double cc(const MLNetworkSharedPtr& mnet, const NodeSharedPtr& node) {
	int num_edges = 0;
    NodeListSharedPtr neigh = mnet->neighbors(node,INOUT);
    int num_neigh = neigh->size();
    if (num_neigh<=1) return 0.0;
    
	for (NodeSharedPtr n1: *neigh) {
		for (NodeSharedPtr n2: *neigh) {
            if (n1>=n2) continue;
            if (mnet->get_edge(n1,n2))
				num_edges++;
		}
	}
	return num_edges*2.0/(num_neigh*(num_neigh-1));
}
Esempio n. 9
0
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();
	}
}
Esempio n. 10
0
void test_double_layer() {
	{
	log(1);
	// create multiplex network
	MLNetworkSharedPtr mnet = read_multilayer("test/data/ACModel_BA_copy.csv","mlnet 2",',');

	// BEGIN Getting Layers
	layer_list layers_l = mnet->get_layers();
	std::unordered_set<LayerSharedPtr> layers;
	for(LayerSharedPtr layer : layers_l){
		layers.insert(layer);
	}
	// END Getting Layers
/*
	std::cout<<"[.] NODE Jaccard :"<<std::endl;
	for(LayerSharedPtr layer1 : layers){

		for(LayerSharedPtr layer2 : layers){
			double jaccard_sim = jaccard_node_similarity(mnet, layer1, layer2);
			std::cout<<jaccard_sim<<" - ";

		}
		std::cout<<std::endl;
	}

	std::cout<<"[.] EDGE Jaccard :"<<std::endl;
	for(LayerSharedPtr layer1 : layers){

		for(LayerSharedPtr layer2 : layers){
			double jaccard_edge_sim = jaccard_similarity(mnet, layer1, layer2);
			std::cout<<jaccard_edge_sim<<" - ";

		}
		std::cout<<std::endl;
	}*/
		benchmark_adjust_error(mnet, "ACModel_BA_copy", "csv");
		//benchmark_dissortative_swap(mnet, "ACModel_BA_copy", "csv");
	}
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
property_matrix<ActorSharedPtr,LayerSharedPtr,double> actor_degree_property_matrix(const MLNetworkSharedPtr& mnet, edge_mode mode) {
	property_matrix<ActorSharedPtr,LayerSharedPtr,double> P(mnet->get_actors()->size(),mnet->get_layers()->size(),0);
	for (ActorSharedPtr actor: *mnet->get_actors()) {
		for (LayerSharedPtr layer: *mnet->get_layers()) {
			NodeSharedPtr node = mnet->get_node(actor,layer);
			if (!node) P.set_na(actor,layer);
			else P.set(actor,layer,mnet->neighbors(node,mode)->size());
		}
	}
	return P;
}
Esempio n. 13
0
// 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;
}
Esempio n. 14
0
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");
}
Esempio n. 15
0
void test_evolution() {
	{
	test_begin("[Evolution Test R1] N1: larger independent, N2: smaller independent and with basic random graph evolution model");
	// create multiplex network
	MLNetworkSharedPtr mnet = MLNetwork::create("synt1");
	LayerSharedPtr layer1 = mnet->add_layer("L1",true);
	LayerSharedPtr layer2 = mnet->add_layer("L2",true);
	// set evolution parameters
	long num_of_steps = 100;
	long num_of_actors = 1000;
	std::vector<double> pr_no_event = {0.0,0.3};
	std::vector<double> pr_internal_event = {1.0,1.0};
	matrix<double> dependency = {{0, 1}, {1, 0}};
	BAEvolutionModel ba(3,2);
	UniformEvolutionModel ra(70);
	std::vector<EvolutionModel*> evolution_model = {&ba, &ra};
	evolve(mnet,num_of_steps,num_of_actors,pr_no_event,pr_internal_event,dependency,evolution_model);
	//log(mnet->to_string());
	//log("Edge Jaccard similarity: " + to_string(jaccard_similarity(mnet,layer1,layer2)));
	//log("Assortativity: " + to_string(assortativity(mnet,layer1,layer2,OUT)));
	}

	{
	test_begin("[Evolution Test R2] N1: larger independent, N2: smaller dependent on N1, both with basic random graph evolution model");
	MLNetworkSharedPtr mnet = MLNetwork::create("synt1");
	LayerSharedPtr layer1 = mnet->add_layer("L1",true);
	LayerSharedPtr layer2 = mnet->add_layer("L2",true);
	// set evolution parameters
	long num_of_steps = 100;
	long num_of_actors = 1000;
	std::vector<double> pr_no_event = {0.0,0.3};
	std::vector<double> pr_internal_event = {1.0,0.5};
	matrix<double> dependency = {{0, 1}, {1, 0}};
	UniformEvolutionModel ra(30);
	std::vector<EvolutionModel*> evolution_model = {&ra, &ra};
	evolve(mnet,num_of_steps,num_of_actors,pr_no_event,pr_internal_event,dependency,evolution_model);
	//log(mnet->to_string());
	//log("Edge Jaccard similarity: " + to_string(jaccard_similarity(mnet,layer1,layer2)));
	//log("Assortativity: " + to_string(assortativity(mnet,layer1,layer2,OUT)));
	}
	/*
	{
	log("[Evolution Test 1] N1: larger independent, N2: smaller independent");
	// create multiplex network
	MultiplexNetwork mnet1;
	for (int i=0; i<1000; i++) mnet1.addGlobalName("U"+std::to_string(i));
	Network n1(true,false,false), n2(true,false,false);
	network_id n1_1 = mnet1.addNetwork("N1",n1);
	network_id n1_2 = mnet1.addNetwork("N2",n2);
	// set evolution parameters
	long num_of_steps = 100;
	std::vector<double> pr_no_event = {0.0,0.3};
	std::vector<double> pr_internal_event = {1.0,1.0};
	vector<vector<double> > dependency = {{0, 1}, {1, 0}};
	BAEvolutionModel ba(3,2);
	std::vector<EvolutionModel*> evolution_model = {&ba, &ba};
	evolve(mnet1,num_of_steps,pr_no_event,pr_internal_event,dependency,evolution_model);
	log("Size 1: " + std::to_string(mnet1.getNetwork(n1_1).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_1).getNumEdges()) + " e");
	log("Size 2: " + std::to_string(mnet1.getNetwork(n1_2).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_2).getNumEdges()) + " e");
	int common_vertexes = 0;
	for (vertex_id v: mnet1.getNetwork(n1_1).getVertexes()) {
		global_identity id = mnet1.getGlobalIdentity(v, n1_1);
		if (mnet1.containsVertex(id,n1_2))
			common_vertexes++;
	}
	log("Common vertexes: " + std::to_string(common_vertexes));
	log("Edge Jaccard similarity: " + std::to_string(network_jaccard_similarity(mnet1,n1_1,n1_2)));
	}
	{
	log("[Evolution Test 2] N1: larger independent, N2: smaller dependent on N1");
	// create multiplex network
	MultiplexNetwork mnet1;
	for (int i=0; i<1000; i++) mnet1.addGlobalName("U"+std::to_string(i));
	Network n1(true,false,false), n2(true,false,false);
	network_id n1_1 = mnet1.addNetwork("N1",n1);
	network_id n1_2 = mnet1.addNetwork("N2",n2);
	// set evolution parameters
	long num_of_steps = 100;
	std::vector<double> pr_no_event = {0.0,0.3};
	std::vector<double> pr_internal_event = {1.0,0.7};
	vector<vector<double> > dependency = {{0, 1}, {1, 0}};
	BAEvolutionModel ba(3,2);
	std::vector<EvolutionModel*> evolution_model = {&ba, &ba};
	evolve(mnet1,num_of_steps,pr_no_event,pr_internal_event,dependency,evolution_model);
	log("Size 1: " + std::to_string(mnet1.getNetwork(n1_1).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_1).getNumEdges()) + " e");
	log("Size 2: " + std::to_string(mnet1.getNetwork(n1_2).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_2).getNumEdges()) + " e");
	int common_vertexes = 0;
	for (vertex_id v: mnet1.getNetwork(n1_1).getVertexes()) {
		global_identity id = mnet1.getGlobalIdentity(v, n1_1);
		if (mnet1.containsVertex(id,n1_2))
			common_vertexes++;
	}
	log("Common vertexes: " + std::to_string(common_vertexes));
	log("Edge Jaccard similarity: " + std::to_string(network_jaccard_similarity(mnet1,n1_1,n1_2)));
	}
	{
	log("[Evolution Test 3] N1: larger independent, N2: smaller almost completely dependent on N1");
	// create multiplex network
	MultiplexNetwork mnet1;
	for (int i=0; i<1000; i++) mnet1.addGlobalName("U"+std::to_string(i));
	Network n1(true,false,false), n2(true,false,false);
	network_id n1_1 = mnet1.addNetwork("N1",n1);
	network_id n1_2 = mnet1.addNetwork("N2",n2);
	// set evolution parameters
	long num_of_steps = 100;
	std::vector<double> pr_no_event = {0.0,0.3};
	std::vector<double> pr_internal_event = {1.0,0.1};
	vector<vector<double> > dependency = {{0, 1}, {1, 0}};
	BAEvolutionModel ba(3,2);
	std::vector<EvolutionModel*> evolution_model = {&ba, &ba};
	evolve(mnet1,num_of_steps,pr_no_event,pr_internal_event,dependency,evolution_model);
	log("Size 1: " + std::to_string(mnet1.getNetwork(n1_1).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_1).getNumEdges()) + " e");
	log("Size 2: " + std::to_string(mnet1.getNetwork(n1_2).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_2).getNumEdges()) + " e");
	int common_vertexes = 0;
	for (vertex_id v: mnet1.getNetwork(n1_1).getVertexes()) {
		global_identity id = mnet1.getGlobalIdentity(v, n1_1);
		if (mnet1.containsVertex(id,n1_2))
			common_vertexes++;
	}
	log("Common vertexes: " + std::to_string(common_vertexes));
	log("Edge Jaccard similarity: " + std::to_string(network_jaccard_similarity(mnet1,n1_1,n1_2)));
	}
	{
	log("[Evolution Test 4] N1: larger independent, N2: smaller dependent more on N1 than on N3, N3: smaller almost independent");
	// create multiplex network
	MultiplexNetwork mnet1;
	for (int i=0; i<1000; i++) mnet1.addGlobalName("U"+std::to_string(i));
	Network n1(true,false,false), n2(true,false,false), n3(true,false,false);
	network_id n1_1 = mnet1.addNetwork("N1",n1);
	network_id n1_2 = mnet1.addNetwork("N2",n2);
	network_id n1_3 = mnet1.addNetwork("N3",n3);
	// set evolution parameters
	long num_of_steps = 100;
	std::vector<double> pr_no_event = {0.0,0.2,0.2};
	std::vector<double> pr_internal_event = {1.0,0.3,0.9};
	vector<vector<double> > dependency = {{0, 1, 1}, {1, 0, .3}, {1, 1, 0}};
	BAEvolutionModel ba(3,2);
	std::vector<EvolutionModel*> evolution_model = {&ba, &ba, &ba};
	evolve(mnet1,num_of_steps,pr_no_event,pr_internal_event,dependency,evolution_model);
	log("Size 1: " + std::to_string(mnet1.getNetwork(n1_1).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_1).getNumEdges()) + " e");
	log("Size 2: " + std::to_string(mnet1.getNetwork(n1_2).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_2).getNumEdges()) + " e");
	log("Size 3: " + std::to_string(mnet1.getNetwork(n1_3).getNumVertexes()) + " v, " + std::to_string(mnet1.getNetwork(n1_3).getNumEdges()) + " e");
	log("Edge Jaccard similarity (n1-n2): " + std::to_string(network_jaccard_similarity(mnet1,n1_1,n1_2)));
	log("Edge Jaccard similarity (n1-n3): " + std::to_string(network_jaccard_similarity(mnet1,n1_1,n1_3)));
	log("Edge Jaccard similarity (n2-n3): " + std::to_string(network_jaccard_similarity(mnet1,n1_3,n1_2)));
	}
	*/
	{
	test_begin("[Evolution Test 5] LARGER NETWORKS, COMMON ACTORS - N1: larger independent, N2: smaller dependent more on N1 than on N3, N3: smaller almost independent");
	// create multiplex network
	MLNetworkSharedPtr mnet = MLNetwork::create("synt1");
		LayerSharedPtr layer1 = mnet->add_layer("L1",true);
		LayerSharedPtr layer2 = mnet->add_layer("L2",true);
		LayerSharedPtr layer3 = mnet->add_layer("L3",true);
		// set evolution parameters
		long num_of_steps = 1000;
		long num_of_actors = 10000;
		std::vector<double> pr_no_event = {0.0,0.3,0.3};
		std::vector<double> pr_internal_event = {1,0,0.9};
		matrix<double> dependency = {{0, 0, 0}, {1, 0, 0}, {1, 0, 0}};
		BAEvolutionModel ba(3,2);
		std::vector<EvolutionModel*> evolution_model = {&ba, &ba, &ba};
		evolve(mnet,num_of_steps,num_of_actors,pr_no_event,pr_internal_event,dependency,evolution_model);
		//log(mnet->to_string());
		//log("Edge Jaccard similarity 1-2: " + to_string(jaccard_similarity(mnet,layer1,layer2)));
		//log("Edge Jaccard similarity 1-3: " + to_string(jaccard_similarity(mnet,layer1,layer3)));
		//log("Edge Jaccard similarity 2-3: " + to_string(jaccard_similarity(mnet,layer2,layer3)));
		//log("Assortativity 1-2: " + to_string(assortativity(mnet,layer1,layer2,OUT)));
		//log("Assortativity 1-3: " + to_string(assortativity(mnet,layer1,layer3,OUT)));
		//log("Assortativity 2-3: " + to_string(assortativity(mnet,layer2,layer3,OUT)));
	}
}
Esempio n. 16
0
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;
}