我正在修补强化学习,尝试使用函数式编程来实现简单的环境。
我有函数step: State, Action -> State
和action_space: State -> [Action, ...]
。
我正在寻找在初始step
上实现函数State
的迭代组合的函数式编程方法
s = State()
e = [s]
while action_space(s):
a = best(action_space(s))
s = step(s, a)
e.append(s)
所以我认为我需要的是创造理解[f(x) and c(x), f(f(x)) and c(f(x)), f(f(f(x))) and c(f(f(x)), ...]
的方法,但没有不必要的评估。
提前致谢。
答案 0 :(得分:1)
此方案无法理解,但您可以创建生成器。在进入之前,我还建议您定义最佳和步骤函数,使其返回错误的内容(如False
或{{ 1}})每当最后一个( actions )参数是假的。它将简化您的代码。
然后你可以定义这个生成器:
None
这具有懒惰的优点。您可以像这样使用它:
def unfold(s):
while s:
yield s
s = step(s, best(action_space(s)))
或者只是:
e = [s for s in unfold(State())]
更具功能性的编程方法可以是这种递归函数:
e = list(unfold(State()))
如果您发现需要一个令人讨厌的命名函数,那么您可以选择这个技巧:
def unfold(s):
return [s] + unfold(step(s, best(action_space(s)))) if s else []
e = unfold(State())
但这很晦涩难懂。使用另一个函数作为参数立即调用第一个函数(第二行中的函数):实际的展开函数,其获取的名称是第一个函数的参数名称。
然后第一个函数返回另一个接受 state 参数的函数(e = (lambda unfold:lambda s:unfold(unfold,s))(
lambda unfold, s: [s] + unfold(unfold, step(s, best(action_space(s)))) if s else []
)(State())
),并用它调用展开。我们还立即调用该函数,并将初始值lambda s:unfold(unfold,s)
传递给它。
请注意,展开也会在递归树中自行传递,以便将其保持在范围内。