检查一个命题公式是否暗示另一个命题公式(在Haskell中)
假设我们有检查一个命题公式是否暗示另一个命题公式(在Haskell中),haskell,logic,Haskell,Logic,假设我们有 data Exp = Prop String -- a proposition | And Exp Exp -- a conjunction of propositions | Or Exp Exp -- a disjunction of propositions 那么,有没有办法确定一个嵌套表达式是否暗示另一个嵌套表达式?也就是说,我正在寻找以下内容: implies :: Exp -> Exp -> Bool implies =
data Exp = Prop String -- a proposition
| And Exp Exp -- a conjunction of propositions
| Or Exp Exp -- a disjunction of propositions
那么,有没有办法确定一个嵌套表达式是否暗示另一个嵌套表达式?也就是说,我正在寻找以下内容:
implies :: Exp -> Exp -> Bool
implies = {- returns true if and only if the first expression
implies the second expression -}
implies
(And (Prop "Apple") (Prop "Banana"))
(Or (Prop "Apple") (Prop "Banana"))
-- => True, since "Apple and Banana" implies "Apple or Banana"
implies
(Or (Prop "Apple") (Prop "Banana"))
(And (Prop "Apple") (Prop "Banana"))
-- => False, since "Apple or Banana" does not imply "Apple and Banana"
有没有一种方法可以实现这一点,或者有没有实现这一点的库?如果有区别的话:我只需要
和和或(也就是说,我不需要实质性的暗示)。这涉及到计算机科学中的一个关键问题。对于布尔变量的and和OR表达式,我们能否确定该表达式是否可满足?还是这个表达总是错误的
一个简单的算法是通过矛盾构造证明,然后迭代应用
例如,第一个问题相当于证明无效的APPLE&&BANANA&&NOT(APPLE | | BANANA)
。这个表达式相当于苹果和香蕉,而不是苹果和香蕉,这个表达式是无效的,所以我们可以得出这样的结论
类似地,第二个问题相当于证明无效的(APPLE | | BANANA)&&NOT(APPLE&&BANANA)
。这可分为四个表达式:APPLE&NOT APPLE
,APPLE&NOT BANANA
,BANANA&NOT APPLE
,BANANA&NOT BANANA
。可以证明第一个子表达式和最后一个子表达式无效,但其他子表达式无效。解析算法实现了它被卡住,因此蕴涵不成立
像这样解决公式是否有效问题的算法属于。布尔可满足性问题比您面临的问题更一般,解决该问题的包(如and)采用了比本文所述更复杂的算法,但您应该发现可以将表达式转换为可满足性问题。通常会要求您使用变量、and和OR创建一个与抽象数据类型相似的表达式。这两个包都会给出一个结果数据类型,告诉您表达式不可满足或可满足,下面是所有变量的内容。你的命题可以作为变量来实现,你已经知道它们的真值是真的。这涉及到计算机科学中的一个关键问题。对于布尔变量的and和OR表达式,我们能否确定该表达式是否可满足?还是这个表达总是错误的
一个简单的算法是通过矛盾构造证明,然后迭代应用
例如,第一个问题相当于证明无效的APPLE&&BANANA&&NOT(APPLE | | BANANA)
。这个表达式相当于苹果和香蕉,而不是苹果和香蕉,这个表达式是无效的,所以我们可以得出这样的结论
类似地,第二个问题相当于证明无效的(APPLE | | BANANA)&&NOT(APPLE&&BANANA)
。这可分为四个表达式:APPLE&NOT APPLE
,APPLE&NOT BANANA
,BANANA&NOT APPLE
,BANANA&NOT BANANA
。可以证明第一个子表达式和最后一个子表达式无效,但其他子表达式无效。解析算法实现了它被卡住,因此蕴涵不成立
像这样解决公式是否有效问题的算法属于。布尔可满足性问题比您面临的问题更一般,解决该问题的包(如and)采用了比本文所述更复杂的算法,但您应该发现可以将表达式转换为可满足性问题。通常会要求您使用变量、and和OR创建一个与抽象数据类型相似的表达式。这两个包都会给出一个结果数据类型,告诉您表达式不可满足或可满足,下面是所有变量的内容。你的命题可以作为变量来实现,你已经知道其真值为真。通常你会使用SAT解算器(如另一个答案中所指出的)但对于您的具体示例,您还可以利用这样一个事实:一组文字U
上的命题公式可以由U
的子集表示。这些“表示子集”是公式的模型
在您的示例中,U={Apple,Banana}
。表达式(苹果和香蕉)
仅由U
的单个子集表示,即由{Apple,Banana}
表示(苹果或香蕉)
另一方面有三种型号:{Apple}
,{Banana}
和{Apple,Banana}
如果命题p
在models(f)
中,则p
为真,否则为假。公式f和g
的模型是U
的子集,它们是f
和g
的模型。模型f或g
是属于f
模型或g
模型的任何集合
在Haskell中,这看起来像(如果我们添加导入限定数据。在顶部设置为S
):
最后,如果f
的每个模型也是g
的模型,则公式f
意味着公式g
:
implies :: Exp -> Exp -> Bool
implies f g = all isGModel fModels where
fModels = models f
gModels = models g
isGModel s = any ((==) s) gModels
请注意,这种方法效率很低,并且不能扩展到少数文字(因为模型是通过枚举所有文字的子集来计算的)。但是,从集合的角度来思考这个问题是很有教育意义的。通常你会使用SAT解算器(如另一个答案中所指出的),但对于你的具体例子,你也可以利用这样一个事实,即一组文字U
上的命题公式可以用U
的子集来表示。这些"代表",
implies :: Exp -> Exp -> Bool
implies f g = all isGModel fModels where
fModels = models f
gModels = models g
isGModel s = any ((==) s) gModels