Consignes

Lisez attentivement chaque question. Repondez de maniere concise. Les questions sont independantes : traitez-les dans l'ordre de votre choix.

QuestionPointsSujet
Q1 — Lambda-calcul4 ptsCodage de Church
Q2 — OCaml : listes5 ptsFold, map, filter
Q3 — OCaml : types4 ptsTypes algebriques, pattern matching
Q4 — Coq : logique4 ptsPreuves propositionnelles
Q5 — Coq : induction3 ptsPreuve par induction

Question 1 — Lambda-calcul et codage de Church [4 pts]

On considere le lambda-calcul non type avec ses deux constructions : l'abstraction (λx. M) et l'application (M N). Le codage de Church encode les entiers naturels et les operations arithmetiques dans ce formalisme.

1.1 Fonction successeur [1 pt]

Donnez le terme du lambda-calcul pour la fonction successeur : une fonction qui, appliquee a un entier de Church ‹n›, retourne ‹n+1›. Montrez qu'elle est correcte en l'appliquant a ‹0› et en montrant que le resultat est bien ‹1›.

1.2 Entiers de Church [1 pt]

Donnez le terme du lambda-calcul pour la constante zero ‹0› et pour ‹1›, puis verifiez que succ ‹0› se reduit bien vers ‹1›.

1.3 Addition de Church [1 pt]

En vous basant sur le mecanisme du codage de Church, donnez le terme du lambda-calcul pour l'addition de deux entiers de Church. Expliquez en une phrase comment cette addition fonctionne.

1.4 Multiplication de Church [1 pt]

Donnez le terme du lambda-calcul pour la multiplication de deux entiers de Church. Expliquez en une phrase pourquoi la multiplication « repose » sur l'addition.

1.1 Fonction successeur

Reponse
succ = λn.λf.λx. f (n f x)

Verification avec 0 :
succ 0 = (λn.λf.λx. f (n f x)) 0
       →_β λf.λx. f (0 f x)
Or 0 f x = (λg.λy. y) f x →_β (λy. y) x →_β x
Donc succ 0 →_β λf.λx. f x = 1  ✓
Pointage
  • Terme correct + verification avec 0 : 1 pt
  • Terme correct sans verification : 0.75 pt
  • Verification correcte mais terme incorrect : 0.25 pt

1.2 Entiers de Church

Reponse
0 = λf.λx. x
1 = λf.λx. f x

Verification :
succ 0 = (λn.λf.λx. f (n f x)) (λf.λx. x)
       →_β λf.λx. f ((λf.λx. x) f x)
       →_β λf.λx. f ((λx. x) x)
       →_β λf.λx. f x = 1  ✓

1.3 Addition de Church

Reponse
add = λm.λn.λf.λx. m f (n f x)

Principe : add m n demande a m d'appliquer f m fois
sur le resultat de n qui applique f n fois sur x,
soit m + n applications au total.

1.4 Multiplication de Church

Reponse
mul = λm.λn.λf.λx. m (n f) x

Principe : m est applique non pas a f directement,
mais a la fonction (n f) qui correspond a l'application
de f n fois. Ainsi m applique (n f) m fois, ce qui
donne m × n applications de f.

Question 2 — OCaml : manipulation de listes [5 pts]

On considere les definitions suivantes :

let rec fold_left f acc = function
  | [] -> acc
  | x :: xs -> fold_left f (f acc x) xs

let rec map f = function
  | [] -> []
  | x :: xs -> f x :: map f xs

let rec filter p = function
  | [] -> []
  | x :: xs -> if p x then x :: filter p xs
               else filter p xs

2.1 Types infers [1 pt]

Donnez le type infere de chaque fonction (fold_left, map, filter).

2.2 Longueur avec fold_left [1 pt]

En utilisant uniquement fold_left, implementez longueur : 'a list -> int qui retourne la longueur d'une liste.

2.3 Renverser avec fold_left [1 pt]

En utilisant uniquement fold_left, implementez renverser : 'a list -> 'a list qui retourne la liste inversee. (Indice : penser a la concatenation @.)

2.4 Compter les pairs [1 pt]

Implementez compter_pairs : int list -> int qui compte le nombre d'elements pairs d'une liste, en utilisant List.filter et List.length (ou fold_left).

2.5 Minimum avec fold_left [1 pt]

En utilisant uniquement fold_left, implementez minimum : int list -> int qui retourne le minimum d'une liste d'entiers non vide. On donnera une valeur arbitraire (ex. : 0) si la liste est vide.

2.1 Types infers

