0

I understand that there are generally-accepted algorithms for reducing a given boolean-logic expression to CNF or DNF. I've found a few websites about this sorta thing, but nothing that I can really use to build a Haskell program around it.

This isn't homework, nor am I asking for someone to write me code - I'm just looking for some kind of resource that I can follow to help me build my functions.

It seems to me that I have to define a datatype Exp which deals with Or Exp Exp, And Exp Exp, etc., etc. and then build the standard 'rules' (De Morgan's, Modus Ponens, Modus Tollens, what have you) to use to repeatedly apply to to the Exp until I reach a point where I'm not getting any further.

(As I've been playing around with Agda etc., I've tended to write everything in Haskell before translating it to Agda. So yeah, if you're more familiar with expressing anything in Agda, then I'm going to understand that too.)

Allan
  • 149
  • 5
  • You have the right idea. If your `Exp` is only `And` or `Or` then you actually only need one of De Morgan's laws (on that choice depends whether you reach CNF or DNF). What exactly is your question? – Karolis Juodelė Jul 26 '14 at 15:58
  • If you add more operations, you'll only need to rewrite them with `and, or, not`. It doesn't really add complexity. Also, I confused something about the rules. You need both De Morgans. You need one distribution instead. – Karolis Juodelė Jul 26 '14 at 17:43
  • 1
    I'm not sure what description there is. You match each constructor, call your `toCNF` on the children and combine the results. Obviously, `toCNF (And a b) = And (toCNF a) (toCNF b)`. You also need to match `Not (And a b)` and `Not (Or a b)` for De Morgan. Matching `Or` is the most interesting part, of course, but it's just distribution. If you find this challenging, I suggest first writing a function which applies De Morgan until all negations are of literals. It's simpler, but basically the same. – Karolis Juodelė Jul 26 '14 at 18:19
  • You can try to implement e.g. [Tseitin transformation](http://en.wikipedia.org/wiki/Tseitin_transformation). There are plenty of websites explaining how it works. – aztek Aug 08 '14 at 12:16

1 Answers1

3

You can actually use the nice hatt package for it. It has API for converting to NNF, CNF etc. This is some sample code:

import Data.Logic.Propositional
import Data.Logic.Propositional.NormalForms

a = Variable (Var 'A')
b = Variable (Var 'B')
c = Variable (Var 'C')
d = Variable (Var 'D')

expression = Conjunction a (Disjunction b (Conjunction c d))

And then you can play up with the expression in ghci:

λ> expression
(A ∧ (B ∨ (C ∧ D)))
λ> toCNF expression
(A ∧ ((B ∨ C) ∧ (B ∨ D)))

I would suggest you to look on the source of the package as it's not very complicated.

Sibi
  • 47,472
  • 16
  • 95
  • 163