Simulação baseada em agente em Python

Neste artigo, demonstro simulação baseada em agente em Python. Na verdade, já apresentei a modelagem baseada em agente em Python em postagens anteriores. Por exemplo, introduzi um modelo de campo de batalha que contém grupos de agentes localizados em uma grade 2D. Codifiquei esse modelo em Python e usei o Matplotlib para visualização. Neste artigo, não apenas construirei um modelo, mas também executarei toda uma simulação baseada em agente em Python.

Módulo simples para simulação baseada em agente em Python

Para começar, preciso construir um módulo simples para simulações baseadas em agentes em Python. Em primeiro lugar, assim como em minha introdução anterior à modelagem baseada em agente em Python, defino um tipo de dados de agente personalizado. Isso é feito na forma de uma classe personalizada em Python.

# class, defining agents as abstract data types
class agent:
    # init-method, the constructor method for agents
    def __init__(self,x,y,group):
        self.life = 100 # agent's life score
        self.x = x
        self.y = y
        self.group = group

Como pode ser visto no construtor da classe de agente, um agente tem uma pontuação de vida. Além disso, os agentes pertencem a um grupo e têm coordenadas x e y. Esses atributos de coordenadas são usados ​​para descrever a localização dos agentes em uma grade 2D.

Basicamente, um array bidimensional é usado para conter todos os agentes. Assim, as populações de agentes são alocadas em uma grade 2D. Neste caso, esta grade representa um campo de batalha. Como pode ser visto abaixo, criei o campo de batalha com uma compreensão de lista em Python.

# creating empty 100 x 100 list using list comprehension in python
battlefield = [[None for i in range(0,100)] for i in range(0,100)]

Agora continuo definindo uma função auxiliar em Python para criar e alocar agentes no campo de batalha. Vou usar esta função para configurar minha simulação baseada em agente em Python.

# define a function for creating agents and assigning them to grid
def agentCreator(size,group,groupList,field,n,m):
    # loop through entire group, i.e. in this case 1000 units
    for j in range(0,size):
        # select random available location 
        while True:
            # random x coordinate
            x = random.choice(range(0,n))
            # random y coordinate
            y = random.choice(range(0,m))
            # check if spot is available; if not then re-iterate 
            if field[x][y] == None:
                field[x][y] = agent(x=x,y=y,group=group)
                # append agent object reference to group list
                groupList.append(field[x][y])
                # exit while loop; spot on field is taken
                break

Resumindo, a função agentCreator cria uma quantidade especificada de agentes e os aloca em um campo. Cada agente criado por uma chamada de função tem o mesmo tipo. Como pode ser visto na definição da função, o tipo é um parâmetro de entrada da função. Outro ponto importante a ser observado é que o campo em que os agentes estão alocados é passado como referência. Ou seja, neste caso o campo é a grade do campo de batalha. Ele facilita a tela na qual essa simulação baseada em agente em Python ocorre.

Inicializando minha simulação baseada em agente em Python

Usando esses componentes de modelo, agora inicio meu modelo. Para iniciar minha simulação baseada em agente em Python, crio um campo de batalha inicial. Além disso, adiciono agentes a ele. Tudo isso é feito chamando a função agentCreator como mostrei acima. Eu chamo a função duas vezes para adicionar dois grupos de agentes. O primeiro grupo é do tipo “A” enquanto o segundo grupo é do tipo “B”.

# list with available x and y locations
locations = battlefield.copy() # using .copy prevents copying by reference
# create empty list for containing agent references in future, type A & B
agents_A = []
agents_B = []
# assigning random spots to agents of group A and B; 
import random
agentCreator(size = 1000,
                group = "A",
                groupList = agents_A,
                field = battlefield,
                n = 100,
                m = 100)
agentCreator(size = 1000,
                group = "B",
                groupList = agents_B,
                field = battlefield,
                n = 100,
                m = 100) 

Embora os dados agora reflitam uma grade 2D com duas populações de agentes concorrentes, não consigo vê-los visualmente. Usarei o Matplotlib para visualizar essa simulação baseada em agente em Python. Nos parágrafos seguintes, demonstro como fazer isso.

Matplotlib visualiza simulação baseada em agente em Python

Conforme mostrado por mim em uma das minhas postagens anteriores no blog, o Matplotlib pode ser usado para visualizar grades 2D em Python. Eu coloquei uma referência na forma de um link no final deste artigo. Certifique-se de ler caso queira implementar esse tipo de visualização do zero por conta própria.

