class Simulador(): def __init__( self, tamanho_matriz, #numero de linhas e colunas da matriz esférica percentual_inicial_tipo1, #percentual inicial da população que será infectada tipo 1 percentual_inicial_tipo2, #percentual inicial da população que será infectada tipo 2 chance_infeccao, #chance que um infectado tipo 2 tem de infectar um indivíduo saudável chance_infeccao_tipo2, #chance de um indivíduo infectado se tornar contagioso chance_morte, #chance de um indivíduo tipo 2 morrer ao fim de uma atualização atualizacoes_cura ): #número de atualizações necessárias para a cura de um indivíduo tipo 1 ou 2 self.num_atualizacoes = 0 self.individuos_infectados_tipo_2 = [] self.individuos_infectados_tipo_1 = [] self.individuos_curados = [] self.individuos_mortos = [] self.lista_matrizes_posicionamento = [] self.matriz_status = np.zeros([tamanho_matriz, tamanho_matriz], dtype=int) self.fabrica_individuo = Fabrica_individuo(chance_infeccao, chance_infeccao_tipo2, chance_morte, atualizacoes_cura) self.matriz_individuos = pd.DataFrame(columns=range(tamanho_matriz), index=range(tamanho_matriz)) self.matriz_individuos.loc[:] = self.fabrica_individuo.criar_individuo( Individuo.SADIO, (0, 0)) self.matriz_status[:] = Individuo.SADIO #objeto que é responsável por validar a movimentação no grid n x n self.matriz_esferica = Matriz_esferica(tamanho_matriz) self.populacao_inicial = int(tamanho_matriz**2) self.num_inicial_tipo2 = int(self.populacao_inicial * percentual_inicial_tipo2) self.num_inicial_tipo1 = int(self.populacao_inicial * percentual_inicial_tipo1) self.num_inicial_sadios = self.populacao_inicial - ( self.num_inicial_tipo2 + self.num_inicial_tipo1) self.popular(tamanho_matriz) dict = { 'num_sadios': self.num_inicial_sadios, 'num_infect_t1': self.num_inicial_tipo1, 'num_infect_t2': self.num_inicial_tipo2, 'num_curados': 0, 'num_mortos': 0 } #dataframe que guardará os resultados de cada atualização self.dataframe = pd.DataFrame(index=[0]) self.salvar_posicionamento() def salvar_posicionamento(self): self.lista_matrizes_posicionamento.append(self.matriz_status) def verificar_infeccao(self, lista_infectantes): lista_novos_infectados_tipo1 = [] lista_novos_infectados_tipo2 = [] #itera sobre sobre a lista de individuos que infectam e cada um realiza a tividade de infectar for indice in lista_infectantes: #busca os vizinhos do infectante atual lista_vizinhos = self.matriz_esferica.get_vizinhos( indice[0], indice[1]) #Para cada vizinho, se ele for sadio, é gerado um número aleatório para verificar se foi infectado for vizinho in lista_vizinhos: x = vizinho[0] y = vizinho[1] #verificação de SADIO if self.matriz_status[x, y] == Individuo.SADIO: #verificação do novo status novo_status = self.matriz_individuos.loc[ indice[0], indice[1]].infectar() #se for um infectado tipo 1 if novo_status == Individuo.INFECTADO_TIPO_1: #adiciona na lista de novos tipo 1 lista_novos_infectados_tipo1.append((x, y)) #modifica o status do objeto recém infectado self.matriz_individuos.loc[ x, y].status = Individuo.INFECTADO_TIPO_1 #modifica o status na matriz de status self.matriz_status[x, y] = Individuo.INFECTADO_TIPO_1 if novo_status == Individuo.INFECTADO_TIPO_2: #adiciona na lista de novos tipo 2 lista_novos_infectados_tipo2.append((x, y)) #modifica o status do objeto recém infectado self.matriz_individuos.loc[ x, y].status = Individuo.INFECTADO_TIPO_2 #modifica o status na matriz de status self.matriz_status[x, y] = Individuo.INFECTADO_TIPO_2 return lista_novos_infectados_tipo1, lista_novos_infectados_tipo2 def verificar_morte(self, lista_infectantes_tipo2): lista_mortos = [] for indice in lista_infectantes_tipo2: novo_status = self.matriz_individuos.loc[ indice[0], indice[1]].checagem_morte() if novo_status == Individuo.MORTO: lista_mortos.append(indice) self.matriz_status[indice[0], indice[1]] = Individuo.MORTO return lista_mortos def verificar_cura(self, lista_infectantes): lista_curados = [] for indice in lista_infectantes: novo_status = self.matriz_individuos.loc[ indice[0], indice[1]].checagem_cura() if novo_status == Individuo.CURADO: lista_curados.append(indice) self.matriz_status[indice[0], indice[1]] = Individuo.CURADO return lista_curados def iterar(self): #Verifica os novos infectados a partir dos atuais infectantes na matriz lista_novos_infectados_tipo1_1, lista_novos_infectados_tipo2_1 = self.verificar_infeccao( self.individuos_infectados_tipo_1) lista_novos_infectados_tipo1_2, lista_novos_infectados_tipo2_2 = self.verificar_infeccao( self.individuos_infectados_tipo_2) #Verifica morte dos tipo 2 lista_mortos = self.verificar_morte(self.individuos_infectados_tipo_2) self.individuos_infectados_mortos #retirar os mortos da lista de infectados tipo 2 ### """ """ #adiciona os novos mortos na lista geral de mortos # self.individuos_infectados_mortos #Verificar cura lista_curados_tipo1 = verificar_cura(self.individuos_infectados_tipo_1) lista_curados_tipo2 = verificar_cura(self.individuos_infectados_tipo_2) #retirar os curados das lista de infectados tipo 1 e 2 """ """ #adiciona os novos curados na lista geral de curados # self. #movimentar infectantes: for i in range(len(self.individuos_infectados_tipo_1)): self.individuos_infectados_tipo_1[i] = self.mover_infectante( self.individuos_infectados_tipo_1[i]) for i in range(len(self.individuos_infectados_tipo_2)): self.individuos_infectados_tipo_2[i] = self.mover_infectante( self.individuos_infectados_tipo_2[i]) #adicionar os novos infectados tipo 1 e 2 para as respectivas listas # self.individuos_infectados_tipo_2 = [] # self.individuos_infectados_tipo_1 = [] #salva os resultados da atualização no dataframe: num_mortos = len(self.individuos_mortos) num_curados = len(self.individuos_curados) num_tipo_1 = len(self.individuos_infectados_tipo_1) num_tipo_2 = len(self.individuos_infectados_tipo_2) #salva a nova matriz de status self.salvar_posicionamento() #adiciona 1 ao número de atualizações realizadas na matriz self.num_atualizacoes += 1 def popular(self, tamanho_matriz): #lista de possíveis combinações de índices da matriz de dados permutacoes = permutations(list(range(tamanho_matriz)), 2) #conversão para lista de tuplas(x,y) lista_indices = list(permutacoes) #embaralhamento dos índices random.shuffle(lista_indices) #cria o primeiro tipo1: indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ ind_x, ind_y] = self.fabrica_individuo.criar_individuo( Individuo.INFECTADO_TIPO_1, (ind_x, ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_1.append((ind_x, ind_y)) self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 #cria o restante dos tipos 1 for i in range(1, self.num_inicial_tipo1): indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ ind_x, ind_y] = self.fabrica_individuo.criar_individuo( Individuo.INFECTADO_TIPO_1, (ind_x, ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_1.append((ind_x, ind_y)) self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 #cria o restante dos tipo 2: for indice in range(self.num_inicial_tipo2): indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ ind_x, ind_y] = self.fabrica_individuo.criar_individuo( Individuo.INFECTADO_TIPO_2, (ind_x, ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_2.append((ind_x, ind_y)) self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_2 def mover_infectante(self, indice): pos_x, pos_y = indice[0], indice[1] rng_posicao = random.random() if rng_posicao <= 0.25: #move pra cima pos_x -= 1 elif rng_posicao <= 0.5: #move pra baixo pos_x += 1 elif rng_posicao <= 0.75: #move para esquerda pos_y -= 1 else: #move para direita pos_y += 1 novo_x, novo_y = self.matriz_esferica.validar(pos_x, pos_y) #troca os valores no dataframe aux = self.matriz_individuos.loc[novo_x, novo_y] self.matriz_individuos.loc[novo_x, novo_y] = self.matriz_individuos.loc[pos_x, pos_y] self.matriz_individuos.loc[pos_x, pos_y] = aux #troca os valores na matriz de status aux = self.matriz_status[novo_x, novo_y] self.self.matriz_status[novo_x, novo_y] = self.matriz_status[pos_x, pos_y] self.self.matriz_status[pos_x, pos_y] = aux return (novo_x, novo_y)
class Simulador(): def __init__( self, tamanho_matriz, #numero de linhas e colunas da matriz esférica percentual_inicial_tipo1, #percentual inicial da população que será infectada tipo 1 percentual_inicial_tipo2, #percentual inicial da população que será infectada tipo 2 chance_infeccao, #chance que um infectado tipo 2 tem de infectar um indivíduo saudável chance_infeccao_tipo2, #chance de um indivíduo infectado se tornar contagioso chance_morte, #chance de um indivíduo tipo 2 morrer ao fim de uma atualização atualizacoes_cura): #número de atualizações necessárias para a cura de um indivíduo tipo 1 ou 2 self.num_atualizacoes = 0 self.individuos_infectados_tipo_2 = [] self.individuos_infectados_tipo_1 = [] self.individuos_infectados_curados = [] self.individuos_infectados_mortos = [] self.lista_matrizes_posicionamento = [] self.matriz_status = np.zeros([tamanho_matriz,tamanho_matriz]) self.fabrica_individuo = Fabrica_individuo( chance_infeccao, chance_infeccao_tipo2, chance_morte, atualizacoes_cura) self.matriz_individuos = pd.DataFrame(columns=range(tamanho_matriz), index=range(tamanho_matriz)) self.matriz_individuos.loc[:] = self.fabrica_individuo.criar_individuo(Individuo.SADIO,(0,0)) self.matriz_status[:] = Individuo.SADIO #objeto que é responsável por validar a movimentação no grid n x n self.matriz_esferica = Matriz_esferica(tamanho_matriz) self.populacao_inicial = int(tamanho_matriz**2) self.num_inicial_tipo2 = int(self.populacao_inicial * percentual_inicial_tipo2) self.num_inicial_tipo1 = int(self.populacao_inicial * percentual_inicial_tipo1) self.num_inicial_sadios = self.populacao_inicial - (self.num_inicial_tipo2 + self.num_inicial_tipo1) self.popular(tamanho_matriz) dict = { 'num_sadios':self.num_inicial_sadios, 'num_infect_t1':self.num_inicial_tipo1, 'num_infect_t2':self.num_inicial_tipo2, 'num_curados':0, 'num_mortos':0} #dataframe que guardará os resultados de cada atualização self.dataframe = pd.DataFrame(dict, index = [0]) self.salvar_posicionamento() def salvar_posicionamento(self): self.lista_matrizes_posicionamento.append(self.matriz_status) def popular(self, tamanho_matriz): #lista de possíveis combinações de índices da matriz de dados permutacoes = permutations(list(range(tamanho_matriz)),2) #conversão para lista de tuplas(x,y) lista_indices = list(permutacoes) #embaralhamento dos índices random.shuffle(lista_indices) print(len(lista_indices)) #cria o primeiro tipo1: indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ind_x,ind_y] = self.fabrica_individuo.criar_individuo(Individuo.INFECTADO_TIPO_1,(ind_x,ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_1.append((ind_x,ind_y)) self.matriz_status[ind_x,ind_y] = Individuo.INFECTADO_TIPO_1 #cria o restante dos tipos 1 for i in range(1,self.num_inicial_tipo1): indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ind_x,ind_y] = self.fabrica_individuo.criar_individuo(Individuo.INFECTADO_TIPO_1,(ind_x,ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_1.append((ind_x,ind_y)) self.matriz_status[ind_x,ind_y] = Individuo.INFECTADO_TIPO_1 #cria o restante dos tipo 2: for indice in range(self.num_inicial_tipo2): indice = lista_indices.pop() ind_x = indice[0] ind_y = indice[1] self.matriz_individuos.loc[ind_x,ind_y] = self.fabrica_individuo.criar_individuo(Individuo.INFECTADO_TIPO_2,(ind_x,ind_y)) #self.matriz_individuos[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1 self.individuos_infectados_tipo_2.append((ind_x,ind_y)) self.matriz_status[ind_x,ind_y] = Individuo.INFECTADO_TIPO_2 def mover_infectado(self, individuo: Individuo): pos_x, pos_y = individuo.posicao[0], individuo.posicao[1] rng_posicao = random.random() if rng_posicao <=0.25: #move pra cima pos_x -= 1 elif rng_posicao <=0.5: #move pra baixo pos_x += 1 elif rng_posicao <=0.75: #move para esquerda pos_y -= 1 else: #move para direita pos_y += 1 novo_x, novo_y = self.matriz_esferica.validar(pos_x, pos_y) #troca os valores no dataframe aux = self.matriz_individuos.loc[novo_x, novo_y] self.matriz_individuos.loc[novo_x, novo_y] = self.matriz_individuos.loc[pos_x, pos_y] self.matriz_individuos.loc[pos_x, pos_y] = aux #troca os valores na matriz de status aux = self.matriz_status[novo_x, novo_y] self.self.matriz_status[novo_x, novo_y] = self.matriz_status[pos_x, pos_y] self.self.matriz_status[pos_x, pos_y] = aux return (novo_x, novo_y)