简体   繁体   中英

Checking if One Propositional Formula Implies Another (in Haskell)

Suppose we have

data Exp = Prop String -- a proposition
         | And Exp Exp -- a conjunction of propositions
         | Or Exp Exp  -- a disjunction of propositions

Then is there a way to see if one nested expression implies another one? That is, I'm looking for something like the following:

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"

Is there a way to implement this, or is there some library that implements this? If it makes a difference: I only need And and Or (ie, I don't need material implication).

Normally you would use a SAT solver (as pointed out in the other answer) but for your specific example you could also exploit the fact that propositional formulae over a set of literals U can be represented by subsets of U . These "representing subsets" are the models of a formula.

In your example, U = { Apple, Banana } . The expression (Apple AND Banana) is only represented by a single subset of U , namely by { Apple, Banana } . (Apple OR Banana) on the other hand has three models: { Apple } , { Banana } and { Apple, Banana } .

If a proposition p is in models(f) then p is true, otherwise it is false. The models for a formula f AND g are those subsets of U that are models of f and of g . A model f OR g is any set that is a model of f or a model of g .

In Haskell this looks like (if we add import qualified Data.Set as S at the top):

-- The powerset of `U = {Apple, Banana}`
u = [S.empty, S.singleton "Apple", S.singleton "Banana", S.fromList ["Apple", "Banana"]]

isModelOf :: S.Set String -> Exp -> Bool
isModelOf s = any ((==) s) . models

models :: Exp -> [S.Set String]
models e = case e of
  Prop s -> filter (s `S.member`) u
  And l r -> filter (flip isModelOf r) $ models l
  Or l r -> models l ++ models r

Finally, a formula f implies a formula g if every model of f is also a model of g :

implies :: Exp -> Exp -> Bool
implies f g = all isGModel fModels where
  fModels = models f
  gModels = models g
  isGModel s = any ((==) s) gModels

Please note that this approach is highly inefficient and does not scale beyond a small number of literals (because models are computed by enumerating subsets of all literals). But it can be educational to think about the problem in terms of sets.

This touches on one of the keystone problems in computer science. For an expression of ANDs and ORs of boolean variables, can we determine whether the expression is satisfiable? Or is the expression always false?

A simple algorithm is to construct a proof by contradiction and then iteratively applying resolution .

For example, the first problem is equivalent to proving invalid APPLE && BANANA && NOT (APPLE || BANANA) . Well, that expression is equivalent to APPLE && BANANA && NOT APPLE && NOT BANANA and that expression is invalid so we can conclude that the implication holds.

Similarly the second problem is equivalent to proving invalid (APPLE || BANANA) && NOT (APPLE && BANANA) . This splits into four expressions: APPLE && NOT APPLE , APPLE && NOT BANANA , BANANA && NOT APPLE , BANANA & NOT BANANA . The first and the last subexpressions can be proven invalid but the others cannot. The resolution algorithm realizes it is stuck and so the implication does not hold.

Algorithms like this one that tackle the question of whether formulas are valid fall under the heading of SAT solvers . The boolean satisfiability problem is more general than the problem you are facing, and the packages for tackling it (such as incremental-sat-solver on Hackage and funsat on Hackage ) employ a more sophisticated algorithm than outlined here, but you should find it possible to translate your expression to a satisfiability problem. Generally you will be asked to create one expression that is not unlike your abstract data type, using variables and ANDs and ORs. Both packages will spit out a result data type telling you that either the expression is unsatisfiable or that it is satisfiable and here are what all the variables should be. Your propositions can be implemented as variables whose truth values you already know to be true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM