packages feed

Proper (empty) → 0.1.0.0

raw patch · 8 files changed

+385/−0 lines, 8 filesdep +HUnitdep +basedep +containerssetup-changed

Dependencies added: HUnit, base, containers, parsec

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Dillon Huff++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Proper.cabal view
@@ -0,0 +1,32 @@+-- Initial Proper.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                Proper+version:             0.1.0.0+synopsis:	     An implementation of propositional logic in Haskell            +-- description:         +license:  		BSD3           +license-file:        LICENSE+-- author:              +-- maintainer:          +-- copyright:           +-- category:            +build-type:          Simple+cabal-version:       >=1.8++library+  hs-source-dirs:	src+  build-depends:	base==4.5.*, containers+  exposed-modules:	Proper.Sentence, Proper.CNF, Proper.Clause++executable Proper+  main-is:             Main.hs+  -- other-modules:       +  build-depends:       base ==4.5.*, containers, parsec+  hs-source-dirs:      src++executable Proper-tests+  main-is:             Main.hs+  -- other-modules:       +  build-depends:       base ==4.5.*, HUnit, containers, parsec+  hs-source-dirs:      test, src
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Main.hs view
@@ -0,0 +1,23 @@+module Main(main) where++import System.Environment+import Proper.Lexer+import Proper.Parser+import Proper.Sentence+import System.IO+import Proper.Utils++main :: IO ()+main = do+  (fileName:rest) <- getArgs+  fHandle <- openFile fileName ReadMode+  thmString <- hGetContents fHandle+  let thm = processTheoremFile thmString+  case thm of+    Failed errMsg -> putStrLn errMsg+    Succeeded t -> do+      putStr $ show t+      putStrLn $ "\n\nis " ++ (show $ checkTheorem t)+  +processTheoremFile thmFileContents =+  (toTokens thmFileContents >>= parseTheoremToks)
+ src/Proper/CNF.hs view
@@ -0,0 +1,52 @@+module Proper.CNF(+  CNF, cnf, mergeCNFFormulas,+  naiveSAT)+       where++import Data.Map as M+import Data.Set as S+import Proper.Clause+import Proper.Utils++type CNF = Set Clause+  +cnf :: [Clause] -> CNF+cnf clauses = S.fromList clauses++mergeCNFFormulas :: [CNF] -> CNF+mergeCNFFormulas formulas = S.foldl S.union S.empty (S.fromList formulas)++literals :: CNF -> Set Atom+literals formula = S.foldl S.union S.empty (S.map (S.map literal) formula)++naiveSAT :: CNF -> Bool+naiveSAT formula = nSat simplifiedFormula allLits+  where+    simplifiedFormula = unitClauseSimplify formula+    allLits = literals simplifiedFormula+    +nSat :: CNF -> Set Atom -> Bool+nSat formula lits = case S.member S.empty formula of+  True -> False+  False -> case S.size formula of+    0 -> True+    _ -> (nSat nextFormula nextLits) || (nSat nextFormulaNeg nextLits)+    where+      nextLit = S.findMin lits+      nextLits = S.delete nextLit lits+      unitClause = clause [nextLit]+      unitNegClause = clause [negation nextLit]+      nextFormula = unitClauseSimplify (S.insert unitClause formula)+      nextFormulaNeg = unitClauseSimplify (S.insert unitNegClause formula)++unitClauseSimplify :: CNF -> CNF+unitClauseSimplify formula = S.foldl removeUnitClause formula unitClauses+  where+    unitClauses = S.filter (\s -> S.size s == 1) formula++removeUnitClause :: CNF -> Clause -> CNF+removeUnitClause formula c = remainingClauses+  where+    elemC = S.findMin c+    removeNegC = S.map (S.delete (negation elemC)) formula+    remainingClauses = S.filter (\s -> (not $ S.member elemC s)) removeNegC
+ src/Proper/Clause.hs view
@@ -0,0 +1,31 @@+module Proper.Clause(+  Atom, negation, lit, nLit, literal,+  Clause, clause, concatClause) where++import Data.Set as S++import Proper.Utils++data Atom =+  Lit Name |+  NLit Name+  deriving (Eq, Ord, Show)+  +negation :: Atom -> Atom+negation (Lit n) = NLit n+negation (NLit n) = Lit n++literal :: Atom -> Atom+literal (Lit n) = Lit n+literal (NLit n) = Lit n++lit name = Lit name+nLit name = NLit name++type Clause = Set Atom++concatClause :: Clause -> Clause -> Clause+concatClause c1 c2 = S.union c1 c2++clause :: [Atom] -> Clause+clause atoms = S.fromList atoms
+ src/Proper/Sentence.hs view
@@ -0,0 +1,203 @@+module Proper.Sentence(+  Sentence, checkTheorem,+  neg, con, dis, val, bic, imp,+  truthAssignment,+  evalSentence,+  isValidByTruthTable,+  toCNF, theorem) where++import Data.Map as M++import Proper.Clause+import Proper.CNF+import Proper.Utils++data Sentence =+  Val Name              |+  Neg Sentence          |+  Con Sentence Sentence |+  Dis Sentence Sentence |+  Bic Sentence Sentence |+  Imp Sentence Sentence+  deriving (Eq, Ord)++instance Show Sentence where+  show = showSent+  +showSent :: Sentence -> String+showSent (Val name) = name+showSent (Neg s) = "~(" ++ show s ++ ")"+showSent (Con s1 s2) = "(" ++ show s1 ++ " & " ++ show s2 ++ ")"+showSent (Dis s1 s2) = "(" ++ show s1 ++ " | " ++ show s2 ++ ")"+showSent (Bic s1 s2) = "(" ++ show s1 ++ " <-> " ++ show s2 ++ ")"+showSent (Imp s1 s2) = "(" ++ show s1 ++ " -> " ++ show s2 ++ ")"+           +neg sent = Neg sent+con s1 s2 = Con s1 s2+dis s1 s2 = Dis s1 s2+bic s1 s2 = Bic s1 s2+imp s1 s2 = Imp s1 s2+val name = Val name++constants :: Sentence -> [Sentence]+constants (Val n) = [(Val n)]+constants (Neg s) = constants s+constants (Con s1 s2) = constants s1 ++ constants s2+constants (Dis s1 s2) = constants s1 ++ constants s2+constants (Bic s1 s2) = constants s1 ++ constants s2+constants (Imp s1 s2) = constants s1 ++ constants s2++type TruthAssignment = Map Sentence Bool++truthVal :: Sentence -> TruthAssignment -> Bool+truthVal s tt = case M.lookup s tt of+  Just val -> val+  Nothing -> error $ "Sentence not in truth table " ++ show s++truthAssignment :: [Name] -> [Bool] -> TruthAssignment+truthAssignment constNames constVals = M.fromList $ zip consts constVals+  where+    consts = Prelude.map val constNames++evalSentence :: TruthAssignment -> Sentence -> Bool+evalSentence a (Neg s) = not $ evalSentence a s+evalSentence a (Con s1 s2) = (evalSentence a s1) && (evalSentence a s2)+evalSentence a (Dis s1 s2) = (evalSentence a s1) || (evalSentence a s2)+evalSentence a (Imp s1 s2) = (not s1Eval) || s2Eval+  where+    s1Eval = evalSentence a s1+    s2Eval = evalSentence a s2+evalSentence a (Bic s1 s2) = (s1Eval && s2Eval) || ((not s1Eval) && (not s2Eval))+  where+    s1Eval = evalSentence a s1+    s2Eval = evalSentence a s2+evalSentence a constant = truthVal constant a+  +type TruthTable = [TruthAssignment]++containsSentence :: Sentence -> TruthTable -> Bool+containsSentence s [] = False+containsSentence s tt = M.member s (head tt)++truthTable :: [Sentence] -> TruthTable+truthTable sents = Prelude.foldl addSentence [] sents++addSentence :: TruthTable -> Sentence -> TruthTable+addSentence tt s = if (containsSentence s tt)+  then tt+  else addNewSentence tt s++addNewSentence :: TruthTable -> Sentence -> TruthTable+addNewSentence [] c@(Val n) = [truthAssignment [n] [True], truthAssignment [n] [False]]+addNewSentence tt c@(Val n) = ttFalse ++ ttTrue+ where+   ttFalse = Prelude.map (\ta -> M.insert c False ta) tt+   ttTrue = Prelude.map (\ta -> M.insert c True ta) tt+addNewSentence tt s = Prelude.map (addCompoundSentence s) tt++addCompoundSentence :: Sentence -> TruthAssignment -> TruthAssignment+addCompoundSentence s ta = insert s sval ta+  where+    sval = evalSentence ta s++truthTableForSentence :: Sentence -> TruthTable+truthTableForSentence s = truthTable $ (constants s) ++ [s]+                          +isValidByTruthTable :: Sentence -> Bool+isValidByTruthTable s = and sTruthVals+  where+    sTruthTable = truthTableForSentence s+    sTruthVals = Prelude.map (truthVal s) sTruthTable+    +-- Format conversion functions+toCNF :: Sentence -> CNF+toCNF = cnf .+        cnfClauses .+        distributeDisjunction .+        pushNegation .+        removeImplication .+        removeBiconditional++cnfClauses :: Sentence -> [Clause]+cnfClauses (Con s1 s2) = cnfClauses s1 ++ cnfClauses s2+cnfClauses s = [disjunctiveClause s]++disjunctiveClause :: Sentence -> Clause+disjunctiveClause (Dis s1 s2) = concatClause (disjunctiveClause s1) (disjunctiveClause s2)+disjunctiveClause (Val name) = clause [lit name]+disjunctiveClause (Neg (Val name)) = clause [nLit name]+disjunctiveClause s = error $ "Disjunctive clause contains " ++ show s++removeImplication :: Sentence -> Sentence+removeImplication (Neg s) = Neg $ removeImplication s+removeImplication (Con s1 s2) = Con (removeImplication s1) (removeImplication s2)+removeImplication (Dis s1 s2) = Dis (removeImplication s1) (removeImplication s2)+removeImplication (Imp s1 s2) = Dis (Neg p) q+  where+    p = removeImplication s1+    q = removeImplication s2+removeImplication s = s++removeBiconditional :: Sentence -> Sentence+removeBiconditional (Neg s) = Neg $ removeBiconditional s+removeBiconditional (Con s1 s2) = Con (removeBiconditional s1) (removeBiconditional s2)+removeBiconditional (Dis s1 s2) = Dis (removeBiconditional s1) (removeBiconditional s2)+removeBiconditional (Imp s1 s2) = Imp (removeBiconditional s1) (removeBiconditional s2)+removeBiconditional (Bic s1 s2) = Con noBic1 noBic2+  where+    noBic1 = Imp p q+    noBic2 = Imp q p+    p = removeBiconditional s1+    q = removeBiconditional s2+removeBiconditional (Val name) = (Val name)++pushNegation :: Sentence -> Sentence+pushNegation (Neg (Neg s)) = pushNegation s+pushNegation (Neg (Con s1 s2)) = Dis (pushNegation (Neg s1)) (pushNegation (Neg s2))+pushNegation (Neg (Dis s1 s2)) = Con (pushNegation (Neg s1)) (pushNegation (Neg s2))+pushNegation (Con s1 s2) = Con (pushNegation s1) (pushNegation s2)+pushNegation (Dis s1 s2) = Dis (pushNegation s1) (pushNegation s2)+pushNegation s = s++distributeDisjunction :: Sentence -> Sentence+distributeDisjunction (Con p q) = Con (distributeDisjunction p) (distributeDisjunction q)+distributeDisjunction (Dis p (Con q r)) = Con pdq pdr+ where+   pdq = distributeDisjunction $ Dis p q+   pdr = distributeDisjunction $ Dis p r+distributeDisjunction (Dis (Con p q) r) = Con pdr qdr+ where+   pdr = distributeDisjunction $ Dis p r+   qdr = distributeDisjunction $ Dis q r+distributeDisjunction (Dis p q) = case pd of+  (Con r s) -> distributeDisjunction (Dis pd qd)+  other -> case qd of+    (Con r s) -> distributeDisjunction (Dis pd qd)+    other -> Dis pd qd+  where+    pd = distributeDisjunction p+    qd = distributeDisjunction q+distributeDisjunction s = s++-- Theorem code+data Theorem = Thm [Sentence] Sentence+               deriving (Eq)+                        +instance Show Theorem where+  show = showThm+  +showThm :: Theorem -> String+showThm (Thm axioms hyp) = "THEOREM\n" ++ axiomStr ++ "\n|=\n\n" ++ hypString+  where+    axiomStr = Prelude.concat $ Prelude.map (\a -> (show a) ++ "\n") axioms+    hypString = show hyp++theorem :: [Sentence] -> Sentence -> Theorem+theorem axioms hypothesis = Thm axioms hypothesis++checkTheorem :: Theorem -> Bool+checkTheorem (Thm axioms hypothesis) = not $ naiveSAT cnfFormNegThm+  where+    cnfAxioms = Prelude.map toCNF axioms+    cnfNotHypothesis = toCNF (neg hypothesis)+    cnfFormNegThm = mergeCNFFormulas (cnfNotHypothesis:cnfAxioms)
+ test/Main.hs view
@@ -0,0 +1,12 @@+module Main(main) where++import Proper.CNFTests+import Proper.LexerTests+import Proper.ParserTests+import Proper.SentenceTests++main = do+  allSentenceTests+  allCNFTests+  allLexerTests+  allParserTests