Exemple #1
0
    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])
Exemple #2
0
    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.lista_infectados_tipo_2 = []
        self.lista_infectados_tipo_1 = []
        self.num_curados = 0
        self.num_mortos = 0

        self.chance_infeccao = chance_infeccao
        self.chance_infeccao_tipo2 = chance_infeccao_tipo2
        self.chance_morte = chance_morte

        
        #lista que guarda o posicionamento 
        self.lista_matrizes_posicionamento = []
        #guarda em matriz esparsa o status de saúde de cada elemento
        self.matriz_status = lil_matrix((tamanho_matriz,tamanho_matriz), dtype=np.uint8)

        #guarda em matriz esparsa a localização do objeto em sua respectiva lista
        self.matriz_localizacao = lil_matrix((tamanho_matriz,tamanho_matriz), dtype=np.uint32)

        self.fabrica_individuo = Fabrica_individuo(atualizacoes_cura)

        #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()
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)

        #retirar os mortos da atualização da lista de infectados tipo 2
        self.individuos_infectados_tipo_2 = [
            i for i in self.individuos_infectados_tipo_2
            if i not in lista_mortos
        ]

        #adiciona os novos mortos na lista geral de mortos
        self.individuos_mortos = self.individuos_mortos + lista_mortos

        #Verificar cura
        lista_curados_tipo1 = self.verificar_cura(
            self.individuos_infectados_tipo_1)
        lista_curados_tipo2 = self.verificar_cura(
            self.individuos_infectados_tipo_2)

        #retirar os curados das lista de infectados tipo 1 e 2
        self.individuos_infectados_tipo_2 = [
            i for i in self.individuos_infectados_tipo_2
            if i not in lista_curados_tipo2
        ]
        self.individuos_infectados_tipo_1 = [
            i for i in self.individuos_infectados_tipo_1
            if i not in lista_curados_tipo1
        ]

        #adiciona os novos curados na lista geral de curados
        self.individuos_curados = self.individuos_curados + lista_curados_tipo1 + lista_curados_tipo2

        # 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_2 + lista_novos_infectados_tipo2_1 + lista_novos_infectados_tipo2_2
        self.individuos_infectados_tipo_1 = self.individuos_infectados_tipo_1 + lista_novos_infectados_tipo1_1 + lista_novos_infectados_tipo1_2

        #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)

        dict = {
            'num_sadios':
            self.populacao_inicial - num_mortos - num_curados - num_tipo_1 -
            num_tipo_2,
            'num_infect_t1':
            num_tipo_1,
            'num_infect_t2':
            num_tipo_2,
            'num_curados':
            num_curados,
            'num_mortos':
            num_mortos
        }

        self.dataframe = self.dataframe.append(dict, ignore_index=True)

        #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.valida_ponto_matriz(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.matriz_status[novo_x, novo_y] = self.matriz_status[pos_x, pos_y]
        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.lista_infectados_tipo_2 = []
        self.lista_infectados_tipo_1 = []
        self.num_curados = 0
        self.num_mortos = 0

        self.chance_infeccao = chance_infeccao
        self.chance_infeccao_tipo2 = chance_infeccao_tipo2
        self.chance_morte = chance_morte

        self.populacao_inicial = int(tamanho_matriz**2)
        self.num_inicial_tipo2 = int(self.populacao_inicial *
                                     percentual_inicial_tipo2)
        self.num_inicial_tipo1 = 1 + int(
            self.populacao_inicial * percentual_inicial_tipo1)
        self.num_inicial_sadios = self.populacao_inicial - (
            self.num_inicial_tipo2 + self.num_inicial_tipo1)
        self.fabrica_individuo = Fabrica_individuo(atualizacoes_cura)

        self.df_individuos = pd.DataFrame(index=range(tamanho_matriz),
                                          columns=range(tamanho_matriz))
        #self.matriz_status = lil_matrix((tamanho_matriz, tamanho_matriz),dtype= np.uint8)
        self.matriz_status = self.df_individuos.to_numpy()
        self.popular(tamanho_matriz)

        self.lista_matrizes_posicionamento = []

        #objeto que é responsável por validar a movimentação no grid n x n
        self.matriz_esferica = Matriz_esferica(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.matriz_status = self.df_individuos.to_numpy()
        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 X, Y in lista_infectantes:

            #busca os vizinhos do infectante atual
            lista_vizinhos = self.matriz_esferica.get_vizinhos(X, Y)
            #Para cada vizinho, se ele for sadio, é gerado um número aleatório para verificar se foi infectado
            for x, y in lista_vizinhos:

                #verificação de SADIO
                if self.matriz_status[x, y] == Individuo.SADIO:
                    #verificação do novo status
                    novo_status = self.infectar(chance_infeccao,
                                                chance_infeccao_tipo2)
                    #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 na matriz de status
                        self.df_individuos.loc[
                            x, y] = self.fabrica_individuo.criar_individuo(
                                Individuo.INFECTADO_TIPO_1, (x, y))
                        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 na matriz de status
                        self.df_individuos.loc[
                            x, y] = self.fabrica_individuo.criar_individuo(
                                Individuo.INFECTADO_TIPO_2, (x, y))
                        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_curados = []
        lista_mortos = []
        for x, y in lista_infectantes_tipo2:
            novo_status = self.df_individuos.loc[x, y].checagem_morte(
                self.chance_morte)
            if novo_status == Individuo.MORTO:

                self.matriz_status[x, y] = Individuo.MORTO
                lista_mortos.append((x, y))
            if novo_status == Individuo.CURADO:

                self.matriz_status[x, y] = Individuo.CURADO
                lista_curados.append((x, y))

        return lista_mortos, lista_curados

    def verificar_cura(self, lista_infectantes):
        lista_curados = []
        for x, y in lista_infectantes:
            novo_status = self.df_individuos.loc[x, y].checagem_cura()
            if novo_status == Individuo.CURADO:

                self.matriz_status[x, y] = Individuo.CURADO
                lista_curados.append((x, y))

        return lista_curados

    def iterar(self):

        #Verifica os novos infectados a partir dos atuais infectantes na matriz
        lista_novos_infectados_tipo1, lista_novos_infectados_tipo2 = self.verificar_infeccao(
            self.lista_infectados_tipo_1)
        lista_novos_infectados_tipo1, lista_novos_infectados_tipo2 = self.verificar_infeccao(
            self.lista_infectados_tipo_2)

        #Verifica morte dos tipo 2
        lista_mortos_atualizacao, lista_curados_t2_atualizacao = self.verificar_morte(
            self.lista_infectados_tipo_2)

        self.lista_infectados_tipo_2 = [
            indice for indice in self.lista_infectados_tipo_2
            if indice not in lista_mortos_atualizacao
            and indice not in lista_curados_t2_atualizacao
        ]

        #atualiza o novo número de mortos
        self.num_mortos += len(lista_mortos_atualizacao)
        #Verificar cura
        lista_curados_t1_atualizacao = self.verificar_cura(
            self.lista_infectados_tipo_1)
        self.lista_infectados_tipo_1 = [
            indice for indice in self.lista_infectados_tipo_1
            if indice not in lista_curados_t1_atualizacao
        ]
        #adiciona os novos curados na lista geral de curados
        self.num_curados = self.num_curados + len(
            lista_curados_t1_atualizacao) + len(lista_curados_t2_atualizacao)

        # self.  #movimentar infectantes:
        for x, y in self.lista_infectados_tipo_1:
            self.mover_infectante((x, y))

        for x, y in self.lista_infectados_tipo_2:
            self.mover_infectante((x, y))

        #adicionar os novos infectados tipo 1 e 2 para as respectivas listas
        self.lista_infectados_tipo_2 = self.lista_infectados_tipo_2 + lista_novos_infectados_tipo2
        self.lista_infectados_tipo_1 = self.lista_infectados_tipo_1 + lista_novos_infectados_tipo1

        dict = {
            'num_sadios':
            self.populacao_inicial - self.num_mortos - self.num_curados -
            len(self.lista_infectados_tipo_1) -
            len(self.lista_infectados_tipo_2),
            'num_infect_t1':
            len(self.lista_infectados_tipo_1),
            'num_infect_t2':
            len(self.lista_infectados_tipo_2),
            'num_curados':
            self.num_curados,
            'num_mortos':
            self.num_mortos
        }

        self.dataframe = self.dataframe.append(dict, ignore_index=True)
        # self.matriz_status = self.matriz_status. lil_matrix(self.df_individuos.to to_numpy(),dtype=np.uint8)
        # print("num t1: ", len(self.lista_infectados_tipo_1))
        # print("num t2: ", len(self.lista_infectados_tipo_2))
        # print("num curados: ", self.num_curados)
        # print("num mortos: ", self.num_mortos)
        # print("---------")
        #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 infectar(self, chance_infeccao, chance_infeccao_tipo2):
        saida = Individuo.SADIO

        #número aleatório para chance de infectar o vizinho
        rng_infeccao = random.random()
        if rng_infeccao <= chance_infeccao:
            #número aleatório para chance de infecção tipo 1 ou 2
            rng_infeccao_tipo2 = random.random()
            if rng_infeccao_tipo2 <= chance_infeccao_tipo2:
                saida = Individuo.INFECTADO_TIPO_2
            else:
                saida = Individuo.INFECTADO_TIPO_1
        return saida

    def popular(self, tamanho_matriz):

        # for index, row in self.df_individuos.iterrows():
        #     for item in row:
        #         item = self.fabrica_individuo.criar_individuo(Individuo.SADIO,(0,0))
        self.df_individuos.iloc[:, :] = self.fabrica_individuo.criar_individuo(
            Individuo.SADIO, (0, 0))

        #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.lista_infectados_tipo_1.append((ind_x, ind_y))
        #print(indice)
        self.df_individuos.loc[ind_x,
                               ind_y] = self.fabrica_individuo.criar_individuo(
                                   Individuo.INFECTADO_TIPO_1, (ind_x, ind_y))
        #print(self.df_individuos)
        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.lista_infectados_tipo_1.append((ind_x, ind_y))
            self.df_individuos.loc[
                ind_x, ind_y] = self.fabrica_individuo.criar_individuo(
                    Individuo.INFECTADO_TIPO_1, (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.lista_infectados_tipo_2.append((ind_x, ind_y))
            self.df_individuos.loc[
                ind_x, ind_y] = self.fabrica_individuo.criar_individuo(
                    Individuo.INFECTADO_TIPO_2, (ind_x, ind_y))
            self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_2

    def trocar_status_localizacao(self, ponto_ini, ponto_final):
        x_ini = ponto_ini[0]
        y_ini = ponto_ini[1]
        x_fin = ponto_final[0]
        y_fin = ponto_final[1]

        aux1 = self.matriz_status[x_fin, y_fin]
        self.matriz_status[x_fin, y_fin] = self.matriz_status[x_ini, y_ini]
        self.matriz_status[x_ini, y_ini] = aux1

        aux2 = self.df_individuos.loc[x_fin, y_fin]
        self.df_individuos.loc[x_fin, y_fin] = self.df_individuos.loc[x_ini,
                                                                      y_ini]
        self.df_individuos.loc[x_ini, y_ini] = aux2

    def mover_infectante(self, posicao_inicial):
        pos_x, pos_y = posicao_inicial[0], posicao_inicial[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.valida_ponto_matriz(pos_x, pos_y)
        #descobre qual individuo ocupa atualmente a posição para atribuí-lo a posição de quem o está substituindo
        status = self.matriz_status[novo_x, novo_y]

        self.trocar_status_localizacao(posicao_inicial, (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.lista_infectados_tipo_2 = []
        self.lista_infectados_tipo_1 = []
        self.num_curados = 0
        self.num_mortos = 0

        self.chance_infeccao = chance_infeccao
        self.chance_infeccao_tipo2 = chance_infeccao_tipo2
        self.chance_morte = chance_morte

        self.df_individuos = pd.DataFrame(index=range(tamanho_matriz),
                                          columns=range(tamanho_matriz))
        print(df_individuos)
        #lista que guarda o posicionamento
        self.lista_matrizes_posicionamento = []
        #guarda em matriz esparsa o status de saúde de cada elemento
        self.matriz_status = lil_matrix((tamanho_matriz, tamanho_matriz),
                                        dtype=np.uint8)

        #guarda em matriz esparsa a localização do objeto em sua respectiva lista
        self.matriz_localizacao = lil_matrix((tamanho_matriz, tamanho_matriz),
                                             dtype=np.uint32)

        self.fabrica_individuo = Fabrica_individuo(atualizacoes_cura)

        #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 infectante in lista_infectantes:
            indice_x = infectante.posicao[0]
            indice_y = infectante.posicao[1]
            #busca os vizinhos do infectante atual
            lista_vizinhos = self.matriz_esferica.get_vizinhos(
                indice_x, indice_y)
            #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 = infectante.infectar(chance_infeccao,
                                                      chance_infeccao_tipo2)
                    #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(
                            self.fabrica_individuo.criar_individuo(
                                Individuo.INFECTADO_TIPO_1, (x, y)))
                        #modifica o status na matriz de status
                        self.matriz_status[x, y] = Individuo.INFECTADO_TIPO_1
                        self.matriz_localizacao[
                            x, y] = len(lista_novos_infectados_tipo1) - 1
                    if novo_status == Individuo.INFECTADO_TIPO_2:
                        #adiciona na lista de novos tipo 2
                        lista_novos_infectados_tipo2.append(
                            self.fabrica_individuo.criar_individuo(
                                Individuo.INFECTADO_TIPO_2, (x, y)))
                        #modifica o status na matriz de status
                        self.matriz_status[x, y] = Individuo.INFECTADO_TIPO_2
                        self.matriz_localizacao[
                            x, y] = len(lista_novos_infectados_tipo2) - 1
        return lista_novos_infectados_tipo1, lista_novos_infectados_tipo2

    def verificar_morte(self, lista_infectantes_tipo2):
        num_mortos = 0
        num_curados = 0
        for infectante in lista_infectantes_tipo2:
            novo_status = infectante.checagem_morte(self.chance_morte)
            if novo_status == Individuo.MORTO:
                num_mortos += 1
                self.matriz_status[infectante.posicao[0],
                                   infectante.posicao[1]] = Individuo.MORTO
                lista_infectantes_tipo2.remove(infectante)
            if novo_status == Individuo.CURADO:
                num_curados += 1
                self.matriz_status[infectante.posicao[0],
                                   infectante.posicao[1]] = Individuo.CURADO
                lista_infectantes_tipo2.remove(infectante)

        return num_mortos, num_curados

    def verificar_cura(self, lista_infectantes):
        num_curados = 0
        for infectante in lista_infectantes:
            novo_status = infectante.checagem_cura()
            if novo_status == Individuo.CURADO:
                num_curados += 1
                self.matriz_status[infectante.posicao[0],
                                   infectante.posicao[1]] = Individuo.CURADO
                lista_infectantes_tipo.remove(infectante)

        return num_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.lista_infectados_tipo_1)
        lista_novos_infectados_tipo1_2, lista_novos_infectados_tipo2_2 = self.verificar_infeccao(
            self.lista_infectados_tipo_2)

        #Verifica morte dos tipo 2
        num_mortos_atualizacao, num_curados_t2_atualizacao = self.verificar_morte(
            self.lista_infectados_tipo_2)

        #retirar os mortos da atualização da lista de infectados tipo 2
        self.lista_infectados_tipo_2 = [
            i for i in self.lista_infectados_tipo_2
            if i.status != Individuo.MORTO
        ]

        #atualiza o novo número de mortos
        self.num_mortos += num_mortos_atualizacao

        #Verificar cura
        num_curados_t1_atualizacao = self.verificar_cura(
            self.lista_infectados_tipo_1)

        #retirar os curados das lista de infectados tipo 1 e 2
        self.lista_infectados_tipo_2 = [
            i for i in self.lista_infectados_tipo_2
            if i.status != Individuo.CURADO
        ]
        self.lista_infectados_tipo_1 = [
            i for i in self.lista_infectados_tipo_1
            if i.status != Individuo.CURADO
        ]

        #adiciona os novos curados na lista geral de curados
        self.num_curados = self.num_curados + num_curados_t1_atualizacao + num_curados_t2_atualizacao

        # self.  #movimentar infectantes:
        for infectante in self.lista_infectados_tipo_1:
            self.mover_infectante(infectante)

        for infectante in self.lista_infectados_tipo_2:
            self.mover_infectante(infectante)

        #adicionar os novos infectados tipo 1 e 2 para as respectivas listas
        self.lista_infectados_tipo_2 = self.lista_infectados_tipo_2 + lista_novos_infectados_tipo2_1 + lista_novos_infectados_tipo2_2
        self.lista_infectados_tipo_1 = self.lista_infectados_tipo_1 + lista_novos_infectados_tipo1_1 + lista_novos_infectados_tipo1_2

        num_tipo_1 = len(self.lista_infectados_tipo_1)

        num_tipo_2 = len(self.lista_infectados_tipo_2)

        dict = {
            'num_sadios':
            self.populacao_inicial - self.num_mortos - self.num_curados -
            num_tipo_1 - num_tipo_2,
            'num_infect_t1':
            num_tipo_1,
            'num_infect_t2':
            num_tipo_2,
            'num_curados':
            self.num_curados,
            'num_mortos':
            self.num_mortos
        }

        self.dataframe = self.dataframe.append(dict, ignore_index=True)

        print("num t1: ", num_tipo_1)
        print("num t2: ", num_tipo_2)
        print("num curados: ", self.num_curados)
        print("num mortos: ", self.num_mortos)
        print("---------")
        #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.lista_infectados_tipo_1.append(
            self.fabrica_individuo.criar_individuo(Individuo.INFECTADO_TIPO_1,
                                                   (ind_x, ind_y)))
        self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1
        self.matriz_localizacao[ind_x, ind_y] = 0

        #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.lista_infectados_tipo_1.append(
                self.fabrica_individuo.criar_individuo(
                    Individuo.INFECTADO_TIPO_1, (ind_x, ind_y)))
            self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_1
            self.matriz_localizacao[ind_x, ind_y] = len(
                self.lista_infectados_tipo_1) - 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.lista_infectados_tipo_2.append(
                self.fabrica_individuo.criar_individuo(
                    Individuo.INFECTADO_TIPO_2, (ind_x, ind_y)))
            self.matriz_status[ind_x, ind_y] = Individuo.INFECTADO_TIPO_2
            self.matriz_localizacao[ind_x, ind_y] = len(
                self.lista_infectados_tipo_2) - 1

    def trocar_status_localizacao(self, ponto_ini, ponto_final):
        x_ini = ponto_ini[0]
        y_ini = ponto_ini[1]
        x_fin = ponto_final[0]
        y_fin = ponto_final[1]

        aux1 = self.matriz_status[x_fin, y_fin]
        self.matriz_status[x_fin, y_fin] = self.matriz_status[x_ini, y_ini]
        self.matriz_status[x_ini, y_ini] = aux1

        aux2 = self.matriz_localizacao[x_fin, y_fin]
        self.matriz_localizacao[x_fin, y_fin] = self.matriz_localizacao[x_ini,
                                                                        y_ini]
        self.matriz_localizacao[x_ini, y_ini] = aux2

    def mover_infectante(self, infectante):
        pos_x, pos_y = infectante.posicao[0], infectante.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.valida_ponto_matriz(pos_x, pos_y)
        #descobre qual individuo ocupa atualmente a posição para atribuí-lo a posição de quem o está substituindo
        status = self.matriz_status[novo_x, novo_y]
        if status == Individuo.INFECTADO_TIPO_1:
            individuo_ocupante_destino = self.matriz_localizacao[novo_x,
                                                                 novo_y]
            print(status)
            print(individuo_ocupante_destino)
            print(len(self.lista_infectados_tipo_1))

            self.lista_infectados_tipo_1[
                individuo_ocupante_destino].posicao = infectante.posicao
        elif status == Individuo.INFECTADO_TIPO_2:
            individuo_ocupante_destino = self.matriz_localizacao[novo_x,
                                                                 novo_y]
            print(status)
            print(individuo_ocupante_destino)
            print(len(self.lista_infectados_tipo_2))
            self.lista_infectados_tipo_2[
                individuo_ocupante_destino].posicao = infectante.posicao

        # elif status == Individuo.CURADO:
        #     individuo_ocupante_destino = self.matriz_localizacao[novo_x, novo_y]
        #     self.lista_curados[individuo_ocupante_destino].posicao = infectante.posicao
        # elif status == Individuo.MORTO:
        #     individuo_ocupante_destino = self.matriz_localizacao[novo_x, novo_y]
        #     self.lista_matrizes_posicionamento[individuo_ocupante_destino].posicao = infectante.posicao

        self.trocar_status_localizacao(infectante.posicao, (novo_x, novo_y))
Exemple #6
0
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_individuos = 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.INFECTADO_TIPO_1,(0,0))
        
        #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_individuos.apply(self.get_status_individuo))
    
    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:
        ind_x = lista_indices.pop()[0]
        ind_y = lista_indices.pop()[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))
        
        #cria o restante dos tipos 1
        for i in range(1,self.num_inicial_tipo1):
            ind_x = lista_indices.pop()[0]
            ind_y = lista_indices.pop()[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))

        #cria o restante dos tipo 2:
        for indice in range(self.num_inicial_tipo2):
            ind_x = lista_indices.pop()[0]
            ind_y = lista_indices.pop()[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))
    
    
    
    def get_status_individuo(self, individuo: Individuo):
        return individuo.status

    def mover_infectado(self, individuo: Individuo):
        pos_x, pos_y = individuo.posicao[0], individuo.posicao[1]
        pass