5.1 Logique des predicats

Definition — Predicat

Un predicat est une propriete qui depend d'arguments. Exemple : P(x) signifie "x est pair", Parent(x, y) signifie "x est parent de y".

5.1.1 Quantificateurs en Coq

(* Universel : pour tout x, P(x) *)
Lemma forall_ex : forall n : nat, n + 0 = n.
Proof.
  intro n.
  induction n as [| n' IH].
  - simpl. reflexivity.
  - simpl. rewrite IH. reflexivity.
Qed.

(* Existentiel : il existe x tel que P(x) *)
Lemma exists_even : exists n : nat, n + n = 4.
Proof.
  exists 2.
  simpl. reflexivity.
Qed.

5.1.2 Regles des quantifyurs

RegleEn CoqCondition
∀Iintro xx ne doit pas apparaitre dans le contexte
∀Especialize (H t)Appliquer a un terme concret
&exists;Iexists tDonner le temoin
&exists;Edestruct H as [x Hx]Extraire le temoin et la propriete

5.2 Unification

Definition — Unification

Trouver une substitution qui rend deux termes egaux. C'est le moteur du raisonnement automatique (unification de Robinson, 1965).

type term =
  | TVar of string
  | TFun of string * term list

type subst = (string * term) list

let rec appliquer_subst subst t =
  match t with
  | TVar x       ->
    (try List.assoc x subst with Not_found -> t)
  | TFun (f, ts) ->
    TFun (f, List.map (appliquer_subst subst) ts)

let occurs_check x t =
  let rec aux = function
    | TVar y       -> x = y
    | TFun (_, ts) -> List.exists aux ts
  in aux t

let rec unifier t1 t2 =
  match t1, t2 with
  | TVar x, TVar y when x = y -> Some []
  | TVar x, _ when not (occurs_check x t2) ->
    Some [(x, t2)]
  | _, TVar x when not (occurs_check x t1) ->
    Some [(x, t1)]
  | TFun (f, ts1), TFun (g, ts2) when f = g &&
       List.length ts1 = List.length ts2 ->
    unifier_list ts1 ts2
  | _ -> None

and unifier_list ts1 ts2 =
  match ts1, ts2 with
  | [], [] -> Some []
  | t1 :: r1, t2 :: r2 ->
    match unifier t1 t2 with
    | None -> None
    | Some s1 ->
      match unifier_list
        (List.map (appliquer_subst s1) r1)
        (List.map (appliquer_subst s1) r2) with
      | None -> None
      | Some s2 -> Some (s1 @ s2)
    end
  | _ -> None

5.3 Raisonnement par induction

Principe d'induction sur les entiers naturels

Pour prouver P(n) pour tout n : nat, il suffit de prouver :

  • Cas de base : P(0)
  • Cas inductif : forall k, P(k) -> P(S k)
(* Associativite de l'addition *)
Lemma add_assoc : forall n m p : nat,
  n + (m + p) = (n + m) + p.
Proof.
  intros n m p.
  induction n as [| n' IH].
  - simpl. reflexivity.
  - simpl. rewrite IH. reflexivity.
Qed.

(* Somme des n premiers entiers *)
Lemma somme_formule : forall n : nat,
  2 * somme n = n * (n + 1).
Proof.
  intro n. induction n as [| n' IH].
  - simpl. reflexivity.
  - simpl. lia.
Qed.

(* Longueur de append *)
Lemma append_length : forall (A : Type) (l1 l2 : list A),
  length (l1 ++ l2) = length l1 + length l2.
Proof.
  intros A l1 l2. induction l1 as [| a l1' IH].
  - simpl. reflexivity.
  - simpl. rewrite IH. reflexivity.
Qed.

5.4 Application — Mini Prolog

type fait = {
  pred : string;
  args : term list;
}

type base = {
  faits : fait list;
  regles : (fait * term list) list;  (* regle = fait + conditions *)
}

let ajouter_fait base f = { base with faits = f :: base.faits }

let ajouter_regle base (conclusion, conditions) =
  { base with regles = (conclusion, conditions) :: base.regles }

let rec rechercher base but subst =
  (* Essayer chaque fait de la base *)
  let resultats_faits =
    List.filter_map (fun f ->
      let but_subst = appliquer_subst subst but in
      unifier_fait but_subst f
    ) base.faits
  in
  (* Essayer chaque regle *)
  let resultats_regles =
    List.filter_map (fun (conclusion, conditions) ->
      let but_subst = appliquer_subst subst but in
      match unifier_fait but_subst conclusion with
      | None -> None
      | Some s ->
        (* Resoudre chaque condition recursivement *)
        Some (resoudre_conditions base conditions s)
    ) base.regles
  in
  resultats_faits @ List.concat resultats_regles
Exercices
  • Prouvez forall n, n * 0 = 0 en Coq.
  • Prouvez rev(rev(l)) = l par induction.
  • Ajoutez des variables fraiches au Mini Prolog.
  • Implementez member(X, L) en Prolog.