使用Haskell从公式中删除重言式

时间:2011-02-10 18:23:48

标签: haskell

好的,所以我将我的大问题分成了一小部分,我一次尝试一个。

我正在编写一个将从公式中删除重言式的函数。基本思想是,如果在一个子句中,找到一个文字及其否定,则意味着该子句将为真,无论最终分配的值如何对于那个命题变量。我的建议是创建一个函数来删除它,但是对于一个子句并将其映射到公式。当然,我必须在开头删除重复项。

module Algorithm where

import System.Random
import Data.Maybe
import Data.List

type Atom = String
type Literal = (Bool,Atom)
type Clause = [Literal]
type Formula = [Clause]
type Model = [(Atom, Bool)]
type Node = (Formula, ([Atom], Model))
removeTautologies :: Formula -> Formula
removeTautologies = map tC.map head.group.sort
  where rt ((vx, x) : (vy, y) : clauses) | x == y = rt rest
                                      | otherwise = (vx, x) : rt ((vy, y) : clauses)

现在我尝试给它一个公式时遇到问题(例如(A v B v -A)^(B v C v A))。考虑到这个例子,第一个子句包含文字A和-A。这意味着该子句将始终为true,在这种情况下,它可以简化整个集合(B v C v A)。但我得到以下

Loading package old-locale-1.0.0.2 ... linking ... done.
Loading package time-1.1.4 ... linking ... done.
Loading package random-1.0.0.2 ... linking ... done.
[[(True,"A"),(True,"B")*** Exception: Algorithm.hs:(165,11)-(166,83): Non-exhaustive patterns in function rt

我该怎么办?

1 个答案:

答案 0 :(得分:3)

考虑将[(True,"A"),(True,"B"),(False,"A")]传递给rt函数时会发生什么:

rt [(True,"A"),(True,"B"),(False,"A")] =
  = rt ((True,"A"):(True,"B"):[(False,"A")] =
    -- (vx,x) = (True,"A"), (vy,y) = (True,"B"), clauses = [(False, "A")]
  = (True, "A") : rt ((True,"B"):[(False, "A")] =
    -- (vx,x) = (True,"B"), (vy,y) = (False,"A"), clauses = []
  = (True, "A") : (True,"B") : rt (False, "A"):[] =
    -- (vx,x) = (True,"B"), (vy,y) = ???

在递归调用中,您逐渐将更短和更短的列表传递给rt。但是你没有方程来处理少于一个元素的列表!

你需要有这样一个等式。想想rt [(False, "A")]应该返回什么。我认为正确的答案是简单地返回[(False, "A")]

rt [(vx,x)] = [(vx,x)]

现在,你在考虑是否有空配方? “不,一个空洞的公式毫无意义!”

好吧,想想公式(A∨¬A)。这是一个重言式。如果你删除它,你会留下一个空配方!所以,一个空的公式确实有道理。这是最基本的重言式。

如果我们将空公式传递给rt会怎样?同样,rt []没有等式。在这种情况下,您无法删除任何其他内容。你必须像以前一样不受影响地返回它:

rt [] = []

如果您愿意,可以将这两个额外的方程组合成一个方程式:

rt ((vx, x) : (vy, y) : clauses) | -- ... blah blah
                                 | -- ... blah blah
rt x = x