Python反射型真空智能体报错:感知数据解包值数量不匹配
反射型真空智能体解包错误修复方案
问题根源
报错ValueError: too many values to unpack (expected 2)的核心原因是感知数据格式不匹配:
TrivialVacuumEnvironment类的percept方法仅返回当前位置的清洁状态(如'Dirty'或'Clean'),是单个字符串值。- 但
ReflexVacuumAgent的program函数试图将这个单个值解包成location, status两个变量,导致解包失败。
修复方案(两种可选)
方案一:修改环境的感知输出格式(推荐,符合经典智能体设计)
调整TrivialVacuumEnvironment的percept方法,让它返回包含当前位置+清洁状态的元组,匹配智能体程序的预期:
class TrivialVacuumEnvironment(Environment): def __init__(self): super().__init__() self.status = {loc_A: random.choice(['Clean', 'Dirty']), loc_B: random.choice(['Clean', 'Dirty'])} def percept(self, agent): # 返回(位置,状态)元组 return (agent.location, self.status[agent.location]) def thing_classes(self): return [Dirt, ReflexVacuumAgent]
修改后,智能体程序里的location, status = percept就能正常解包两个值,无需改动智能体代码。
方案二:修改智能体程序的感知处理逻辑
如果不想改动环境代码,可以调整智能体的program函数,直接从智能体自身的location属性获取位置,仅用感知数据作为状态:
def ReflexVacuumAgent(): # 用闭包保存agent实例,让program能访问其location属性 agent = Agent() def program(percept): print("calling correct") status = percept if status == 'Dirty': return 'Suck' elif agent.location == loc_A: return 'Right' elif agent.location == loc_B: return 'Left' agent.program = program return agent
完整可运行代码(方案一修改后)
import collections import collections.abc import numbers import random class Thing: def __repr__(self): return '<{}>'.format(getattr(self, '__name__', self.__class__.__name__)) def is_alive(self): return hasattr(self, 'alive') and self.alive def show_state(self): print("I don't know how to show_state.") class Agent(Thing): def __init__(self, program=None): self.alive = True self.bump = False self.holding = [] self.performance = 0 if program is None or not isinstance(program, collections.abc.Callable): print("Can't find a valid program for {}, falling back to default.".format(self.__class__.__name__)) def program(percept): return eval(input('Percept={}; action? '.format(percept))) self.program = program def can_grab(self, thing): """Return True if this agent can grab this thing. Override for appropriate subclasses of Agent and Thing.""" return False loc_A, loc_B = (0, 0), (1, 0) def ReflexVacuumAgent(): def program(percept): print("calling correct") location, status = percept if status == 'Dirty': return 'Suck' elif location == loc_A: return 'Right' elif location == loc_B: return 'Left' return Agent(program) class Environment: def __init__(self): self.things = [] self.agents = [] def thing_classes(self ): return [] # List of classes that can go into environment def percept(self, agent): """Return the percept that the agent sees at this point. (Implement this.)""" raise NotImplementedError def default_location(self, thing): """Default location to place a new thing with unspecified location.""" return None def is_done(self): """By default, we're done when we can't find a live agent.""" return not any(agent.is_alive() for agent in self.agents) def step(self): """Run the environment for one time step. If the actions and exogenous changes are independent, this method will do. If there are interactions between them, you'll need to override this method.""" if not self.is_done(): actions = [] for agent in self.agents: if agent.alive: actions.append(agent.program(self.percept(agent))) else: actions.append("") for (agent, action) in zip(self.agents, actions): self.execute_action(agent, action) self.exogenous_change() def add_thing(self, thing, location=None): """Add a thing to the environment, setting its location. For convenience, if thing is an agent program we make a new agent for it. (Shouldn't need to override this.)""" if not isinstance(thing, Thing): thing = Agent(thing) if thing in self.things: print("Can't add the same thing twice") else: thing.location = location if location is not None else self.default_location(thing) self.things.append(thing) if isinstance(thing, Agent): thing.performance = 0 self.agents.append(thing) def execute_action(self, agent, action): # 补充动作执行逻辑,原代码缺失导致运行报错 if action == 'Suck': self.status[agent.location] = 'Clean' elif action == 'Right' and agent.location == loc_A: agent.location = loc_B elif action == 'Left' and agent.location == loc_B: agent.location = loc_A def exogenous_change(self): # 空实现,满足父类接口要求 pass class Dirt(Thing): pass class TrivialVacuumEnvironment(Environment): def __init__(self): super().__init__() self.status = {loc_A: random.choice(['Clean', 'Dirty']), loc_B: random.choice(['Clean', 'Dirty'])} def percept(self, agent): return (agent.location, self.status[agent.location]) def thing_classes(self): return [Dirt, ReflexVacuumAgent] # 实例化环境与智能体并运行 env = TrivialVacuumEnvironment() agnt = ReflexVacuumAgent() env.add_thing(agnt, location=loc_A) env.step()
注:原代码缺失execute_action方法实现,上述完整代码已补充,确保智能体动作能被正确执行。
内容的提问来源于stack exchange,提问作者HMPtwo
相关产品推荐
相关产品推荐