Reponse
fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
map       : ('a -> 'b) -> 'a list -> 'b list
filter    : ('a -> bool) -> 'a list -> 'a list
Pointage
Les 3 types corrects : 1 pt • 2 corrects : 0.66 pt • 1 correct : 0.33 pt

2.2 Longueur avec fold_left

Reponse
let longueur lst =
  fold_left (fun acc _ -> acc + 1) 0 lst

2.3 Renverser avec fold_left

Reponse
let renverser lst =
  fold_left (fun acc x -> x :: acc) [] lst
Pointage
Code correct : 1 pt • Avec acc @ [x] (non optimal) : 0.5 pt

2.4 Compter les pairs

Reponse
let compter_pairs lst =
  List.length (List.filter (fun x -> x mod 2 = 0) lst)

(* Alternative avec fold_left : *)
let compter_pairs lst =
  fold_left (fun acc x -> if x mod 2 = 0 then acc + 1 else acc) 0 lst

2.5 Minimum avec fold_left

Reponse
let minimum lst =
  match lst with
  | [] -> 0
  | x :: xs -> fold_left (fun acc y -> if y < acc then y else acc) x xs
Pointage
Code correct avec cas vide : 1 pt • Sans gestion du cas vide : 0.5 pt

Question 3 — OCaml : types algebriques [4 pts]

On considere le type suivant representant des expressions arithmetiques :

type expr =
  | Cst of float
  | Add of expr * expr
  | Mul of expr * expr

3.1 Expression OCaml [1 pt]

Ecrivez l'expression OCaml qui represente mathematiquement (2 + 3) × 4.

3.2 Evaluation [1 pt]

Implementez eval : expr -> float qui evalue une expression arithmetique.

3.3 Comptage des operateurs [1 pt]

Implementez nb_op : expr -> int qui compte le nombre total d'operateurs (Add et Mul) dans l'expression. Utilisez le pattern matching sur le type expr.

3.4 Comptage des constantes [1 pt]

Implementez nb_variables : expr -> int qui compte le nombre de constantes (feuilles) dans l'expression.

3.1 Expression OCaml

Reponse
Mul (Add (Cst 2.0, Cst 3.0), Cst 4.0)

3.2 Evaluation

Reponse
let rec eval = function
  | Cst c        -> c
  | Add (e1, e2) -> eval e1 +. eval e2
  | Mul (e1, e2) -> eval e1 *. eval e2

3.3 Comptage des operateurs

Reponse
let rec nb_op = function
  | Cst _        -> 0
  | Add (e1, e2) -> 1 + nb_op e1 + nb_op e2
  | Mul (e1, e2) -> 1 + nb_op e1 + nb_op e2

3.4 Comptage des constantes

Reponse
let rec nb_variables = function
  | Cst _        -> 1
  | Add (e1, e2) -> nb_variables e1 + nb_variables e2
  | Mul (e1, e2) -> nb_variables e1 + nb_variables e2

Question 4 — Coq : logique des propositions [4 pts]

Prouvez les theoremes suivants en Coq. Donnez la tactique utilisee a chaque etape.

4.1 Transitivite de l'implication [1 pt]

Lemma imp_trans : forall P Q R : Prop,
  (P -> Q) -> (Q -> R) -> P -> R.

4.2 Commutativite de la conjunction [1 pt]

Lemma and_comm_simple : forall P Q : Prop,
  P /\ Q -> Q /\ P.

4.3 Association de la disjonction [1 pt]

Lemma or_assoc : forall P Q R : Prop,
  P \/ (Q \/ R) -> (P \/ Q) \/ R.

4.4 Negation de la conjunction [1 pt]

Lemma not_and_or : forall P Q : Prop,
  ~ (P /\ Q) -> ~ P \/ ~ Q.

4.1 Transitivite de l'implication

Reponse
Lemma imp_trans : forall P Q R : Prop,
  (P -> Q) -> (Q -> R) -> P -> R.
Proof.
  intros H1 H2 HP.
  apply H2.
  apply H1.
  exact HP.
Qed.

4.2 Commutativite de la conjunction

Reponse
Lemma and_comm_simple : forall P Q : Prop,
  P /\ Q -> Q /\ P.
Proof.
  intros H.
  split.
  - destruct H as [HP HQ]. exact HQ.
  - destruct H as [HP HQ]. exact HP.
Qed.

4.3 Association de la disjonction

Reponse
Lemma or_assoc : forall P Q R : Prop,
  P \/ (Q \/ R) -> (P \/ Q) \/ R.
Proof.
  intro H.
  destruct H as [HP | [HQ | HR]].
  - left. left. exact HP.
  - left. right. exact HQ.
  - right. exact HR.
Qed.

4.4 Negation de la conjunction

Attention : logique classique requise !

Ce theoreme n'est PAS prouvable en logique intuitionniste. Il necessite l'axiome du tiers exclu : classic : forall P, P \/ ~P.

Reponse
Lemma not_and_or : forall P Q : Prop,
  ~ (P /\ Q) -> ~ P \/ ~ Q.
Proof.
  intros H.
  destruct (classic P) as [HP | HnP].
  - right. intro HQ. apply H. split. exact HP. exact HQ.
  - left. exact HnP.
Qed.
Pointage
Preuve avec classic : 1 pt • Strategie correcte sans preuve complete : 0.5 pt • Reponse theorique correcte sur la logique classique : 0.5 pt

Question 5 — Coq : preuve par induction [3 pts]

Prouvez le theoreme suivant en Coq. Expliquez brievement la structure de la preuve.

Lemma add_comm : forall n m : nat,
  n + m = m + n.

5.1 Commutativite de l'addition

Reponse
Lemma add_comm : forall n m : nat,
  n + m = m + n.
Proof.
  intros n m.
  induction n as [| n' IH].
  - (* Cas de base : 0 + m = m + 0 *)
    simpl. symmetry. reflexivity.
  - (* Cas inductif : S n' + m = m + S n' *)
    simpl.
    rewrite -> IH.
    reflexivity.
Qed.
Justification
  • Cas de base (n = 0) : 0 + m = m par definition de +, puis m = m + 0 par symetrie.
  • Cas inductif (n = S n') : S n' + m = S (n' + m) par definition, puis on remplace n' + m par m + n' (hypothese IH), ce qui donne S (m + n') = m + S n' par definition de +.
Barème indicatif
CriterePoints
Structure correcte (induction n)0.5 pt
Cas de base correct1 pt
Cas inductif correct1 pt
Justification textuelle claire0.5 pt

Barème general

20–18 Tres bien • 17–14 Bien • 13–10 Assez bien • 9–6 Passable • <6 Insuffisant

Notes pour le correcteur
  • Les reponses alternatives sont acceptees si elles sont correctes.
  • Ne pas penaliser les fautes de frappe mineures (ex. : H1 au lieu de HP).
  • Pour les preuves Coq, accepter toute sequence de tactiques valides.
  • En cas de doute, privilégier une evaluation bienveillante.