是否可以“中断”递归函数并在以后继续?

时间:2020-07-03 09:10:01

标签: python recursion monte-carlo-tree-search

我有一个函数var person = {}; var key = "name"; person[key] /* this is same as person.name */ = "John"; console.log(person); // should print Object { name="John"} (蒙特卡洛树搜索的一种变体),它递归搜索一棵大树。它决定通过 var fileName=@"C:\Test.jpg"; using (ClientContext context = new ClientContext("http://sp/")) { using (var fs = new FileStream(fileName, FileMode.Open)) { var fi = new FileInfo(fileName); var list = context.Web.Lists.GetByTitle("Documents"); context.Load(list.RootFolder); context.ExecuteQuery(); var fileUrl = String.Format("{0}/{1}", list.RootFolder.ServerRelativeUrl, fi.Name); Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, fileUrl, fs, true); } } 遍历树的顺序,然后将结果在叶上传播回树。我必须执行许多此类搜索,some_result = treesearch(node)可以有效地进行批量计算,例如通过SIMD。

所以我的想法是创建一个包含所有搜索/根节点的列表,批量计算next_node = expensive_heuristic(node)以选择遍历的“方向”,然后重复此过程,直到找到叶子并可以传播结果为止那棵树。

当然,我可以使用队列而不是递归来重写搜索(保留历史记录),但是我很好奇是否可以保留递归样式。我可以“中断”递归并将其放入列表/队列中以便在以后的python中继续执行吗?

1 个答案:

答案 0 :(得分:0)

yieldyield fromsend是可能的;感谢juanpa.arrivillaga在评论中的建议。

以下代码在随机二叉树中搜索最多10个节点,并在其中返回最大值。每当必须计算用于引导搜索的heuristic时,它就会中断生成/搜索。

import random


class Node(object):
    def __init__(self, heuristic_value):
        self.children = {"left": None, "right": None}
        self.child_values = heuristic_value
        self.value = random.randint(0, 100)
        self.terminal = random.random() > 0.9

    def add_leaf(self):
        if self.terminal:
            return self.value

        direction = self.select()
        if self.children[direction]:
            value = yield from self.children[direction].add_leaf()
        else:
            value = yield from self.expand(direction)
        value = self.backup(direction, value)

        return value

    def select(self):
        if self.child_values["left"] > self.child_values["right"]:
            return "left"
        else:
            return "right"

    def expand(self, direction):
        heuristic_value = yield
        child = Node(heuristic_value)
        self.children[direction] = child
        return child.value

    def backup(self, direction, value):
        self.child_values[direction] = value
        if value > self.value:
            return value
        else:
            return self.value


def heuristic():
    return {"left": random.randint(0, 100), "right": random.randint(0, 100)}


tree = Node(heuristic())
for _ in range(10):
    gen = tree.add_leaf()
    value = None
    while True:
        try:
            gen.send(value)
            value = heuristic()
        except StopIteration as value:
            max_val = value
            break

print(f"Largest Value: {max_val}")