No código exibido abaixo, uso o Matplotlib para visualizar cada célula na grade do campo de batalha. Eu faço isso criando uma matriz flutuante 2D usando uma compreensão de lista em Python. Em seguida, itero através de cada par de índices da grade 2D. Devido a cada par de índices na matriz flutuante corresponder a um par de índices na grade do campo de batalha, posso identificar células com agentes nelas. Eu sobrescrevo as células que contêm um agente. Resumindo, toda célula com agente do tipo A recebe float 1.0 enquanto toda célula com agente do tipo B recebe float 2.0.

#.imshow() needs a matrix with float elements;
population = [[0.0 for i in range(0,100)] for i in range(0,100)]

# if agent is of type A, put a 1.0, if of type B, pyt a 2.0
for i in range(1,100):
    for j in range(1,100):
        if battlefield[i][j] == None: # empty
            pass # leave 0.0 in population cell
        elif battlefield[i][j].group == "A": # group A agents
            population[i][j] = 1.0 # 1.0 means "A"
        else: # group B agents
            population[i][j] = 2.0 # 2.0 means "B"

Não consigo visualizar o battlefiend. Para fazer isso, importo pyplot e cores do Matplotlib em Python. Isso me permite criar um objeto ListedColormap. Os objetos ListedColormap podem ser baseados como referências ao método pyplot.imshow(). Eu mostro isso no código abaixo.


# import pyplot and colors from matplotlib
from matplotlib import pyplot, colors

# using colors from matplotlib, define a color map
colormap = colors.ListedColormap(["lightgrey","green","blue"])

# define figure size using pyplot
pyplot.figure(figsize = (12,12))
# using pyplot add a title
pyplot.title("battlefield before simulation run (green = A, blue = B)",
            fontsize = 24)
# using pyplot add x and y labels
pyplot.xlabel("x coordinates", fontsize = 20)
pyplot.ylabel("y coordinates", fontsize = 20)
# adjust x and y axis ticks, using pyplot
pyplot.xticks(fontsize = 16)
pyplot.yticks(fontsize = 16)
# use .imshow() method from pyplot to visualize agent locations
pyplot.imshow(X = population,
             cmap = colormap)

<matplotlib.image.AxesImage em 0x22495922ac8>

Status inicial do modelo de simulação baseada em agente em Python

Agora podemos executar e visualizar uma simulação baseada em agente em Python. Embora mostre apenas uma iteração da simulação neste artigo, coloquei uma referência vinculada a outro artigo no qual utilizo a execução de um experimento de simulação inteiro.

Implementando estratégias para interação agente

Para isso implementamos duas estratégias de ataque:

O Grupo A tem a estratégia de acertar sempre o mesmo agente em cada rodada
O Grupo B tem uma estratégia aleatória e independente para atacar os inimigos. Isso significa que cada agente do tipo B atacará um inimigo selecionado aleatoriamente ao alcance desse agente.

A simulação agora é conduzida sob as seguintes condições:

1) Cada rodada é uma iteração
2) A cada rodada, cada agente pode atacar um agente ao seu alcance
3) O alcance de um agente é definido no início da simulação e o padrão é 10
4) Se um agente morrer ele não estará mais localizado no campo de batalha
5) Um agente morre quando sua pontuação de vida iguala ou fica abaixo de zero
6) Cada agente tem um dano de ataque distribuído aleatoriamente, variando de 10 a 60
7) Em cada rodada todos os agentes podem lançar um ataque

Com essas regras em vigor, agora irei iterar por 50 rodadas de luta. No final, imprimirei um gráfico dos agentes restantes no campo de batalha. A implementação segue abaixo:

