DPLL算法定义

时间:2011-04-27 22:57:49

标签: algorithm artificial-intelligence

我在理解DPLL算法时遇到一些问题,我想知道是否有人可以向我解释,因为我认为我的理解是不正确的。

我理解它的方式是,我采用一些文字,如果某些每个子句都为真,则模型为真,但如果某个子句为假,则模型为假。

我通过查找一个单元子句来递归检查模型,如果有的话我设置了该单元子句的值使其成为真,然后更新模型。删除现在为true的所有子句并删除现在为false的所有文字。

当没有单位子句时,我选择了任何其他文字并为该文字指定值使其成立并使其成为假,然后再次删除现在为真的所有子句以及现在为假的所有文字。

2 个答案:

答案 0 :(得分:8)

DPLL要求以析取正常形式陈述问题,即作为一组条款,每一条都必须得到满足。

每个子句都是一组文字{l1, l2, ..., ln},表示这些文字的分离(即,要满足的子句必须至少有一个文字。)

每个文字l断言某些变量为真(x)或者为假(~x)。

如果子句中的任何文字都为真,那么该子句就满足了。

如果一个子句中的所有文字都是假的,那么该条款是不可满足的,因此问题是不可满足的。

解决方案是为变量分配true / false值,以便满足每个子句。 DPLL算法是对此类解决方案的优化搜索。

DPLL本质上是一种深度优先搜索,它在三种策略之间交替。在搜索的任何阶段都有部分分配(即,对某些变量子集赋值)和一组未决条款(即那些尚未满足的条款)。

(1)第一个策略是Pure Literal Elimination:如果未分配的变量x仅在未确定的子句中以正面形式出现(即,文字~x不会出现在任何地方)然后我们只需将x = true添加到我们的作业中,并满足包含文字x的所有子句(类似地,如果x仅以其否定形式出现~x,我们就可以只需将x = false添加到我们的作业中。

(2)第二种策略是单位传播:如果一个未定的条款中的一个文字都是假的,那么剩下的一个必须是真的。如果剩余的字面值为x,我们会将x = true添加到我们的作业中;如果剩余的字面值为~x,我们会在分配中添加x = false。这项任务可以为单位传播带来更多机会。

(3)第三种策略是简单地选择一个未分配的变量x并对搜索进行分支:一方尝试x = true,另一方尝试x = false

如果在任何时候我们最终得到一个不满意的条款,那么我们已经走到了死胡同并且不得不回溯。

有各种巧妙的进一步优化,但这是几乎所有SAT求解器的核心。

希望这有帮助。

答案 1 :(得分:1)

Davis-Putnam-Logemann-Loveland(DPLL)算法是一种基于回溯的搜索算法,用于确定命题逻辑公式在可称正态形式(也称为可满足性问题或SAT)中的可满足性。

任何布尔公式都可以用合取范式(CNF)表示,这意味着条款的连接,即(...)^(...)^(...)

其中一个子句是布尔变量的分离,即(A v B v C'v D)

在CNF中表示的布尔公式的示例是

(A v B v C)^(C'v D)^(D'v A)

并解决SAT问题意味着找到满足它的公式中变量的值组合,如A = 1,B = 0,C = 0,D = 0

这是NP-Complete问题。实际上这是第一个被Stepehn Cook和Leonid Levin证明是NP-Complete的问题

特定类型的SAT问题是3-SAT,它是一个SAT,其中所有子句都有三个变量。

DPLL算法是解决SAT问题(实际上取决于输入的硬度)的方法,递归地创建了一个潜在解决方案树

假设您想解决像这样的3-SAT问题

(A v B v C)^(C'v D v B)^(B v A'v C)^(C'v A'v B')

如果我们枚举像A = 1 B = 2 C = 3 D = 4这样的变量,并且对于A'= -1这样的否定变量是负数,那么可以用Python编写相同的公式

[[1,2,3],[ - 3,4,2],[2,-1,3],[ - 3,-1,-2]

现在想象创建一个树,其中每个节点都包含一个部分解决方案。在我们的例子中,我们还描述了解决方案满足的子句的向量

根节点是[-1,-1,-1,-1],这意味着尚未为变量分配0和1

每次迭代:

  1. 我们采用第一个不满意的条款

  2. 如果没有更多未分配的变量我们可以用来满足该子句,那么在搜索树的这个分支中就没有有效的解决方案,算法将返回无

  3. 否则我们取第一个未赋值变量并设置它使它满足该子句并从步骤1开始递归。如果算法的内部调用返回None,我们翻转变量的值,使其不满足该子句并设置下一个未分配的变量以满足该子句。如果已经尝试了所有三个变量或者该子句没有更多未分配的变量,则意味着该分支中没有有效的解决方案,算法将返回无

  4. 请参阅以下示例:

    从根节点我们选择第一个子句的第一个变量(A)(A v B v C)并设置它使得它满足条件,然后A = 1(搜索树的第二个节点)

    继续第二个子句,我们选择第一个未分配的变量(C)并设置它,使其满足C = 0的子句(左边的第三个节点)

    我们对第四个子句(B v A'v C)做同样的事情,并将B设置为1

    我们尝试对最后一个句子做同样的事情,我们意识到我们不再有未分配的变量,并且该子句总是假的。然后我们必须回溯到搜索树中的先前位置。我们更改了我们分配给B的值并将B设置为0.然后我们查找另一个可以满足第三个子句的未分配值,但是没有。然后我们必须再次回溯到第二个节点

    在那里,我们必须翻转第一个变量(C)的赋值,以便它不满足该子句并设置下一个未赋值变量(D)以满足它(即C = 1和D = 1 )。这也满足包含C的第三个子句。

    满足(C'v A'v B')的最后一个子句有一个未赋值的变量B,然后可以设置为0以满足该子句。

    enter image description here

    在此链接http://lowcoupling.com/post/72424308422/a-simple-3-sat-solver-using-dpll中,您还可以找到实现它的python代码