我正在实现DPLL算法来计算访问节点的数量。我设法实现了不计算访问节点的DPLL,但我想不出任何计算问题的解决方案。主要的问题是,当算法找到满意的评估并返回True时,递归从递归开始的那一刻开始卷起并返回计数器。在任何命令式语言中,我只会使用全局变量并在函数调用后尽快增加它,但在Haskell中并非如此。DPLL算法和访问节点数
我粘贴在这里的代码并不代表我试图解决计数问题,它只是我没有它的解决方案。我尝试使用诸如(True,Int)的元组,但它始终会在递归开始时返回整数值。
这是我的实现其中(节点 - >变量)是一个启发式函数,Sentence是CNF中的子句列表以满足,[变量]是未分配的文字列表,模型只是一个真值计算。
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次之后,直到模型满足句子,函数将评估OR语句与初始ORed递归相同的级别,最终从该递归的特定级别返回计数器。我希望你现在能够理解这个问题。谢谢。 – jdet
那么,你是问如何在'recurUsingHeuristicFunction'的'v:vs'情况下将两次调用返回的'Int'合并到'dpll''?如果是这样,为什么“(+)”不是合并它们的正确方法? –