for counter in range(0,50): # neste caso estou conduzindo 50 iterações
    # iterando por todas as células no campo de batalha
    para i no intervalo(0,len(campo de batalha)):
        para j no intervalo(0,len(campo de batalha)):
            #print("iteração de nível superior, i: "+str(i)+", j: "+str(j))
            # verifica se existe um agente na respectiva célula
            if battlefield[i][j] != Nenhum:
                # dependendo do tipo: executa a respectiva estratégia de ataque
                se campo de batalha[i][j].grupo == "A":
                    encontrado_i = Nenhum
                    found_j = Nenhum
                    # procura nas células vizinhas na mesma ordem para cada iteração
                    para k no intervalo(i-10,i+11):
                        para l no intervalo(j-10,j+11):
                            # verifica se há valores de índice negativos; se assim for - quebre!
                            se k < 0 ou l < 0:
                                pausa
                            # verifique se há valores de índice acima de 99, se for o caso, interrompa!
                            se k > 99 ou l > 99:
                                pausa
                            se campo de batalha[k][l]:
                                if battlefield[k][l].group == "B": # então este é um inimigo
                                    if found_i == Nenhum:
                                        encontrado_i = k
                                        encontrado_j = l
                    # causa dano ao inimigo identificado
                    se encontrado_i:
                        battlefield[found_i][found_j].life = battlefield[found_i][found_j].life - random.randint(10,60)
                outro:
                    # primeiro verifique se há um inimigo em uma das células ao redor
                    inimigo_encontrado = Falso
                    para k no intervalo(i-10,i+11):
                        para l no intervalo(j-10,j+11):
                            # verifica se há índice negativo, se sim, vá para a próxima iteração
                            se k < 0 ou l < 0:
                                pausa
                            # verifique se há valores de índice acima de 99, se for o caso, interrompa
                            se k > 99 ou l > 99:
                                pausa
                            if battlefield[k][l] != Nenhum:
                                se campo de batalha[k][l].grupo == "A":
                                    inimigo_encontrado = Verdadeiro
                    # seleciona uma linha aleatória e uma coluna aleatória
                    encontrado_i = Nenhum
                    found_j = Nenhum
                    enquanto inimigo_encontrado e encontrado_i == Nenhum:
                        k = random.randint(i-10,i+10)
                        l = random.randint(j-10,j+10)
                        # verifique se há índice negativo, se for, continue para a próxima iteração
                        se k < 0 ou l < 0:
                            Prosseguir
                        # verifique se há valor de índice > 99, se sim, continue
                        se k > 99 ou l > 99:
                            Prosseguir
                        se k != i:
                            se campo de batalha[k][l]:
                                se campo de batalha[k][l].grupo == "A":
                                    encontrado_i = k
                                    encontrado_j = l
                        outro:
                            se l != j:
                                se campo de batalha[k][l]:
                                    se campo de batalha[k][l].grupo == "A":
                                        encontrado_i = k
                                        encontrado_j = l
                    # causa dano ao inimigo identificado
                    se encontrado_i:
                        battlefield[found_i][found_j].life = battlefield[found_i][found_j].life - random.randint(10,60)
    # identificando agentes com pontuação de vida de pontuação ou abaixo - e removendo-os da grade
    para i no intervalo(0,len(campo de batalha)):
        para j no intervalo(0,len(campo de batalha)):
            se campo de batalha[i][j]:
                se campo de batalha[i][j].vida <= 0:
                    campo de batalha[i][j] = Nenhum
# produzindo um gráfico de todos os locais do campo de batalha, 10 iterações após
população = [[0,0 para i no intervalo(0,100)] para i no intervalo(0,100)]
# se agente for do tipo A, coloque 1.0, se for do tipo B, pyt 2.0
para i no intervalo (1.100):
    para j no intervalo (1.100):
        if battlefield[i][j] == Nenhum: # vazio
            pass # deixa 0.0 na célula de população
        elif battlefield[i][j].grupo == "A": # agentes do grupo A
            população[i][j] = 1,0 # 1,0 significa "A"
        else: # agentes do grupo B
            população[i][j] = 2,0 # 2,0 significa "B"
# import pyplot e cores do matplotlib 
from matplotlib import pyplot, colors
# usando cores do matplotlib , defina um mapa de cores
colormap = colors.ListedColormap(["lightgrey","green","blue"])
# define o tamanho da figura usando pyplot
pyplot.figure(figsize = (12,12))
# usando pyplot adicione um título
pyplot.title("campo de batalha após 50 iterações (verde = A, azul = B)",
            tamanho da fonte = 24)
# usando pyplot adicione rótulos x e y
pyplot.xlabel("coordenadas x", tamanho da fonte = 20)
pyplot.ylabel("coordenadas y", tamanho da fonte = 20)
# ajusta os tiques dos eixos x e y, usando pyplot
pyplot.xticks(tamanho da fonte = 16)
pyplot.yticks(tamanho da fonte = 16)
# use o método .imshow() do pyplot para visualizar a localização dos agentes
pyplot.imshow(X = população,
             cmap = mapa de cores)
<matplotlib.image.AxesImage em 0x22495be1848>
Estado final no horário final da simulação baseada em agente em Python

Considerações finais e referências a conteúdo relacionado

Em algumas postagens a seguir, limparei o código e empacotarei sua funcionalidade em funções reutilizáveis. Em seguida, conduzirei um estudo de simulação mais abrangente no qual vários parâmetros são variados para investigar seu impacto no resultado da batalha.

Neste exemplo, usei listas do Python como meus contêineres de agentes preferidos. No entanto, modelos semelhantes podem ser construídos usando, por exemplo, arrays NumPy .

Se você estiver interessado em simulação baseada em agentes, poderá se interessar pelo seguinte conteúdo:

Leave a Reply

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Close

Meta