树搜索保存执行状态

时间:2011-08-20 21:15:18

标签: java clojure tree lisp

我有一棵树,

     A
    / \
   B   C
  /\    \
 D  E    F

表示为列表,

(A (B (D) (E)) (C (F)))

它实际上是一棵非常大的树,所以我想做的就是开始搜索,如果我找不到我要找的东西说100毫秒保存状态,返回,做一些家务,然后再打电话搜索并继续我离开的地方。基本上我正在使用的模拟给了我一定的时间来完成搜索。我正在寻找关于如何实现这一目标的想法/技巧? (在Clojure,Java)

3 个答案:

答案 0 :(得分:7)

线程可能是最简单的解决方案,但在单个线程上自己管理它并不是很困难。

基本思想是创建一个闭包,表示完成任务需要完成的工作,如果没有时间完成,则返回结果而不是结果。这是一个草图:它增加了一系列数字,并且每十次操作而不是每100ms被中断。

(let [timer (atom 9)]
  (defn keep-going? []
    (not= 0 (swap! timer #(mod (inc %) 10)))))

(defn saving-addition [sum xs]
  (if-let [[x & more] (seq xs)]
    (let [next-thunk (fn [] (saving-addition (+ x sum) more))]
      (if (keep-going?)
        (next-thunk)
        next-thunk))
    sum))

(defn monitor [xs]
  (loop [thunk (saving-addition 0 xs)]
    (if (fn? thunk)
      (do
        (println "Saving execution state")
        (recur (thunk)))
      thunk)))

user> (monitor (range 25))
Saving execution state
Saving execution state
Saving execution state
300

编辑:因为Clojure没有尾调用优化,所以创建一个thunk然后调用它会占用堆栈。如果您可能在需要中断之前执行超过几千步,则会出现堆栈溢出。唯一可行的解​​决方案是在recur和延续中复制thunk的主体,例如

(defn saving-addition [sum xs]
  (if-let [[x & more] (seq xs)]
    (let [sum (+ x sum)]
      (if (keep-going?)
        (recur sum more)
        #(saving-addition sum more)))
    sum))

如果必须编写多个这样的“可挂起”函数,你可以用宏来抽象出来。

答案 1 :(得分:2)

如果您不介意线程的开销,请将搜索放在一个稍微有点工作的线程上,然后不时产生。

线程的优点是您不必以编程方式保存状态;系统会为你做。

你必须为此付出复杂的代价,因为搜索的结果会异步进入,你必须安排以某种方式得到它。此外,您可能需要设置100毫秒的计时器。很多代码。 :)

答案 2 :(得分:0)

最好的办法是在你可以轻松保存状态并稍后恢复的位置(你可以尝试使函数递归以便轻松找到最佳点)。

然后在那些点上,您可以选择保存状态或继续