formes normales ; lecture des formes normales ; écriture des formes normales ; inverse fonctionnel d'une permutation ; algorithme de Johnson ; parseur arithmétique
Retour à la page générale de La lettre de Caml.
let rec point_fixe tr x0 =
let rec aux x xx = if x = xx then x else aux xx (tr xx)
in
aux x0 (tr x0) ;;
let set_of_list =
let rec aux accu = function
| [] -> accu
| h :: t -> if mem h accu then aux accu t else aux (h :: accu) t
in
aux [] ;;
let remove_p prédicat =
let rec aux accu = function
| [] -> accu
| h :: t -> if prédicat h then (aux accu t) else aux (h :: accu) t
in aux [] ;;
type proposition = Var of int
| Non of proposition
| Implique of proposition * proposition
| Equivalent of proposition * proposition
| Ou of proposition * proposition
| Et of proposition * proposition ;;
let éliminer_implique =
let rec étape = function
| Var(n) -> Var(n)
| Non(t) -> Non(étape t)
| Implique(t1,t2) -> Ou(Non(étape t1),étape t2)
| Equivalent(t1,t2) -> Et( Ou(Non(étape t1),étape t2) ,
Ou(Non(étape t2),étape t1) )
| Ou(t1,t2) -> Ou(étape t1,étape t2)
| Et(t1,t2) -> Et(étape t1,étape t2)
in point_fixe étape ;;
let intérioriser_négation =
let rec étape = function
| Non(Et(t1,t2)) -> Ou(Non(étape t1),Non(étape t2))
| Non(Ou(t1,t2)) -> Et(Non(étape t1),Non(étape t2))
| Var(n) -> Var(n)
| Non(t) -> Non(étape t)
| Ou(t1,t2) -> Ou(étape t1,étape t2)
| Et(t1,t2) -> Et(étape t1,étape t2)
in point_fixe étape ;;
let exterioriser_conjonction =
let rec étape = function
| Ou(f,Et(g,h)) -> Et(Ou(étape f,étape g),Ou(étape f,étape h))
| Ou(Et(g,h),f) -> Et(Ou(étape g,étape f),Ou(étape h,étape f))
| Var(n) -> Var(n)
| Non(t) -> Non(étape t)
| Ou(t1,t2) -> Ou(étape t1,étape t2)
| Et(t1,t2) -> Et(étape t1,étape t2)
in point_fixe étape ;;
let exterioriser_disjonction =
let rec étape = function
| Et(f,Ou(g,h)) -> Ou(Et(étape f,étape g),Et(étape f,étape h))
| Et(Ou(g,h),f) -> Ou(Et(étape g,étape f),Et(étape h,étape f))
| Var(n) -> Var(n)
| Non(t) -> Non(étape t)
| Ou(t1,t2) -> Ou(étape t1,étape t2)
| Et(t1,t2) -> Et(étape t1,étape t2)
in point_fixe étape ;;
let fnc_vers_ll p =
let aplatir_et =
let rec aux l = function
| Et(a,b) -> (aux l a) @ (aux l b)
| a -> a :: l
in aux []
and aplatir_ou =
let rec aux l = function
| Ou(a,b) -> (aux l a) @ (aux l b)
| a -> a :: l
in aux []
in map aplatir_ou (aplatir_et p) ;;
let fnd_vers_ll p =
let aplatir_et =
let rec aux l = function
| Et(a,b) -> (aux l a) @ (aux l b)
| a -> a :: l
in aux []
and aplatir_ou =
let rec aux l = function
| Ou(a,b) -> (aux l a) @ (aux l b)
| a -> a :: l
in aux []
in map aplatir_et (aplatir_ou p) ;;
let éliminer_double_négation =
let élim =
let rec étape = function
| Var(n) -> Var(n)
| Non(Non(a)) -> (étape a)
| Non(a) -> Non(étape a)
in point_fixe étape
in map (map élim) ;;
let éliminer_a_non_a =
let inutile liste =
let négation = function
| Var(n) -> exists (function x -> x = Non(Var(n))) liste
| Non(Var(n)) -> exists (function x -> x = Var(n)) liste
in exists négation liste
in map (function x -> if (inutile x) then [] else x) ;;
let éliminer_variable_inutile = map set_of_list ;;
let éliminer_vide = remove_p (function [] -> true | _ -> false) ;;
let formeC t =
(éliminer_vide
(éliminer_a_non_a
(éliminer_variable_inutile
(éliminer_double_négation
(fnc_vers_ll
(fnc t)))))) ;;
let formeD t =
(éliminer_vide
(éliminer_a_non_a
(éliminer_variable_inutile
(éliminer_double_négation
(fnd_vers_ll
(fnd t)))))) ;;
type forme_normale = FNC of proposition list list
| FND of proposition list list ;;
let forme_normale_conjonctive s = FNC(formeC (parseur s))
and forme_normale_disjonctive s = FND(formeD (parseur s)) ;;
type lexème = Entier of int | Conjonction | Disjonction | Implication | Équivalence
| Négation | ParenthèseGauche | ParenthèseDroite ;;
let int_of_digit c = (int_of_char c) - (int_of_char `0`) ;;
let rec MangeEntier flot accu = match flot with
| [< '(`0`..`9` as c) >] -> MangeEntier flot (10*accu+(int_of_digit c))
| [< >] -> Entier(accu) ;;
let rec lexeur flot = match flot with
| [< '(` ` | `\r` | `\t` | `\n`) >] -> lexeur flot
| [< '`^` >] -> [< 'Conjonction ; (lexeur flot) >]
| [< '`|` >] -> [< 'Disjonction ; (lexeur flot) >]
| [< '`=`;'`>` >] -> [< 'Implication ; (lexeur flot) >]
| [< '`<`;'`=`;'`>` >] -> [< 'Équivalence ; (lexeur flot) >]
| [< '`-` >] -> [< 'Négation ; (lexeur flot) >]
| [< '`(` >] -> [< 'ParenthèseGauche ; (lexeur flot) >]
| [< '`)` >] -> [< 'ParenthèseDroite ; (lexeur flot) >]
| [< '(`0`..`9` as c) >]
-> [< '(MangeEntier flot (int_of_digit c)) ; (lexeur flot) >]
| [< >] -> [< >] ;;
exception Syntax_error ;;
let rec parseur_E flot = match flot with
| [< parseur_F f ; parseur_E' e' >]
-> match e' with
| [< 'Ou(_,e) >] -> Ou(f,e)
| [< >] -> f
| [< >] -> raise Syntax_error
and parseur_E' flot = match flot with
| [< 'Disjonction ; parseur_E e >] -> [< 'Ou(Var(0),e) >]
| [< >] -> [< >]
and parseur_F flot = match flot with
| [< parseur_G g ; parseur_F' f' >]
-> match f' with
| [< 'Et(_,e) >] -> Et(g,e)
| [< >] -> g
| [< >] -> raise Syntax_error
and parseur_F' flot = match flot with
| [< 'Conjonction ; parseur_F f >] -> [< 'Et(Var(0),f) >]
| [< >] -> [< >]
and parseur_G flot = match flot with
| [< parseur_H h ; parseur_G' g' >]
-> match g' with
| [< 'Implique(_,e) >] -> Implique(h,e)
| [< 'Equivalent(_,e) >] -> Equivalent(h,e)
| [< >] -> h
| [< >] -> raise Syntax_error
and parseur_G' flot = match flot with
| [< 'Implication ; parseur_G g >] -> [< 'Implique(Var(0),g) >]
| [< 'Équivalence ; parseur_G g >] -> [< 'Equivalent(Var(0),g) >]
| [< >] -> [< >]
and parseur_H flot = match flot with
| [< 'Négation ; parseur_I i >] -> Non(i)
| [< parseur_I i >] -> i
| [< >] -> raise Syntax_error
and parseur_I flot = match flot with
| [< 'ParenthèseGauche ; parseur_E e ; 'ParenthèseDroite >] -> e
| [< 'Entier(n) >] -> Var(n)
| [< >] -> raise Syntax_error ;;
let parseur s = parseur_E (lexeur (stream_of_string s)) ;;
#open "format" ;;
let print_variable = function
| Var(n) -> open_hbox () ;
print_char (char_of_int (n-1+(int_of_char `a`))) ;
close_box ()
| Non(Var (n)) -> open_hbox () ;
print_char `-` ;
print_char (char_of_int (n-1+(int_of_char `a`))) ;
close_box () ;;
let print_disjonction l =
let rec aux = function
| [] -> ()
| tête :: queue -> print_space () ;
print_char `|` ;
print_space () ;
print_variable tête ;
aux queue
in
open_hovbox 3 ;
match l with
| [] -> ()
| [x] -> print_variable x
| tête :: queue ->
print_char `(` ;
print_variable tête ; aux queue ;
print_char `)` ;
close_box () ;;
let print_conjonction l =
let rec aux = function
| [] -> ()
| tête :: queue -> print_space () ;
print_char `^` ;
print_space () ;
print_variable tête ;
aux queue
in
open_hovbox 3 ;
match l with
| [] -> ()
| [x] -> print_variable x
| tête :: queue ->
print_char `(` ;
print_variable tête ; aux queue ;
print_char `)` ;
close_box () ;;
let print_fnc ll =
let rec aux = function
| [] -> ()
| tête :: queue -> print_space () ;
print_char `^` ;
print_space () ;
print_disjonction tête ;
aux queue
in
open_hvbox 2 ;
match ll with
| [] -> ()
| [ l ] -> print_conjonction l
| tête :: queue -> print_break(2,0) ;
print_disjonction tête ;
aux queue ;
close_box () ;;
let print_fnd ll =
let rec aux = function
| [] -> ()
| tête :: queue -> print_space () ;
print_char `|` ;
print_space () ;
print_conjonction tête ;
aux queue
in
open_hvbox 2 ;
match ll with
| [] -> ()
| [ l ] -> print_conjonction l
| tête :: queue -> print_break(2,0) ;
print_conjonction tête ;
aux queue ;
close_box () ;;
let print_forme_normale = function
| FNC ll -> print_fnc ll
| FND ll -> print_fnd ll ;;
install_printer "print_forme_normale" ;;
(* deux définitions utiles *)
let id = function x -> x;;
let compose f g = function x-> f(g x);;
(* la transposition de p et q *)
let tau p q x = if x = p then q else if x = q then p else x ;;
(* la composition à gauche par icelle *)
let by_tau p q h = compose (tau p q) h ;;
(* tout est prêt, allons-y ! *)
let inverse f n =
let rec inv_rec f g n =
if n = 0 then g else
if n = f(n) then inv_rec f g (n-1)
else inv_rec (by_tau n (f n) f) (by_tau n (f n) g) (n-1)
in
inv_rec f id n ;;
(* on fait un essai pour voir *)
let f = function 1 -> 3 | 2 -> 5 | 3 -> 4 | 4 -> 1 | 5 -> 2 | 6 -> 6 | x -> x ;;
for k=1 to 6 do print_int(f(inverse f 6 k)) done ;;
exception Fin ;; type sens = Gauche | Droite ;; let valeur_de (_,n) = n and sens_de (s,_) = s ;; let voit table i = match sens_de table.(i) with | Gauche -> i-1 | Droite -> i+1 ;; let est_mobile table i = try valeur_de table.(voit table i) < valeur_de table.(i) with Invalid_argument(_) -> false ;; let inverse table i = match table.(i) with | Gauche,p -> table.(i) <- Droite,p | Droite,p -> table.(i) <- Gauche,p ;; let initialise n = let v = make_vect n (Gauche,0) in for i = 0 to n-1 do v.(i) <- (Gauche,i+1) done ; v ;; let avance table n = let rec cherche_max_mobile i indice_du_max = if i = n then if indice_du_max = (-1) then raise Fin else indice_du_max else if est_mobile table i && (indice_du_max = (-1) || valeur_de table.(i) > (valeur_de table.(indice_du_max))) then cherche_max_mobile (i+1) i else cherche_max_mobile (i+1) indice_du_max in let indice_du_max = cherche_max_mobile 0 (-1) in let le_max = table.(indice_du_max) and indice_vu = voit table indice_du_max in let vu = table.(indice_vu) in table.(indice_du_max) <- vu ; table.(indice_vu) <- le_max ; for i = 0 to n-1 do if (valeur_de table.(i)) > (valeur_de le_max) then inverse table i done ;; let affiche_permutation table n = for i = 0 to n-1 do print_int (valeur_de table.(i)) ; print_char ` ` done ; print_newline () ;; let affiche_les_permutations n = let table = initialise n in try while true do affiche_permutation table n ; avance table n done with Fin -> () ;; (*************************************************) let impair n = n mod 2 = 1 ;; let permutation n k = let table = make_vect n 0 in let rec installe d p saut = if table.(d) = 0 then if saut = 0 then table.(d) <- p else installe (d+1) p (saut-1) else installe (d+1) p saut in let rec place p k = let bloc = 1 + (k-1)/p and ligne = 1 + (k-1) mod p in installe 0 p (if impair bloc then p-ligne else ligne-1) ; if p>1 then place (p-1) bloc in place n k ; table ;;
exception Syntax_error ;;
let rec parseur_E pile flot =
let e = parseur_F [] flot
in
match flot with
| [< 'Plus >] -> parseur_E ((e,Plus) :: pile) flot
| [< 'Moins >] -> parseur_E ((e,Moins) :: pile) flot
| [< >] -> construit_E pile e
and construit_E pile e = match pile with
| [] -> e
| (f,op) :: queue -> match op with
| Plus -> Somme(construit_E queue f,e)
| Moins -> Différence(construit_E queue f,e)
and parseur_F pile flot =
let e = parseur_G flot
in
match flot with
| [< 'Multiplie >] -> parseur_F ((e,Multiplie) :: pile) flot
| [< 'Divise >] -> parseur_F ((e,Divise) :: pile) flot
| [< >] -> construit_F pile e
and construit_F pile e = match pile with
| [] -> e
| (f,op) :: queue -> match op with
| Multiplie -> Produit(construit_F queue f,e)
| Divise -> Quotient(construit_F queue f,e)
and parseur_G flot = match flot with
| [< parseur_H h ; parseur_G' g' >] -> match g' with
| [< 'Élévation(_,e) >] -> Élévation(h,e)
| [< >] -> h
| [< >] -> raise Syntax_error
and parseur_G' flot = match flot with
| [< 'Puissance ; parseur_G g >] -> [< 'Élévation(N(0),g) >]
| [< >] -> [< >]
and parseur_H flot = match flot with
| [< 'Moins ; parseur_I i >] -> Opposé(i)
| [< parseur_I i >] -> i
| [< >] -> raise Syntax_error
and parseur_I flot = match flot with
| [< 'ParenthèseGauche ; (parseur_E []) e ; 'ParenthèseDroite >] -> e
| [< 'Entier(n) >] -> N(n)
| [< >] -> raise Syntax_error ;;
let parseur s = parseur_E [] (lexeur (stream_of_string s)) ;;
Retour à la page générale de La lettre de Caml.