如何限制库里的搜索空间?

时间:2014-07-05 23:30:50

标签: logic-programming curry

以下是我在库里的第一个节目。它打印到达所需解决方案所需的一系列步骤(走过关闭的门)。

Evaluating expression: main
Done
(Just [Open,Walk,Close])

如何在寻找Impossible时终止它?我正在使用Kics2 0.3.1。

import List
import AllSolutions
import IO
import ReadShowTerm
import Constraint

data State = Opened | Closed | Outside | Done | Impossible
data Action = Open | Walk | Close

e Open Closed = Opened
e Walk Opened = Outside
e Close Outside = Done

solution target | foldl (flip e) Closed actions =:= target & length actions <: 4  = actions
   where actions free

main = do
  target <- getContents
  getOneValue (solution $ readTerm target) >>= print 

1 个答案:

答案 0 :(得分:0)

如果是Done,则使用getOneValue修剪搜索空间。也就是说,当找到第一个结果时,该函数不会为自由变量actions生成更多可能性。但是,当没有解决方案时,如Impossible的情况,使用getOneValue无法修剪搜索空间,因为它一直在寻找第一个解决方案。实际上,如果您搜索所有解决方案而不是仅搜索第一个解决方案,那么在找到解决方案之后,即使是另一个呼叫也不会终止。

要获得终止版本,您可以尝试以下solution的定义。

solution target | foldl (flip e) Closed (take 4 actions) =:= target = actions
   where actions free

这样,搜索空间实际上被修剪,因为take仅评估列表的前四个cons构造函数。相反,length导致对列表中所有构造函数的求值来计算长度。因为它评估整个列表,所以自由变量actions生成越来越多的列表,因为自由变量的非确定性可能性的生成是由自由变量的评估驱动的。

限制Curry程序的搜索空间可能非常困难,因为您必须推理评估。例如,如果使用peano数而不是原始整数,也可以获得终止程序。更准确地说,您可以使用Peano数字定义以下函数。

data Peano = Zero | Succ Peano

fourP :: Peano
fourP = Succ (Succ (Succ (Succ Zero)))

lengthP :: [a] -> Peano
lengthP [] = Zero
lengthP (_:xs) = Succ (lengthP xs)

lessP :: Peano -> Peano -> Success
lessP Zero     (Succ _) = success
lessP (Succ x) (Succ y) = lessP x y

通过这些功能,您可以获得如下的终止版本。

solution target | lessP (lengthP actions) fourP & foldl (flip e) Closed actions =:= target = actions
   where actions free

但是,请注意,您必须首先检查列表的长度,因为&在评估方面存在左偏差。也就是说,如果它的第一个参数失败,它就不会评估它的第二个参数。如果我们切换&的参数,则条件将首先检查操作列表是否产生状态Closed,然后检查其长度。也就是说,我们不再使用长度来修剪搜索空间。