-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTree.hs
111 lines (88 loc) · 3.38 KB
/
Tree.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
{-# LANGUAGE FlexibleInstances #-}
-- A Tableaux prover.
-- Nodes in the trees are lists of formulas with weights, together
-- with a rule that was applied to get the children.
module Logic.Propositional.Prove.Tree where
import Data.GraphViz
import Data.GraphViz.Types.Monadic
import Data.List
import Data.Maybe (isJust)
import Logic.Internal
import Logic.Propositional
data Tableaux = Node [WForm] RuleName [Tableaux] | End
deriving (Eq,Ord,Show)
type RuleName = String
type WForm = Either Form Form
collapse :: WForm -> Form
collapse (Left f) = f
collapse (Right f) = f
collapseList :: [Either Form Form] -> [Form]
collapseList = map collapse
leftsOf, rightsOf :: [WForm] -> [Form]
leftsOf wfs = [f | Left f <- wfs]
rightsOf wfs = [f | Right f <- wfs]
ppWForms :: [WForm] -> String
ppWForms wfs = show (leftsOf wfs) ++ " ; " ++ show (rightsOf wfs)
instance DispAble Tableaux where
toGraph = toGraph' "" where
toGraph' pref End =
node pref [shape PlainText, toLabel "✘"]
toGraph' pref (Node fs rule ts) = do
node pref [shape PlainText, toLabel $ show fs]
mapM_ (\(t,y') -> do
toGraph' (pref ++ show y' ++ ":") t
edge pref (pref ++ show y' ++ ":") [toLabel rule]
) (zip ts [(0::Integer)..])
-- Given a formula, is their an applicable rule?
-- If so, which one, and what formulas are the result?
simpleRule :: Form -> Maybe (RuleName, [[Form]])
-- Nothing to do:
simpleRule (At _) = Nothing
simpleRule (Neg (At _)) = Nothing
simpleRule Top = Nothing
simpleRule (Neg Top) = Nothing
-- Single-branch rules:
simpleRule (Neg (Neg f)) = Just ("¬¬", [ [f] ])
simpleRule (Neg (Imp f g)) = Just ("¬→", [ [f, Neg g] ])
simpleRule (Con f g) = Just ("&" , [ [f, g] ])
-- Splitting rules:
simpleRule (Imp f g) = Just ("→" , [ [ Neg f ], [ g] ])
simpleRule (Neg (Con f g)) = Just ("¬&", [ [ Neg f ], [Neg g] ])
usable :: WForm -> Bool
usable = isJust . simpleRule . collapse
weightOf :: WForm -> (Form -> WForm)
weightOf (Left _) = Left
weightOf (Right _) = Right
isClosedNode :: [Form] -> Bool
isClosedNode fs = bot `elem` fs || any (\f -> Neg f `elem` fs) fs
extend :: Tableaux -> Tableaux
extend End = End
extend (Node wfs "" []) = case (isClosedNode (collapseList wfs), filter usable wfs) of
(True,_ ) -> Node wfs "✘" [End]
(_ ,[] ) -> Node wfs "" []
(_ ,wf:_) -> Node wfs therule ts where
rest = delete wf wfs
Just (therule,results) = simpleRule (collapse wf)
ts = [ extend $ Node (nub . sort $ rest++newwfs) "" [] | newwfs <- map (map $ weightOf wf) results ]
extend (Node fs rule ts@(_:_)) = Node fs rule (map extend ts)
extend (Node _ rule@(_:_) []) = error $ "Rule '" ++ rule ++ "' applied but no successors!"
-- To prove f, start with ¬f.
startFor :: Form -> Tableaux
startFor f = Node [Left $ Neg f] "" []
isClosedTab :: Tableaux -> Bool
isClosedTab End = True
isClosedTab (Node _ _ ts) = ts /= [] && all isClosedTab ts
prove :: Form -> Tableaux
prove = extend . startFor
provable :: Form -> Bool
provable = isClosedTab . prove
-- | Prove and show the tableau.
proveSlideshow :: Form -> IO Bool
proveSlideshow f = do
let t = extend (startFor f)
disp t
return $ isClosedTab t
-- | Soundness and Completeness, to be used with QuickCheck.
soundness, completeness :: Form -> Bool
soundness f = provable f `implies` isValid f
completeness f = isValid f `implies` provable f