Domácí úkoly 4:



Poznámka: K řešení těchto úkolů je potřeba mít ve stejném adresáři uložené a zkompilované následující soubory s implementací programovacího jazyka Imp a Hoareovy logiky: hoare/LibMaps.v, hoare/LibImp.v, hoare/LibAssertion.v, hoare/LibHoare.v, hoare/LibHoare2.v.
Tyto soubory jsou k dispozici na webových stránkách předmětu IADKP.


Require Import LibHoare2.

From Coq Require Import Bool.Bool.
From Coq Require Import Arith.Arith.
From Coq Require Import Arith.EqNat.
From Coq Require Import Arith.PeanoNat. Import Nat.
From Coq Require Import Lia.

Open Scope dcom_scope.

Definition ZDE_DOPLNIT := <{True}>.


Příklad A: 1 bod

Připomeňme, že zápis n! označuje faktoriál čísla n (tj. n! = 1*2*...*n]). Ve standardní knihovně Coqu je funkce faktoriál formálně definována pomocí rekurze následujícím způsobem:
    Fixpoint fact (n : nat) : nat :=
      match n with
      | O => 1
      | S n' => S n' * (fact n')
      end.
Uvažujme následující implementaci funkce pro výpočet faktoriálu v jazyce Imp. V dané funkci obsahuje na začátku proměnná X hodnotu n. Po skončení výpočtu by měla proměnná Y obsahovat hodnotu n! (tj. faktoriál n). V daném kódu místo ZDE_DOPLNIT doplňte příslušné anotace tak, abyste následně mohli dokázat korektnost tohoto programu pomocí taktiky verify.
Pozn.: Po použití taktiky verify vám zřejmě zbude několik málo nedokázaných tvrzení, která se pravděpodobně budou týkat především nějakých matematických vlastností funkce fact. Pro dokončení důkazu tedy musíte dokázat i tato tvrzení.
Připomeňme ještě, že pro volání funkcí Coqu v assertions (jako třeba funkce fact) je třeba použít pomocný operátor ap (nebo ap2 pro binární funkce).

Definition factorial_v1_dec (n:nat) : decorated
     :=
  <{ {{ X = n }} ==>
                 {{ ZDE_DOPLNIT }}
     Y := 1
                 {{ ZDE_DOPLNIT }};
     W := 0
                 {{ ZDE_DOPLNIT }};
     while W < X do
                      {{ ZDE_DOPLNIT }} ==>
                      {{ ZDE_DOPLNIT }}
         W := 1 + W
                      {{ ZDE_DOPLNIT }};
         Y := Y × W
                      {{ ZDE_DOPLNIT }}
     end
                 {{ ZDE_DOPLNIT }} ==>
     {{ Y = ap fact n }}
  }>.

Theorem factorial_v1_correct: n,
  outer_triple_valid (factorial_v1_dec n).
Proof.
Admitted.



Příklad B: 2 body

Uvažujme následující definici funkce pro výpočet faktoriálu. Podobně jako v předchozím příkladě doplňte v kódu příslušné anotace a dokažte, že tato funkce je korektní.
Nápověda: Obecně může být při dokazování tvrzení, která se týkají aritmetických operací na přirozených číslech, jednodušší se vyhnout operacím jako je dělení a místo toho formulovat příslušná tvrzení tak, aby používala jen násobení a další jednoduché operace jako třeba sčítání.

Definition factorial_v2_dec (n:nat) : decorated
     :=
  <{
     {{ X = n }} ==>
                 {{ ZDE_DOPLNIT }}
     Y := 1
                 {{ ZDE_DOPLNIT }} ==>
                 {{ ZDE_DOPLNIT }};
     while X > 1 do
                      {{ ZDE_DOPLNIT }}
         Y := X × Y
                      {{ ZDE_DOPLNIT }};
         X := X - 1
                      {{ ZDE_DOPLNIT }}
     end
                 {{ ZDE_DOPLNIT }} ==>
     {{ Y = fact n }}
  }>.

Theorem factorial_v2_correct: n,
  outer_triple_valid (factorial_v2_dec n).
Proof.
Admitted.



Příklad C: 1 bod

Fibonacciho funkce je obvykle zapsána následujícím způsobem:
      Fixpoint fib n :=
        match n with
        | 0 => 1
        | 1 => 1
        | _ => fib (pred n) + fib (pred (pred n))
        end.
Tato definice neprojde kontrolou Coqu, která ověřuje, že se výpočet této funkce po konečném počtu kroků zastaví. Následující mírně komplikovanější definice touto kontrolou projde.

Fixpoint fib n :=
  match n with
  | 0 ⇒ 1
  | S n'match n' with
            | 0 ⇒ 1
            | S n''fib n' + fib n''
            end
  end.

Dokažte, že funkce fib splňuje následující rovnost. Je možné, že tato rovnost se vám bude hodit při vytváření důkazu v následujícím příkladě.

Lemma fib_eqn : n,
  n > 0 →
  fib n + fib (pred n) = fib (1 + n).
Proof.
Admitted.



Příklad D: 2 body

Následující program v jazyce Imp spočítá hodnotu fib n. Tato hodnota by se měla po skončení výpočtu nacházet v proměnné Y.
Doplňte anotace v následující definici dfib a dokažte, že splňuje následující specifikaci:
      {{ True }} dfib {{ Y = fib n }}
Pozn.: Pravděpodobně budete potřebovat ve vašich anotacích mnohokrát použít ap.

Definition T : var := "T"%string.

Definition dfib (n : nat) : decorated :=
  <{
    {{ True }} ==>
    {{ ZDE_DOPLNIT }}
    X := 1
                {{ ZDE_DOPLNIT }};
    Y := 1
                {{ ZDE_DOPLNIT }};
    Z := 1
                {{ ZDE_DOPLNIT }};
    while X ≠ 1 + n do
                  {{ ZDE_DOPLNIT }} ==>
                  {{ ZDE_DOPLNIT }}
      T := Z
                  {{ ZDE_DOPLNIT }};
      Z := Z + Y
                  {{ ZDE_DOPLNIT }};
      Y := T
                  {{ ZDE_DOPLNIT }};
      X := 1 + X
                  {{ ZDE_DOPLNIT }}
    end
    {{ ZDE_DOPLNIT }} ==>
    {{ Y = fib n }}
   }>.

Theorem dfib_correct : n,
  outer_triple_valid (dfib n).
Proof.
Admitted.



Příklad E: 4 body

V Hoareově logice můžeme používat několik různých variant pravidel pro přiřazení. Níže jsou uvedeny tři takové varianty označené hoare_assign_A, hoare_assign_B a hoare_assign_C.
Dokažte, že všechna tři tato pravidla jsou mezi sebou navzájem odvoditelná, a to bez ohledu na to, jak konkrétně je nadefinován přesný význam Hoareovy trojice.
Z toho důvodu je v tomto případě místo hoare_triple použita v daných pravidlech hoare_triple_abstract, o které nic bližšího nepředpokládáme. Kromě toho můžete v důkazech používat pravidla hoare_consequence_pre, hoare_consequence_post a hoare_exists_pre, která zde bereme jako axiomy.
Při dokazování se vám mohou hodit rovněž tvrzení t_update_eq, t_update_shadow a t_update_same ze souboru LibMaps.v a případně též následující pomocné tvrzení t_update_restore, které si rovněž dokažte.

Lemma t_update_restore (x : var) (v : value) (st : state) :
    (x !-> st x; x !-> v; st) = st.
Proof.
Admitted.

Module Hoare_assign.

    Parameter hoare_triple_abstract : AssertioncomAssertionProp.

    Notation "{{ P }} c {{ Q }}" :=
       (hoare_triple_abstract P c Q) (at level 90, c custom com at level 99)
         : hoare_spec_scope.

    Axiom hoare_consequence_pre : P P' Q c,
         {{ P' }} c {{ Q }} → (P ==> P') → {{ P }} c {{ Q }}.

    Axiom hoare_consequence_post : P Q Q' c,
         {{ P }} c {{ Q' }} → (Q' ==> Q) → {{ P }} c {{ Q }}.

    Axiom hoare_exists_pre : {M : Type} P Q c,
       ( x, {{ P x }} c {{ Q }}) →
         {{ fun st x : M, P x st }} c {{ Q }}.

    Definition hoare_assign_A := P x a,
            {{ P[x |-> a] }} <{ x := a }> {{ P }}.

    Definition hoare_assign_B := x a m P,
          {{ fun stP stst x = m }}
             <{ x := a }>
          {{ fun stP (x !-> m ; st) ∧ st x = aeval (x !-> m ; st) a }}.

    Definition hoare_assign_C := x a P,
          {{fun stP st}}
             <{ x := a }>
          {{fun st m,
                 P (x !-> m ; st) ∧ st x = aeval (x !-> m ; st) a }}.

    Theorem B_from_A :
        hoare_assign_Ahoare_assign_B.
    Proof.
Admitted.

    Theorem C_from_A :
        hoare_assign_Ahoare_assign_C.
    Proof.
Admitted.

    Theorem A_from_B :
        hoare_assign_Bhoare_assign_A.
    Proof.
Admitted.

    Theorem A_from_C :
        hoare_assign_Choare_assign_A.
    Proof.
Admitted.

End Hoare_assign.



This page has been generated by coqdoc