【发布时间】:2017-08-03 23:30:10
【问题描述】:
我正在实施 DPLL 算法来计算访问节点的数量。我设法实现了不计算访问节点的 DPLL,但我想不出任何解决计数问题的方法。主要问题是,当算法找到令人满意的估值并返回 True 时,递归从递归开始的那一刻起就向上滚动并返回计数器。在任何命令式语言中,我都会使用全局变量并在调用函数时立即递增它,但在 Haskell 中并非如此。
我在这里粘贴的代码并不代表我尝试解决计数问题,这只是我没有它的解决方案。我尝试使用 (True,Int) 之类的元组,但它总是从递归开始的那一刻起返回整数值。
这是我的实现,其中 (Node -> Variable) 是启发式函数,Sentence 是 CNF 中要满足的子句列表,[Variable] 是未分配的 Literals 列表,Model 只是一个真值评估。
dpll' :: (Node -> Variable) -> Sentence -> [Variable] -> Model -> Bool
dpll' heurFun sentence vars model
| satisfiesSentence model sentence = True
| falsifiesSentence model sentence = False
| otherwise = applyRecursion
where
applyRecursion
| pureSymbol /= Nothing = recurOnPureSymbol
| unitSymbol /= Nothing = recurOnUnitSymbol
| otherwise = recurUsingHeuristicFunction
where
pureSymbol = findPureSymbol vars sentence model
unitSymbol = findUnitClause sentence model
heurVar = heurFun (sentence,(vars,model))
recurOnPureSymbol =
dpll' heurFun sentence (vars \\ [getVar pureSymbol]) ((formAssignment pureSymbol):model)
recurOnUnitSymbol =
dpll' heurFun sentence (vars \\ [getVar unitSymbol]) ((formAssignment unitSymbol):model)
recurUsingHeuristicFunction = case vars of
(v:vs) -> (dpll' heurFun sentence (vars \\ [heurVar]) ((AS (heurVar,True)):model)
|| dpll' heurFun sentence (vars \\ [heurVar]) ((AS (heurVar,False)):model))
[] -> False
我非常感谢有关如何计算已访问节点的任何建议。谢谢。
编辑:
我可以使用的唯一库是 System.Random、Data.Maybe 和 Data.List。
编辑:
我尝试实现的一种可能的解决方案是使用元组 (Bool,Int) 作为 DPPL 函数的返回值。代码如下:
dpll'' :: (Node -> Variable) -> Sentence -> [Variable] -> Model -> Int -> (Bool,Int)
dpll'' heurFun sentence vars model counter
| satisfiesSentence model sentence = (True,counter)
| falsifiesSentence model sentence = (False,counter)
| otherwise = applyRecursion
where
applyRecursion
| pureSymbol /= Nothing = recurOnPureSymbol
| unitSymbol /= Nothing = recurOnUnitSymbol
| otherwise = recurUsingHeuristicFunction
where
pureSymbol = findPureSymbol vars sentence model
unitSymbol = findUnitClause sentence model
heurVar = heurFun (sentence,(vars,model))
recurOnPureSymbol =
dpll'' heurFun sentence (vars \\ [getVar pureSymbol]) ((formAssignment pureSymbol):model) (counter + 1)
recurOnUnitSymbol =
dpll'' heurFun sentence (vars \\ [getVar unitSymbol]) ((formAssignment unitSymbol):model) (counter + 1)
recurUsingHeuristicFunction = case vars of
(v:vs) -> ((fst $ dpll'' heurFun sentence (vars \\ [heurVar]) ((AS (heurVar,True)):model) (counter + 1))
|| (fst $ dpll'' heurFun sentence (vars \\ [heurVar]) ((AS (heurVar,False)):model) (counter + 1)),counter)
[] -> (False,counter)
这种方法的基本思想是在每次递归调用时递增计数器。但是,这种方法的问题是我不知道如何从 OR 语句中的递归调用中检索计数器。我什至不确定这在 Haskell 中是否可行。
【问题讨论】:
-
我还不确定我是否理解问题所在。 “从递归开始的那一刻起,它总是返回整数值”是什么意思?
-
在一种可能的解决方案中,我使用 (True,Int) 元组返回节点计数器。当 DPLL 函数到达 OR 语句并且在应用递归 n 次直到模型满足 Sentence 之后,函数在与初始 ORed 递归开始的相同级别评估 OR 语句,最终从该特定递归级别返回计数器。我希望你现在能理解这个问题。谢谢。
-
那么,您是在问如何在
v:vs的recurUsingHeuristicFunction的情况下合并从对dpll'的两次调用返回的两个Ints?如果是这样,为什么(+)不是合并它们的正确方法? -
如果您认为使用元组 (Bool,Int) 可以解决问题,那么可以。在我尝试解决它时,我基本上无法从 OR 语句中较低级别的递归中检索计数器值。
-
你应该包括一个 MWE:最小的完整的代码,展示你不喜欢的行为,以及如何运行它的描述,你期望发生什么,以及什么而是发生了。
标签: algorithm haskell recursion artificial-intelligence dpll