Arborescence et satisabilité TD 2
On dénit le type expression pour représenter des expressions logiques contenant des constantes, des variables logiques et des opérateurs logiques : Et, Ou, Non,⇒ , ⇔, Xor et Nor.
type constante = Vrai | Faux;;
type expression =
| Const of constante
| Var of string
| Et of expression * expression
| Ou of expression * expression
| Non of expression
| Implique of expression * expression
| Equiv of expression * expression
| Xor of expression * expression (* le ou exclusif *)
;;
On peut ainsi considérer l'expression :
let expr1 = Implique(Var "a",Equiv(Const Vrai,Var "b"));;
Exercice 1 : Écrire une fonction transforme qui transforme toute expression du type précé- dent en une expression ne contenant que les opérateurs logiques : Et, Ou et Non.
transforme : expression -> expression Correction
La fonction transforme est récursive, la terminaison est assurée pour la constante ou la variable.
Pour l'implication, on utilise : (a⇒b)≡ ¬a∨b.
Pour l'équivalence, on utilise : (a⇔b)≡(a∧b)∨(¬a∧ ¬b).
Pour le Xor, on utilise : (aL
b)≡(a∧ ¬b)∨(¬a∧b). Listing 1 la fonctiontransforme
let rec transforme exp = match exp with
| Const(c) -> exp
| Var(s) -> exp
| Et ( e1 , e2 ) -> Et(transforme(e1) , transforme(e2))
| Ou ( e1 , e2 ) -> Ou(transforme(e1) , transforme(e2))
| Non(e)-> Non(transforme(e))
| Implique(e1,e2) -> Ou (Non ( transforme(e1)) , transforme(e2))
| Equiv(e1,e2) -> let a = transforme e1 and b = transforme e2 in Ou(Et(a,b),Et(Non(a),Non(b)))
| Xor(e1,e2) -> let a = transforme e1 and b = transforme e2 in Ou(Et(a,Non(b)),Et(Non(a),b))
;;
Exercice 2 : Écrire une fonction simplifiequi simplie une expression de contenant comme
simplifie : expression -> expression Correction
Pour simplier, on applique quelques règles ( la liste est non exhaustive...) de simplication.
On réitère la simplication tant que l'expression est simpliable.
Listing 2 la fonction simplifie
let rec simplifie_trans exp = match exp with
| Const(c) -> exp
| Var(s) -> exp
| Non(Const(Vrai))-> Const(Faux)
| Non(Const(Faux)) -> Const(Vrai)
| Et ( e_1 , Const(Vrai)) -> simplifie_trans(e_1)
| Et ( Const(Vrai),e_1) -> simplifie_trans(e_1)
| Et ( e_1 , Const(Faux)) -> Const(Faux)
| Et ( Const(Faux),e_1) -> Const(Faux)
| Ou ( e_1 , Const(Vrai)) -> Const(Vrai)
| Ou( Const(Vrai),e_1) -> Const(Vrai)
| Ou ( e_1 , Const(Faux)) -> simplifie_trans(e_1)
| Ou ( Const(Faux),e_1) -> simplifie_trans(e_1)
| Non(e_1) -> Non(simplifie_trans(e_1))
| Et(e_1,e_2) -> Et(simplifie_trans(e_1) , simplifie_trans(e_2))
| Ou(e_1,e_2) -> Ou(simplifie_trans(e_1) , simplifie_trans(e_2))
| _ -> exp;;
let rec simpl exp = let exp_2 = simplifie_trans exp in if exp_2 = exp then exp else simpl exp_2;;
let simplifie exp = simpl( transforme exp);;
simplifie(expr1);;
Exercice 3 : Écrire la fonction liste_varqui prend en argument une expression, et renvoie la liste des variables dans l'expression, sans répétition.
liste_var : expression -> string list Correction
La fonction fusion est là pour l'union de listes triées ( car chaque création de liste est triée, car elle ne contient qu'un seul élément).
Listing 3 la fonction simplifie
let rec fusion l_1 l_2 =match (l_1,l_2) with
| ([],l_2) -> l_2
| (l_1,[]) -> l_1
| ((a_1::reste_1),(a_2::reste_2)) ->
if a_1 < a_2 then a_1::(fusion reste_1 l_2) elseif a_2 < a_1 then a_2::(fusion l_1 reste_2) else a_1::(fusion reste_1 reste_2);;
let rec liste_var exp = match exp with
| Const(c) -> []
| Var(s) -> [s]
| Et ( e1 , e2 ) -> fusion (liste_var e1) (liste_var e2)
| Ou ( e1 , e2 ) -> fusion(liste_var e1) (liste_var e2)
| Non(e)-> liste_var e;;
Exercice 4 : Ecrire la fonction eval_affect qui prend en argument une expression et une aectation, qui est une liste de couples variable, valeur. La fonction renvoie alors la valeur associée à cette aectation.
eval_affect : expression -> (string * bool) list -> bool Exemple :
eval_affect (transforme expr1) [("a" , true) ; ("b" , false)];;
- : bool = false Correction
On écrit d'abord la fonction association qui permet de renvoyer le second élément d'un couple.
Listing 4 la fonctioneval_affect
let rec association v liste = match liste with
|[] -> failwith " Erreur d'affectation"
|(variable, booleen)::reste when variable = v -> booleen
|(variable, booleen)::reste ->association v reste;;
let rec eval_affect exp liste_affect = match exp with
| Const(Vrai) -> true
| Const(Faux) -> false
| Var(s) -> association s liste_affect
| Non(e_1) -> not ( eval_affect e_1 liste_affect)
| Et(e_1,e_2) -> ( eval_affect e_1 liste_affect) && ( eval_affect e_2 liste_affect)
| Ou(e_1,e_2) -> ( eval_affect e_1 liste_affect) || ( eval_affect e_2 liste_affect);;
Exercice 5 :
1. Écrire la fonction distribue qui prend en argument un élément et une liste de liste et distribue l'élément à toutes les listes.
distribue : 'a -> 'a list list -> 'a list list
Exemple :
distribue 12 [ [1;5;6];[3;1] ; []];;
- : int list list = [[12; 1; 5; 6]; [12; 3; 1]; [12]]
Correction
Listing 5 la fonction distribue
let rec distribue a liste = match liste with
| [] -> []
| l_1::reste -> (a::l_1):: (distribue a reste );;
2. Écrire la fonctionaffectation_listequi prend en argument une liste et renvoie la liste des couples correspondants aux aectations.
affectation_liste : 'a list -> ('a * bool) list list Exemple :
affectation_liste ["a" ; "b" ];;
- : (string * bool) list list =
[[("a", true); ("b", true)]; [("a", true); ("b", false)];
[("a", false); ("b", true)]; [("a", false); ("b", false)]]
Correction
Listing 6 la fonctionaffectation_list
let rec affectation_liste liste_var = match liste_var with
| [] -> [[]]
| element::reste -> let l_reste = affectation_liste reste in
(distribue (element, true) l_reste)@ (distribue (element, false) l_reste);;
3. En déduire la fonction affectation qui prend en argument une expression logique, et renvoie la liste des aectations pour les variables de l'expression.
affectation : expression -> (string * bool) list list Exemple :
affectation expr1;;
- : (string * bool) list list =
[[("a", true); ("b", true)]; [("a", true); ("b", false)];
[("a", false); ("b", true)]; [("a", false); ("b", false)]]
Correction
Listing 7 la fonctionaffectation
let rec affectation exp =
let l = liste_var (transforme exp) in affectation_liste l;;
Exercice 6 : Écrire la fonction est_une_tautologie qui en argument une expression lo- gique, et renvoie le booléen correspondant au fait que l'expression est une tautologie.
est_une_tautologie : expression -> bool
Exemple : ((r ⇒ s)∧(s ⇒ t)) ⇒ (r ⇒ t) est une tautologie (principe de transitivité de l'implication).
tauto : expression =
Implique (Et (Implique (Var "r", Var "s"), Implique (Var "s", Var "t")), Implique (Var "r", Var "t"))
est_une_tautologie tauto ;;
- : bool = true Correction
Listing 8 la fonction est_une_tautologie
let est_une_tautologie exp = let affect = affectation exp in
let rec aux liste_affect = match liste_affect with
| [] -> true
| l::reste when (eval_affect (transforme exp) l) -> aux reste
| _ -> false in aux affect;;
Exercice 7 : Écrire la fonction liste_satisfiablequi en argument une expression logique, et renvoie la liste des aections pour lesquelles l'expression est satisfaite.
liste_satisfiable : expression -> (string * bool) list list Correction
Listing 9 la fonction liste_satisfiable
let liste_satisfiable exp =
let affect = affectation exp in
let rec aux liste_affect = match liste_affect with
| [] -> []
| l::reste when (eval_affect (transforme exp) l) -> l::(aux reste)
| l::reste -> aux reste in aux affect;;
Exercice 8 : Trois étudiants déjeunent ensemble à midi : Amine, Bertrand, Claire. Les habi- tudes font que :
si Amine prend un dessert, Bertrand aussi ;
soit Bertrand, soit Claire prennent un dessert, mais pas les deux ;
Amine ou Claire prend un dessert ;
si Claire prend un dessert, Amine aussi.
Trouve la combinaison satisfaisant à la problématique.
let probleme = Et( Et(Implique(Var("A" ),Var("B")), Xor(Var("B"),Var("C"))) , Et(Ou(Var("A"),Var("C")) ,Implique(Var("C"),Var("A")) ));;
liste_satisfiable probleme;;