Lecture notes 20210412 Denotations vs Triples 2

Require Import PL.Imp.
Import Assertion_D.
Import Abstract_Pretty_Printing.

Review

Here is a list of important terminologies that introduced in the last lecture.
  • We use syntax trees to describe assertions. Assertions describe properties of program states and logical variables via expressions (aexp and bexp) and terms.
  • Syntactic substitution is recursively defined. When quantifiers (forall and exists) are involved, renaming should be done beforehand. E.g. (EXISTS x, [[X]] = 2 * x) [X x] should be EXISTS y, [[x]] = 2 * y instead of EXISTS x, [[x]] = 2 * x .
  • A Hoare triple is provable (可证) if we can prove it from our Hoare logic proof rules, written as    {{ P } c  {{ Q } . In these two weeks, we will pick backward assignment rule in our proof theories.
  • An interpretation (解释) is a pair of program state and logical variable assignment. When an interpretation satisfies (满足) an assertion is defined by recursively on the assertion's syntax tree. We write J |= P if J satisfies P.
  • A Hoare triple  {{ P } c  {{ Q } is valid (有效) when for any beginning state st1, assignment La and ending state st2, if (st1, La) |= P and (st1, st2) is in the denotation of c, then (st2, La) |= Q , written as  {{ P } c  {{ Q } .

Soundness

We will prove Hoare logic's soundness today. Recall that a Hoare logic is sound when all provable Hoare triples are valid.
Definition hoare_sound (T: FirstOrderLogic): Prop :=
  P c Q,
      {{ P }c  {{ Q }}  ->
    ⊨  {{ P }c  {{ Q }} .
We will prove that if the logic for assertion derivation is sound, then the corresponding Hoare logic is also sound. Similarly, an assertion is called valid if it is satisfied on all interpreations. And a logic for assertion derivation is called sound, if every provable assertion is valid.
Definition FOL_valid (P: Assertion): Prop :=
  J: Interp, JP.

Definition FOL_sound (T: FirstOrderLogic): Prop :=
  P: Assertion, FOL_provable P -> FOL_valid P.

Lemma FOL_sound_spec {T: FirstOrderLogic}:
  FOL_sound T ->
  P Q: Assertion,
    P  Q ->
    st La,
      ((st, La) ⊨ P) -> ((st, La) ⊨ Q).
Proof.
  intros.
  apply H in H0.
  specialize (H0 (st, La)).
  simpl in H0; tauto.
Qed.
Now, we will start our Hoare logic soundness proof.
Lemma hoare_seq_sound : (P Q R: Assertion) (c1 c2: com),
  ⊨  {{P}c1  {{Q}}  ->
  ⊨  {{Q}c2  {{R}}  ->
  ⊨  {{P}c1;;c2  {{R}} .
Proof.
  unfold valid.
  intros.
  rewrite ceval_CSeq in H2.
  unfold BinRel.concat in H2.
  destruct H2 as [st1' [? ?]].
  specialize (H _ _ _ H1 H2).
  specialize (H0 _ _ _ H H3).
  exact H0.
Qed.

Lemma hoare_skip_sound : P,
  ⊨  {{P}Skip  {{P}} .
Proof.
  unfold valid.
  intros.
  rewrite ceval_CSkip in H0.
  unfold BinRel.id in H0.
  rewrite <- H0.
  exact H.
Qed.

Lemma hoare_if_sound : P Q (b: bexp) c1 c2,
  ⊨  {{ P AND [[b]] }c1  {{ Q }}  ->
  ⊨  {{ P AND NOT [[b]] }c2  {{ Q }}  ->
  ⊨  {{ P }If b Then c1 Else c2 EndIf  {{ Q }} .
Proof.
  unfold valid.
  intros.
  rewrite ceval_CIf in H2.
  unfold if_sem in H2.
  unfold BinRel.union,
         BinRel.concat,
         BinRel.test_rel in H2.
  destruct H2 as [H2 | H2];
  destruct H2 as [st [[? ?] ?]]; subst st.
  + apply H with st1.
    - simpl.
      pose proof beval_bexp'_denote st1 La b.
      tauto.
    - tauto.
  + apply H0 with st1.
    - simpl.
      simpl in H3.
      unfold Sets.complement in H3.
      pose proof beval_bexp'_denote st1 La b.
      tauto.
    - tauto.
Qed.

Lemma hoare_while_sound : P (b: bexp) c,
  ⊨  {{ P AND [[b]] }c  {{P}}  ->
  ⊨  {{P}While b Do c EndWhile  {{ P AND NOT [[b]] }} .
Proof.
  unfold valid.
  intros.
  rewrite ceval_CWhile in H1.
  unfold loop_sem in H1.
  unfold BinRel.omega_union in H1.
  destruct H1 as [n ?].
  revert st1 H0 H1; induction n; intros.
  + simpl in H1.
    unfold BinRel.test_rel,
           Sets.complement in H1.
    destruct H1.
    subst st2.
    simpl.
    pose proof beval_bexp'_denote st1 La b.
    tauto.
  + simpl in H1.
    unfold BinRel.concat at 1,
           BinRel.test_rel in H1.
    destruct H1 as [st1' [[HH ?] ?]]; subst st1'.
    unfold BinRel.concat in H2.
    destruct H2 as [st1' [? ?]].
    apply IHn with st1'.
    - apply H with st1.
      * simpl.
        pose proof beval_bexp'_denote st1 La b.
        tauto.
      * exact H2.
    - exact H3.
Qed.
For backward assignment rule's case, we need to use an important property of syntactic substitution.
Check Assertion_sub_spec.

(* Assertion_sub_spec
     : forall (st1 : state) (st2 : var -> Z) (La : Lassn) 
         (P : Assertion) (X : var) (E : aexp'),
       st2 X = aexp'_denote (st1, La) E ->
       (forall Y : var, X <> Y -> st1 Y = st2 Y) ->
       (st1, La) ⊨ P X E <-> (st2, La) ⊨ P *)

It says: the effect of syntactic substitution is the same as doing real modification on program states. We provide its proof in Imp.
Lemma hoare_asgn_bwd_sound : P (X: var) (E: aexp),
  ⊨  {{ P [ XE] }X ::= E  {{ P }} .
Proof.
  unfold valid.
  intros.
  rewrite ceval_CAss in H0.
  destruct H0.
  pose proof aeval_aexp'_denote st1 La E.
  rewrite H2 in H0.
  pose proof Assertion_sub_spec st1 st2 _ P _ _ H0 H1.
  tauto.
Qed.

Lemma hoare_consequence_sound : (T: FirstOrderLogic) (P P' Q Q' : Assertion) c,
  FOL_sound T ->
  P  P' ->
  ⊨  {{P'}c  {{Q'}}  ->
  Q'  Q ->
  ⊨  {{P}c  {{Q}} .
Proof.
  intros.
  pose proof FOL_sound_spec H _ _ H0.
  pose proof FOL_sound_spec H _ _ H2.
  unfold valid in H1.
  unfold valid.
  intros.
  apply H4.
  apply H1 with st1; [| tauto].
  apply H3.
  exact H5.
Qed.

Theorem Hoare_logic_soundness: (T: FirstOrderLogic) (TS: FOL_sound T),
  hoare_sound T.
Proof.
  intros.
  unfold hoare_sound.
  intros.
  remember ( {{P}c  {{Q}} ) as Tr.
  clear P c Q HeqTr.
  induction H.
  + eapply hoare_seq_sound.
    - exact IHprovable1.
    - exact IHprovable2.
  + apply hoare_skip_sound.
  + apply hoare_if_sound.
    - exact IHprovable1.
    - exact IHprovable2.
  + apply hoare_while_sound.
    exact IHprovable.
  + apply hoare_asgn_bwd_sound.
  + pose proof hoare_consequence_sound T P P' Q Q' c TS H IHprovable H1.
    exact H2.
Qed.

(* 2021-04-14 07:19 *)