1
0
mirror of https://github.com/gsi-upm/soil synced 2024-11-14 07:22:29 +00:00
soil/soil.py

404 lines
15 KiB
Python
Raw Normal View History

2015-12-04 10:41:42 +00:00
from nxsim import NetworkSimulation
from nxsim import BaseNetworkAgent
from nxsim import BaseLoggingAgent
from random import randint
from matplotlib import pyplot as plt
import random
import numpy as np
import networkx as nx
import settings
2015-12-18 12:03:58 +00:00
import math
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
settings.init() # Loads all the data from settings
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
####################
# Network creation #
####################
2015-12-04 10:41:42 +00:00
if settings.network_type == 0:
G = nx.complete_graph(settings.number_of_nodes)
if settings.network_type == 1:
G = nx.barabasi_albert_graph(settings.number_of_nodes,3)
if settings.network_type == 2:
G = nx.margulis_gabber_galil_graph(settings.number_of_nodes, None)
2015-12-04 11:32:24 +00:00
# More types of networks can be added here
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
##############################
# Variables initializitation #
##############################
myList=[] # List just for debugging
networkStatus=[] # This list will contain the status of every node of the network
2015-12-17 11:56:39 +00:00
emotionStatus=[]
2015-12-04 10:41:42 +00:00
for x in range(0, settings.number_of_nodes):
networkStatus.append({'id':x})
2015-12-17 11:56:39 +00:00
emotionStatus.append({'id':x})
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
# Initialize agent states. Let's assume everyone is normal.
init_states = [{'id': 0, } for _ in range(settings.number_of_nodes)] # add keys as as necessary, but "id" must always refer to that state category
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
# Seed a zombie, just for zombie model
#init_states[5] = {'id': 1}
#init_states[3] = {'id': 1}
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
####################
# Available models #
####################
2015-12-04 10:41:42 +00:00
2015-12-10 18:18:12 +00:00
class BigMarketModel(BaseNetworkAgent):
def __init__(self, environment=None, agent_id=0, state=()):
super().__init__(environment=environment, agent_id=agent_id, state=state)
self.time_awareness = 0
2015-12-17 11:56:39 +00:00
self.type = ""
2015-12-10 18:18:12 +00:00
if self.id == 0: #Empresa 1
self.state['id']=0
2015-12-17 11:56:39 +00:00
self.type="Enterprise"
self.tweet_probability = settings.tweet_probability_enterprises[0]
2015-12-10 18:18:12 +00:00
elif self.id == 1: #Empresa 2
self.state['id']=1
2015-12-17 11:56:39 +00:00
self.type="Enterprise"
self.tweet_probability = settings.tweet_probability_enterprises[1]
2015-12-10 18:18:12 +00:00
else: #Usuarios normales
self.state['id']=2
2015-12-17 11:56:39 +00:00
self.type="User"
2015-12-14 11:57:21 +00:00
self.tweet_probability = settings.tweet_probability_users
self.tweet_relevant_probability = settings.tweet_relevant_probability
self.tweet_probability_about = settings.tweet_probability_about #Lista
self.sentiment_about = settings.sentiment_about #Lista
2015-12-10 18:18:12 +00:00
2015-12-17 11:56:39 +00:00
networkStatus[self.id][self.env.now]=self.state['id']
emotionStatus[self.id][self.env.now]=0
2015-12-10 18:18:12 +00:00
def run(self):
while True:
2015-12-18 12:03:58 +00:00
if(self.id < 2): # Empresa
2015-12-17 11:56:39 +00:00
self.enterpriseBehaviour()
2015-12-18 12:03:58 +00:00
else: # Usuario
2015-12-17 11:56:39 +00:00
self.userBehaviour()
yield self.env.timeout(settings.timeout)
def enterpriseBehaviour(self):
if random.random()< self.tweet_probability: #Twittea
2015-12-18 12:03:58 +00:00
aware_neighbors = self.get_neighboring_agents(state_id=2) #Nodos vecinos usuarios
2015-12-17 11:56:39 +00:00
for x in aware_neighbors:
2015-12-18 12:03:58 +00:00
if random.uniform(0,10) < 5:
x.sentiment_about[self.id] += 0.01 #Aumenta para empresa
else:
x.sentiment_about[self.id] -= 0.01 #Reduce para empresa
# Establecemos limites
if x.sentiment_about[self.id] > 1:
x.sentiment_about[self.id] = 1
if x.sentiment_about[self.id] < -1:
x.sentiment_about[self.id] = -1
#Guardamos estado para visualizacion
emotionStatus[x.id][self.env.now]=x.sentiment_about[self.id]
2015-12-14 11:57:21 +00:00
2015-12-17 11:56:39 +00:00
def userBehaviour(self):
if random.random() < self.tweet_probability: #Twittea
2015-12-14 11:57:21 +00:00
if random.random() < self.tweet_relevant_probability: #Twittea algo relevante
2015-12-18 12:03:58 +00:00
2015-12-14 11:57:21 +00:00
#Probabilidad de tweet para cada empresa
for i in range(len(self.tweet_probability_about)):
2015-12-17 11:56:39 +00:00
random_num = random.random()
if random_num < self.tweet_probability_about[i]:
2015-12-14 11:57:21 +00:00
#Se ha cumplido la condicion, evaluo los sentimientos hacia esa empresa
if self.sentiment_about[i] < 0:
#NEGATIVO
2015-12-18 12:03:58 +00:00
self.userTweets("negative",i)
2015-12-14 11:57:21 +00:00
elif self.sentiment_about[i] == 0:
#NEUTRO
2015-12-18 12:03:58 +00:00
pass
2015-12-14 11:57:21 +00:00
else:
#POSITIVO
2015-12-18 12:03:58 +00:00
self.userTweets("positive",i)
def userTweets(self,sentiment,enterprise):
aware_neighbors = self.get_neighboring_agents(state_id=2) #Nodos vecinos usuarios
for x in aware_neighbors:
if sentiment == "positive":
x.sentiment_about[enterprise] +=0
elif sentiment == "negative":
x.sentiment_about[enterprise] -=0
else:
pass
2015-12-14 11:57:21 +00:00
2015-12-10 18:18:12 +00:00
2015-12-17 11:56:39 +00:00
################################################
2015-12-10 18:18:12 +00:00
2015-12-04 10:41:42 +00:00
class SentimentCorrelationModel(BaseNetworkAgent):
def __init__(self, environment=None, agent_id=0, state=()):
super().__init__(environment=environment, agent_id=agent_id, state=state)
self.outside_effects_prob = settings.outside_effects_prob
self.anger_prob = settings.anger_prob
self.joy_prob = settings.joy_prob
self.sadness_prob = settings.sadness_prob
self.disgust_prob = settings.disgust_prob
self.time_awareness=[]
2015-12-04 11:32:24 +00:00
for i in range(4): #En este modelo tenemos 4 sentimientos
2015-12-04 10:41:42 +00:00
self.time_awareness.append(0) #0-> Anger, 1-> joy, 2->sadness, 3 -> disgust
networkStatus[self.id][self.env.now]=0
def run(self):
while True:
2015-12-04 11:32:24 +00:00
2015-12-04 10:41:42 +00:00
angry_neighbors_1_time_step=[]
joyful_neighbors_1_time_step=[]
sad_neighbors_1_time_step=[]
disgusted_neighbors_1_time_step=[]
angry_neighbors = self.get_neighboring_agents(state_id=1)
for x in angry_neighbors:
if x.time_awareness[0] > (self.env.now-500):
angry_neighbors_1_time_step.append(x)
num_neighbors_angry = len(angry_neighbors_1_time_step)
joyful_neighbors = self.get_neighboring_agents(state_id=2)
for x in joyful_neighbors:
if x.time_awareness[1] > (self.env.now-500):
joyful_neighbors_1_time_step.append(x)
num_neighbors_joyful = len(joyful_neighbors_1_time_step)
sad_neighbors = self.get_neighboring_agents(state_id=3)
for x in sad_neighbors:
if x.time_awareness[2] > (self.env.now-500):
sad_neighbors_1_time_step.append(x)
num_neighbors_sad = len(sad_neighbors_1_time_step)
disgusted_neighbors = self.get_neighboring_agents(state_id=4)
for x in disgusted_neighbors:
if x.time_awareness[3] > (self.env.now-500):
disgusted_neighbors_1_time_step.append(x)
num_neighbors_disgusted = len(disgusted_neighbors_1_time_step)
anger_prob= settings.anger_prob+(len(angry_neighbors_1_time_step)*settings.anger_prob)
joy_prob= settings.joy_prob+(len(joyful_neighbors_1_time_step)*settings.joy_prob)
sadness_prob = settings.sadness_prob+(len(sad_neighbors_1_time_step)*settings.sadness_prob)
disgust_prob = settings.disgust_prob+(len(disgusted_neighbors_1_time_step)*settings.disgust_prob)
outside_effects_prob= settings.outside_effects_prob
num = random.random()
if(num<outside_effects_prob):
self.state['id'] = random.randint(1,4)
myList.append(self.id)
networkStatus[self.id][self.env.now]=self.state['id'] #Almaceno cuando se ha infectado para la red dinamica
self.time_awareness[self.state['id']-1] = self.env.now
yield self.env.timeout(settings.timeout)
if(num<anger_prob):
myList.append(self.id)
self.state['id'] = 1
networkStatus[self.id][self.env.now]=1
self.time_awareness[self.state['id']-1] = self.env.now
elif (num<joy_prob+anger_prob and num>anger_prob):
myList.append(self.id)
self.state['id'] = 2
networkStatus[self.id][self.env.now]=2
self.time_awareness[self.state['id']-1] = self.env.now
elif (num<sadness_prob+anger_prob+joy_prob and num>joy_prob+anger_prob):
myList.append(self.id)
self.state['id'] = 3
networkStatus[self.id][self.env.now]=3
self.time_awareness[self.state['id']-1] = self.env.now
elif (num<disgust_prob+sadness_prob+anger_prob+joy_prob and num>sadness_prob+anger_prob+joy_prob):
myList.append(self.id)
self.state['id'] = 4
networkStatus[self.id][self.env.now]=4
self.time_awareness[self.state['id']-1] = self.env.now
yield self.env.timeout(settings.timeout)
class BassModel(BaseNetworkAgent):
def __init__(self, environment=None, agent_id=0, state=()):
super().__init__(environment=environment, agent_id=agent_id, state=state)
self.innovation_prob = settings.innovation_prob
self.imitation_prob = settings.imitation_prob
networkStatus[self.id][self.env.now]=0
def run(self):
while True:
#Outside effects
if random.random() < settings.innovation_prob:
if self.state['id'] == 0:
self.state['id'] = 1
myList.append(self.id)
networkStatus[self.id][self.env.now]=1
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
#Imitation effects
if self.state['id'] == 0:
aware_neighbors = self.get_neighboring_agents(state_id=1)
num_neighbors_aware = len(aware_neighbors)
if random.random() < (settings.imitation_prob*num_neighbors_aware):
myList.append(self.id)
self.state['id'] = 1
networkStatus[self.id][self.env.now]=1
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
class IndependentCascadeModel(BaseNetworkAgent):
def __init__(self, environment=None, agent_id=0, state=()):
super().__init__(environment=environment, agent_id=agent_id, state=state)
self.innovation_prob = settings.innovation_prob
self.imitation_prob = settings.imitation_prob
self.time_awareness = 0
networkStatus[self.id][self.env.now]=0
def run(self):
while True:
aware_neighbors_1_time_step=[]
#Outside effects
if random.random() < settings.innovation_prob:
if self.state['id'] == 0:
self.state['id'] = 1
myList.append(self.id)
networkStatus[self.id][self.env.now]=1
self.time_awareness = self.env.now #Para saber cuando se han contagiado
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
#Imitation effects
if self.state['id'] == 0:
aware_neighbors = self.get_neighboring_agents(state_id=1)
for x in aware_neighbors:
if x.time_awareness == (self.env.now-1):
aware_neighbors_1_time_step.append(x)
num_neighbors_aware = len(aware_neighbors_1_time_step)
if random.random() < (settings.imitation_prob*num_neighbors_aware):
myList.append(self.id)
self.state['id'] = 1
networkStatus[self.id][self.env.now]=1
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
class ZombieOutbreak(BaseNetworkAgent):
def __init__(self, environment=None, agent_id=0, state=()):
super().__init__(environment=environment, agent_id=agent_id, state=state)
self.bite_prob = settings.bite_prob
networkStatus[self.id][self.env.now]=0
def run(self):
while True:
if random.random() < settings.heal_prob:
if self.state['id'] == 1:
self.zombify()
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
else:
if self.state['id'] == 1:
print("Soy el zombie " + str(self.id) + " y me voy a curar porque el num aleatorio ha sido " + str(num))
networkStatus[self.id][self.env.now]=0
if self.id in myList:
myList.remove(self.id)
self.state['id'] = 0
yield self.env.timeout(settings.timeout)
else:
yield self.env.timeout(settings.timeout)
def zombify(self):
normal_neighbors = self.get_neighboring_agents(state_id=0)
for neighbor in normal_neighbors:
if random.random() < self.bite_prob:
print("Soy el zombie " + str(self.id) + " y voy a contagiar a " + str(neighbor.id))
neighbor.state['id'] = 1 # zombie
myList.append(neighbor.id)
networkStatus[self.id][self.env.now]=1
networkStatus[neighbor.id][self.env.now]=1
print(self.env.now, "Soy el zombie: "+ str(self.id), "Mi vecino es: "+ str(neighbor.id), sep='\t')
break
2015-12-04 11:32:24 +00:00
##############
# Simulation #
##############
2015-12-04 10:41:42 +00:00
2015-12-17 11:56:39 +00:00
sim = NetworkSimulation(topology=G, states=init_states, agent_type=BigMarketModel,
2015-12-04 10:41:42 +00:00
max_time=settings.max_time, num_trials=settings.num_trials, logging_interval=1.0)
sim.run_simulation()
2015-12-04 11:32:24 +00:00
###########
# Results #
###########
2015-12-04 10:41:42 +00:00
myList = sorted(myList, key=int)
#print("Los zombies son: " + str(myList))
trial = BaseLoggingAgent.open_trial_state_history(dir_path='sim_01', trial_id=0)
2015-12-04 11:32:24 +00:00
status_census = [sum([1 for node_id, state in g.items() if state['id'] == 1]) for t,g in trial.items()]
2015-12-04 10:41:42 +00:00
2015-12-04 11:32:24 +00:00
#################
# Visualization #
#################
2015-12-04 10:41:42 +00:00
for x in range(0, settings.number_of_nodes):
2015-12-17 11:56:39 +00:00
emotionStatusAux=[]
for tiempo in emotionStatus[x]:
2015-12-04 10:41:42 +00:00
if tiempo != 'id':
2015-12-18 12:03:58 +00:00
prec = 2
output = math.floor(emotionStatus[x][tiempo] * (10 ** prec)) / (10 ** prec) #Para tener 2 decimales solo
emotionStatusAux.append((output,tiempo,None))
2015-12-17 11:56:39 +00:00
G.add_node(x, emotion= emotionStatusAux)
#lista = nx.nodes(G)
#print('Nodos: ' + str(lista))
# for x in range(0, settings.number_of_nodes):
# networkStatusAux=[]
# for tiempo in networkStatus[x]:
# if tiempo != 'id':
# networkStatusAux.append((networkStatus[x][tiempo],tiempo,None))
# G.add_node(x, status= networkStatusAux)
2015-12-04 10:41:42 +00:00
#print(networkStatus)
nx.write_gexf(G,"test.gexf", version="1.2draft")
2015-12-04 11:32:24 +00:00
plt.plot(status_census)
2015-12-04 10:41:42 +00:00
plt.draw() # pyplot draw()
2015-12-04 11:32:24 +00:00
plt.savefig("status.png")
2015-12-04 10:41:42 +00:00
#print(networkStatus)
#nx.draw(G)
#plt.show()
#plt.savefig("path.png")
2015-12-04 11:32:24 +00:00