首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于agent的模型的实现

基于agent的模型的实现
EN

Stack Overflow用户
提问于 2019-09-17 03:54:18
回答 1查看 58关注 0票数 0

作为练习,我正在尝试用python (不使用Mesa包)实现一个基于代理的模型。我已经编写了描述观察者(包含所有代理)的代码,它可以帮助邻居代理,并告诉每个代理执行一个步骤。在将步骤复制到包含先前情况的列表之前,该步骤将保存在新列表中。

代理(本质上是域模型)是以下类型之一:'T‘(树)、'S’(土壤)、'B‘(燃烧树)和'Bd’(燃烧树)。

概念很简单:我们从一些树开始,一些燃烧的树,其余的是土壤。-土壤不会燃烧.-被烧毁的树仍然是被烧毁的树-被烧毁的树直接点燃它旁边的树(左、右、上或下),并在下一步成为被烧毁的树-树仍然是树,除非它们被邻近的燃烧的树点燃。

下面是这个的代码。我已经有了几个版本,但似乎都不起作用。当我运行下面的版本时,我得到一个错误。

代码语言:javascript
复制
import os
import sys
from copy import deepcopy
import random

# observer class
class Obs:
    def __init__(self, max_iters=10):
        self.agents = []
        self.max_iters = max_iters

    def run(self):
        self.history = []
        self.prev_agents = None
        self.iters = 0

        while self.iters < self.max_iters:
            print(self.iters)
            self.history.append(deepcopy(self.agents))
            self.prev_agents = deepcopy(self.agents)
            for agent in self.prev_agents:
                agent.step()
            self.iters += 1

    def add_agent(self, x, y, agent_type, num_agent):
        self.agents.append(
            Agent(
                agent_type=agent_type,
                x=x,
                y=y,
                observer=self,
                agent_id=num_agent
            ))

    def get_neighbours(self, x, y):
        # items do not move so use current_situation
        nbs = []
        for agent in self.agents:
            if (abs(agent.x-x) == 1) & (abs(agent.y-y) == 1) & (abs(agent.x-x) == abs(agent.y-y)):
                nbs.append(agent)
        return nbs

    def set_agent(self, index, agent):
        self.agents[index] = agent

    def changed(self, agent_id):
        if self.prev_agents[agent_id].agent_type != self.agents[agent_id].agent_type:
            # been changed, can't change it back so skip it
            return True
        return False

class Agent:
    def __init__(self, agent_type, x, y, observer, agent_id):
        self.agent_type = agent_type
        self.x = x
        self.y = y
        self.observer = observer
        self.agent_id = agent_id

    def step(self):
        # perform action
        if self.agent_type == 'B':
            # burning
            nbs = self.observer.get_neighbours(self.x, self.y)
            for nb in nbs:
                if nb.agent_type == 'T':
                    self.observer.set_agent(
                        nb.agent_id,
                        Agent('B',
                          nb.x,
                          nb.y,
                          nb.observer,
                          nb.agent_id))

            # set to burned
            self.agent_type = 'Bd'
            self.observer.set_agent(
                self.agent_id,
                self)
        elif self.agent_type == 'T':
            if not self.observer.changed(self.agent_id):
                self.observer.set_agent(
                    self.agent_id,
                    self)
        else:
            # nothing happens to soil or burned trees
            self.observer.set_agent(
                    self.agent_id,
                    self)


xsize, ysize = 10, 10
num_trees = 40
num_burning = 10
num_soil = (xsize * ysize) - num_trees - num_burning

items = ['T'] * num_trees + ['B'] * num_burning + ['S'] * num_soil
random.shuffle(items)
observer = Obs(10)

for i, item in enumerate(items):
    x = i % xsize
    y = i // xsize
    observer.add_agent(x=x, y=y, agent_type=item, num_agent=i)

observer.run()

我得到的错误是:

代码语言:javascript
复制
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-74779de210e4> in <module>
    104     observer.add_agent(x=x, y=y, agent_type=item, num_agent=i)
    105 
--> 106 observer.run()

<ipython-input-26-74779de210e4> in run(self)
     20             self.prev_agents = deepcopy(self.agents)
     21             for agent in self.prev_agents:
---> 22                 agent.step()
     23             self.iters += 1
     24 

<ipython-input-26-74779de210e4> in step(self)
     79                 self)
     80         elif self.agent_type == 'T':
---> 81             if not self.observer.changed(self.agent_id):
     82                 self.observer.set_agent(
     83                     self.agent_id,

<ipython-input-26-74779de210e4> in changed(self, agent_id)
     45 
     46     def changed(self, agent_id):
---> 47         if self.prev_agents[agent_id].agent_type != self.agents[agent_id].agent_type:
     48             # been changed, can't change it back so skip it
     49             return True

TypeError: 'NoneType' object is not subscriptable
EN

回答 1

Stack Overflow用户

发布于 2019-09-17 04:26:38

问题是,使用deepcopy时,您正在复制observer本身,它是每个代理上的引用,并且在您将要设置此属性时,这些observer副本具有self.prev_agents = None。具体来说,第20行self.prev_agents = deepcopy(self.agents)

对于

  • 中的每个代理,创建一个副本。每个代理存储一个引用,我们正在进行深度复制,我们还需要复制该观察者。

  • observer有各种属性,其中有self.prev_agents = deepcopy(self.agents)的右侧,我们仍在计算。self.prev_agents仍然是None (第14行)。

  • ,因此每个代理副本现在都有一个引用self.observer,它是原始观察者的副本,该副本具有self.prev_agents is None.

这就是为什么在随后对step的调用中,代理引用了错误的观察者,从而导致了错误。我不明白为什么要复制观察者,所以使用copy.copy而不是copy.deepcopy应该可以解决这个问题。

附注:深度复制每个代理也会遇到agent -> observer -> self.agents -> agent形式的引用循环,但copy.deepcopy通过保留已复制对象的备注字典来避免此问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57963581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档