Une base pour travailler en logique avec Haskell. Il restera en mini-projet à créer des fonctions de mise sous forme normale conjonctive et disjonctive...
Haskell
---- Last modified: <MD1_logique.hs modifié par Guillaume CONNAN le vendredi 6 septembre 2013 à 11h 43min 49s> import qualified Data.Map as Dic import qualified Data.Set as Set type Atome = Char type Environnement = Dic.Map Atome Bool data Formule = Antitruc |Atomic Atome |Non Formule |Et Formule Formule |Ou Formule Formule |Imp Formule Formule |Equiv Formule Formule deriving (Eq) -- Opérateurs infixes plus pratiques à utiliser µ x = Atomic x infixr 2 & x & y = Et x y infixr 2 § x § y = Ou x y infixr 1 ==> x ==> y = Imp x y infixr 1 <==> x <==> y = Equiv x y -- exemple de formule -- de_morg = Equiv (Non (Et (Atomic 'p') (Atomic 'q'))) (Ou (Non (Atomic 'p')) (Non (Atomic 'q'))) de_morg = Non ((µ 'p') & (µ 'q')) <==> (Non (µ 'p') § Non (µ 'q')) -- fonction sur les formules f :: Formule -> Formule -> Formule -> Formule -> Formule f p q r s = s ==> (p & (Non (q))) § (p <==> (Non r)) -- exemple d'environnement env1 = Dic.fromList[('p',True),('q',False)] -- évaluation récursive d'une formule sous un environnement eval :: Formule -> Environnement -> Bool eval Antitruc env = False eval (Atomic a) env = env Dic.! a eval (Non f) env = if (eval f env) then False else True eval (Et f g) env = if (eval f env) then (eval g env) else False eval (Ou f g) env = if (eval f env) then True else (eval g env) eval (Imp f g) env = eval (Non (f & (Non g))) env eval (Equiv f g) env = eval ((f & g) § ((Non f) & (Non g))) env -- renvoie l'ensemble des atomes présents dans une formule ens_atomes :: Formule -> Set.Set Atome ens_atomes Antitruc = Set.empty ens_atomes (Atomic a) = Set.singleton a ens_atomes (Non f) = ens_atomes f ens_atomes (Et f g) = Set.union (ens_atomes f ) (ens_atomes g ) ens_atomes (Ou f g) = Set.union (ens_atomes f ) (ens_atomes g ) ens_atomes (Imp f g) = Set.union (ens_atomes f ) (ens_atomes g ) ens_atomes (Equiv f g) = Set.union (ens_atomes f ) (ens_atomes g ) -- "dit" la formule comme on l'énonce habituellement dit :: Formule -> String dit Antitruc = "Antitruc" dit (Non Antitruc) = "Vrai" dit (Atomic a) = [a] dit (Non p) = "Non " ++ (dit p) dit (Et p q) = "( " ++ (dit p) ++ " et " ++ (dit q) ++ " )" dit (Ou p q) = "( " ++ (dit p) ++ " ou " ++ (dit q) ++ " )" dit (Imp p q) = "( " ++ (dit p) ++ " implique " ++ (dit q) ++ " )" dit (Equiv p q) = "( " ++ (dit p) ++ " equivaut a " ++ (dit q) ++ " )" instance Show Formule where show = dit -- renvoie la liste de tous les environnements de taille n -- on nomme les atomes dans l'ordre alpha à partir de ini tous_les_env :: Int -> Atome -> [Environnement] tous_les_env 0 ini = [Dic.empty] tous_les_env n ini = let insere v dic = Dic.insert ini v dic in (map (\d -> insere True d) (tous_les_env (n-1) (succ ini))) ++ (map (\d -> insere False d) (tous_les_env (n-1) (succ ini))) -- teste si une formule est une tautologie est_tautologie :: Formule -> Bool est_tautologie f = let ens = ens_atomes f in let ini = Set.findMin ens in let n = Set.size ens in and $ map (\env -> eval f env) (tous_les_env n ini) -- renvoie la table de vérité sous forme d'une liste de couples (envir, valeur) liste_verite :: Formule -> [([(Atome,Bool)],Bool)] liste_verite f = let ens = ens_atomes f in let ini = Set.findMin ens in let n = Set.size ens in map (\env -> (Dic.toList env,eval f env)) (tous_les_env n ini) -- joli (?) affichage de la table de vérité table_verite :: Formule -> IO () table_verite f = let lv = liste_verite f in let s = foldl (++) "" [(show (fst c)) ++ " --> " ++ (show (snd c)) ++ "\n" | c <- lv] in putStrLn s