我的程序中存在一个错误,我试图使用带有评估表达式的Pycharm调试工具对其进行调试。我碰到了我的代码无法正常工作的原因,但是却不了解这种情况如何发生。当我用一些参数调用函数marginalizedTransition时,结果为1.0,但是当我在函数内部运行代码时,将参数放在它们的位置,则得到0.00101001196095。但是,它们应该相同,因为它们是相同的代码。
player = 1
,world.amountOfPlayers() = 2
和world.amountOfPossibleActions = 5
。
marginalizedTransitionTest(Ps, [(3, 1), (5, 1)], [(2, 1), (5, 1)], 0, world, 1)
其中
def marginalizedTransitionTest(Ps, sis, sfs, action, world, player):
otherPlayers = filter(lambda x: x != player, range(world.amountOfPlayers()))
return sum(np.prod([Ps[otherPlayer][tuple(it.chain(*sis))]
[np.insert(actions, player, action)[otherPlayer]]
for otherPlayer in otherPlayers])
for actions in it.product(range(world.amountOfPossibleActions), repeat=world.amountOfPlayers() - 1))
给出4.05514478458和
sum(np.prod([Ps[otherPlayer][tuple(it.chain(*[(3, 1), (5, 1)]))]
[np.insert(actions, 1, 0)[otherPlayer]]
for otherPlayer in filter(lambda x: x != 1, range(world.amountOfPlayers()))])
for actions in it.product(range(world.amountOfPossibleActions), repeat=world.amountOfPlayers() - 1))
给出1.0。
我不知道这是否是常见问题。如果您需要有关所使用功能的更多信息,我可以提供它们,但是此帖子已经变得很难看了。
答案 0 :(得分:1)
这是由于filter
作为迭代器的行为。在函数中,首先创建迭代器,然后在其上运行for
多次。但是,如果您尝试仅运行以下命令:
otherPlayers = filter(lambda x: x != player, range(world.amountOfPlayers()))
for player in otherPlayers:
print(f'1: {player}')
for player in otherPlayers:
print(f'2: {player}')
结果将是:
1: 0
1: 1
如您所见,一旦为过滤器运行了for,它就筋疲力尽,并且不会返回任何内容。
原始运行时,您没有做相同的事情,因此迭代器按预期工作。
因此,修复很简单:在for
中添加过滤器:
def marginalizedTransition(Ps, sis, sfs, action, world, player):
return sum(world.joinedTransition(sis, sfs, np.insert(actions, player, action)) *
np.prod([Ps[otherPlayer][tuple(it.chain(*sis))][np.insert(actions, player, action)[otherPlayer]]
for otherPlayer in filter(lambda x: x != player, range(world.amountOfPlayers()))])
for actions in it.product(range(world.amountOfPossibleActions), repeat=world.amountOfPlayers() - 1))
或者,正如您在聊天中指出的那样,您可以将迭代器转换为列表:
def marginalizedTransition(Ps, sis, sfs, action, world, player):
otherPlayers = list(filter(lambda x: x != player, range(world.amountOfPlayers())))
return sum(world.joinedTransition(sis, sfs, np.insert(actions, player, action)) *
np.prod([Ps[otherPlayer][tuple(it.chain(*sis))][np.insert(actions, player, action)[otherPlayer]]
for otherPlayer in otherPlayers])
for actions in it.product(range(world.amountOfPossibleActions), repeat=world.amountOfPlayers() - 1))
对于想要重现此问题的SO用户,我基于聊天讨论创建了这些虚拟对象,并解构了如下的理解:
import numpy as np
import itertools as it
class World:
amountOfPossibleActions = 5
def amountOfPlayers(self):
return 2
def joinedTransition(self, a, b, insert):
return 1 if insert[0] == 3 else 0
world = World()
player = 1
Ps = {0: {(3, 1, 5, 1): [[0.055144784579474179], [0.055144784579474179], [0.055144784579474179], [0.055144784579474179],
[0.055144784579474179]]}}
def marginalizedTransition(Ps, sis, sfs, action, world, player):
otherPlayers = filter(lambda x: x != player, range(world.amountOfPlayers()))
s = 0
for actions in it.product(range(world.amountOfPossibleActions), repeat=world.amountOfPlayers() - 1):
w = world.joinedTransition(sis, sfs, np.insert(actions, player, action))
a = []
for otherPlayer in otherPlayers:
b = np.insert(actions, player, action)[otherPlayer]
v = Ps[otherPlayer][tuple(it.chain(*sis))][b]
a.append(v)
p = np.prod(a)
s += w * p
return s
在个人说明上: 列表理解功能很棒,它使代码真正紧凑。但是,这会使阅读和调试代码变得非常困难。下次您想嵌套理解时,请记住这一点。如上所示,在对它进行解构之后,我只能找出问题所在。