2025-06-15 04:25:00 +03:00
|
|
|
module Ternary.Vee (isObvious, hasContradiction, newFact, cleared, think) where
|
|
|
|
|
|
|
|
|
|
import Data.Foldable (concatMap)
|
|
|
|
|
import Data.List
|
|
|
|
|
( elem,
|
|
|
|
|
filter,
|
|
|
|
|
head,
|
|
|
|
|
intersect,
|
|
|
|
|
iterate,
|
|
|
|
|
length,
|
|
|
|
|
nub,
|
|
|
|
|
null,
|
|
|
|
|
union,
|
|
|
|
|
(\\),
|
|
|
|
|
)
|
|
|
|
|
import Data.Maybe (Maybe (Nothing), mapMaybe)
|
|
|
|
|
import GHC.Base ((<), (>))
|
|
|
|
|
import GHC.Maybe (Maybe (..))
|
|
|
|
|
import Ternary.Term (Item (..), Term (..), Vee)
|
|
|
|
|
import Prelude
|
|
|
|
|
( Bool (False, True),
|
|
|
|
|
Eq,
|
|
|
|
|
any,
|
|
|
|
|
foldr,
|
|
|
|
|
fst,
|
|
|
|
|
map,
|
|
|
|
|
not,
|
|
|
|
|
notElem,
|
|
|
|
|
otherwise,
|
|
|
|
|
return,
|
|
|
|
|
snd,
|
|
|
|
|
($),
|
|
|
|
|
(&&),
|
|
|
|
|
(.),
|
|
|
|
|
(/=),
|
|
|
|
|
(<$>),
|
|
|
|
|
(<*>),
|
|
|
|
|
(=<<),
|
|
|
|
|
(==),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Knowledge a = [Vee a]
|
|
|
|
|
|
|
|
|
|
type InferenceRule a = Vee a -> Vee a -> (Knowledge a, Maybe (Vee a))
|
|
|
|
|
|
2025-01-10 20:51:21 +03:00
|
|
|
isSubsetOf :: (Eq a) => [a] -> [a] -> Bool
|
|
|
|
|
a `isSubsetOf` b = nda && not ndb
|
2025-06-15 04:25:00 +03:00
|
|
|
where
|
|
|
|
|
nda = null $ a \\ b
|
|
|
|
|
ndb = null $ b \\ a
|
2025-01-10 20:51:21 +03:00
|
|
|
|
|
|
|
|
isObvious :: (Eq a) => Vee a -> Vee a -> Bool
|
|
|
|
|
isObvious (Term x (Item a)) (Term y (Item b))
|
2025-06-15 04:25:00 +03:00
|
|
|
| x /= y = False
|
|
|
|
|
| x = a `isSubsetOf` b
|
|
|
|
|
| not x = b `isSubsetOf` a
|
|
|
|
|
|
|
|
|
|
hasContradiction :: (Eq a) => Vee a -> Vee a -> Bool
|
|
|
|
|
hasContradiction (Term x (Item a)) (Term y (Item b))
|
|
|
|
|
| a == b && x /= y = True
|
|
|
|
|
| a `isSubsetOf` b && x < y = True
|
|
|
|
|
| b `isSubsetOf` a && x > y = True
|
|
|
|
|
| otherwise = False
|
2025-01-10 20:51:21 +03:00
|
|
|
|
2025-06-15 04:25:00 +03:00
|
|
|
notT :: Term a -> Term a
|
|
|
|
|
notT (Term x v) = Term (not x) v
|
|
|
|
|
|
|
|
|
|
rulePosFromNeg :: (Eq a) => InferenceRule a
|
|
|
|
|
rulePosFromNeg (Term False (Item negSet)) positive@(Term True (Item posSet))
|
|
|
|
|
| length diff /= 1 = ([], Nothing)
|
|
|
|
|
| missing `elem` posSet = ([], Nothing)
|
|
|
|
|
| otherwise = ([positive], Just (Term True (Item (missing : posSet))))
|
|
|
|
|
where
|
|
|
|
|
diff = negSet \\ posSet
|
|
|
|
|
missing = notT (head diff)
|
|
|
|
|
|
|
|
|
|
ruleNegFromNeg :: (Eq a) => InferenceRule a
|
|
|
|
|
ruleNegFromNeg (Term False (Item i0)) (Term False (Item i1))
|
|
|
|
|
| length evidence /= 1 = ([], Nothing)
|
|
|
|
|
| null diff0 && null diff1 = (map (Term False . Item) [i0, i1], Just (Term False (Item result)))
|
|
|
|
|
| otherwise = ([], Just (Term False (Item result)))
|
|
|
|
|
where
|
|
|
|
|
evidence = map notT i0 `intersect` i1
|
|
|
|
|
diff0 = (i0 \\ i1) \\ map notT evidence
|
|
|
|
|
diff1 = (i1 \\ i0) \\ evidence
|
|
|
|
|
result = (i0 `intersect` i1) `union` diff0 `union` diff1
|
|
|
|
|
|
|
|
|
|
newFact :: (Eq a) => InferenceRule a
|
2025-01-10 20:51:21 +03:00
|
|
|
newFact a@(Term True _) b@(Term False _) = newFact b a
|
2025-06-15 04:25:00 +03:00
|
|
|
newFact a@(Term False _) b@(Term True _) = rulePosFromNeg a b
|
|
|
|
|
newFact a@(Term False _) b@(Term False _) = ruleNegFromNeg a b
|
2025-01-10 20:51:21 +03:00
|
|
|
newFact _ _ = ([], Nothing)
|
|
|
|
|
|
2025-06-15 04:25:00 +03:00
|
|
|
next :: (Eq a) => (Knowledge a, Knowledge a) -> (Knowledge a, Knowledge a)
|
|
|
|
|
next (old, new) = (old `union` new \\ used, added)
|
|
|
|
|
where
|
|
|
|
|
results = [newFact o n | o <- old, n <- new]
|
|
|
|
|
used = concatMap fst results
|
|
|
|
|
added = mapMaybe snd results
|
2025-01-10 20:51:21 +03:00
|
|
|
|
2025-06-15 04:25:00 +03:00
|
|
|
applyFacts :: (Eq a) => Knowledge a -> Knowledge a -> Knowledge a
|
|
|
|
|
applyFacts old new =
|
|
|
|
|
fst . head . dropStable $ iterate next (old, new)
|
|
|
|
|
where
|
|
|
|
|
dropStable (x : y : xs)
|
|
|
|
|
| x == y = [x]
|
|
|
|
|
| otherwise = dropStable (y : xs)
|
|
|
|
|
dropStable _ = []
|
2025-01-10 20:51:21 +03:00
|
|
|
|
2025-06-15 04:25:00 +03:00
|
|
|
cleared :: (Eq a) => Knowledge a -> Knowledge a
|
|
|
|
|
cleared vees = nub $ filter (not . isRedundant) vees
|
|
|
|
|
where
|
|
|
|
|
isRedundant v = any (isObvious v) vees
|
2025-01-10 20:51:21 +03:00
|
|
|
|
2025-06-15 04:25:00 +03:00
|
|
|
think :: (Eq a) => (Knowledge a -> Knowledge a) -> Knowledge a -> Knowledge a
|
|
|
|
|
think addition = foldr (applyFacts . withUni . return) []
|
|
|
|
|
where
|
2025-01-10 20:51:21 +03:00
|
|
|
withUni vees = applyFacts (addition vees) vees
|