Lecture notes 20210303 Hoare Logic 3
Remark. Some material in this lecture is from << Software Foundation >>
volume 2.
Require Import PL.Imp.
Import Assertion_S.
Import Assertion_S_Tac.
Import Concrete_Pretty_Printing.
Import Assertion_S.
Import Assertion_S_Tac.
Import Concrete_Pretty_Printing.
Last time, we discovered a common pattern in describing a strongest
postcondition of an assignment command. That is, given a precondition P,
and an assignment command X := E, their postcondition can be:
We have seen many assertions. They mainly follow the following syntax rules.
P ::= t < t, t = t, t ≤ t, ...
| [[ B ]]
| P AND P
| P OR P
| NOT P
| EXISTS x, P
| FORALL x, P
t ::= 0, 1, -1, ...
| x
| [[ E ]]
| t + t
| t - t
| t * t
| ...
where x represents logical variables, E represents integer program
expressions and B represents boolean integer program expressions. When we
define an assertion that
Suppose E is an integer-type expression of the programming language,
What is the result of the following symbolic substitution (x is some
constant)?
What is the result of the following symbolic substitution?
What is the result of the following symbolic substitution?
What is the result of the following symbolic substitution?
What is the result of the following symbolic substitution?
We can also apply symbolic substitution on a boolean expression.
Specifically, for a boolean-type expression B and an integer-type expression
E0, we use
We can also define symbolic substitution in assertions. We use
The following axiom describes the behavior of assignment commands.
There exists an old value x of program variable X, such that (1) the precondition P would hold if the value of X would be x (2) the value of X is result of evaluating the expression E if treating all occurrences of X in E as x.For example, the strongest postcondition of
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n }}
Y ::= 0
{{ ??? }}
can be:
Y ::= 0
{{ ??? }}
{{ EXISTS y, n * y + [[X]] = m AND
0 ≤ [[X]] AND [[X]] < n AND [[Y]] = 0 }} .
Today, we will describe that in logic formally.
0 ≤ [[X]] AND [[X]] < n AND [[Y]] = 0 }} .
Symbolic substitution
The assertion language
P would hold if the value of X would be xor an expression that
replacing all occurrences of X in E with xwe can complete the construction according to P's (or E's) syntax.
Symbolic substitution in program expressions
E [X ⟼ E0]
represents the result of replacing every occurence of program variable X with
program expression E0 in E. This result is still an integer-type
expression.
(X + Y) [ X ⟼ x ]
x + Y
(X - Y) [ X ⟼ 1 ]
1 - Y
(X + Y) [ X ⟼ X - Y ]
(X - Y) + Y
(X * Y) [ X ⟼ 1 ]
1 * Y
(X + 1) [ X ⟼ 1 ]
1 + 1
- (X * Y) [ X ⟼ 1] is 1 * Y , not Y.
- (X + 1) [ X ⟼ 1] is 1 + 1 , not 2.
B [X ⟼ E0]
to represent the result of replacing every occurence of program variable X
with E0 in B, e.g.
(!(X ≤ Y))[X ⟼ 0]
is ! (0 ≤ Y) .
Symbolic substitution in assertions
P [X ⟼ E0]
to represent the result of replacing every occurence of program variable X
with program expression E0 in assertion P. For example,
([[X + Y ≤ Z]] AND 0 ≤ [[X]] + [[Y]]) [X ⟼ X - Y]
([[X + Y ≤ Z]] AND 0 ≤ [[X]] + [[Y]]) [X ⟼ x]
([[X + Y ≤ Z]] AND 0 ≤ [[X]] + [[Y]]) [X ⟼ 0]
are
([[X + Y ≤ Z]] AND 0 ≤ [[X]] + [[Y]]) [X ⟼ x]
([[X + Y ≤ Z]] AND 0 ≤ [[X]] + [[Y]]) [X ⟼ 0]
[[(X - Y) + Y ≤ Z]] AND 0 ≤ [[X - Y]] + [[Y]]
[[x + Y ≤ Z]] AND 0 ≤ [[x]] + [[Y]].
[[0 + Y ≤ Z]] AND 0 ≤ [[0]] + [[Y]].
In other words, the effect of symbolic substitution on an assertion P is
applying substitution on those program expressions mentioned in P.
[[x + Y ≤ Z]] AND 0 ≤ [[x]] + [[Y]].
[[0 + Y ≤ Z]] AND 0 ≤ [[0]] + [[Y]].
Assignment rule (forward)
Axiom hoare_asgn_fwd : ∀P `(X: var) E,
{{ P }}
X ::= E
{{ EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] }} .
{{ P }}
X ::= E
{{ EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] }} .
Write down the postcondition described by hoare_asgn_fwd.
Write down the postcondition described by hoare_asgn_fwd.
Write down the postcondition described by hoare_asgn_fwd.
Write down the postcondition described by hoare_asgn_fwd.
Write down the postcondition described by hoare_asgn_fwd.
When C. A. R. Hoare first proposed Hoare logic for program correctness
proof in 1960s, the assignment rule is not in the forward direction; it was in
the backward direction. Robert W. Floyd proposed forward assignment rule later.
Due to this reason, people also use the nomenclature "Floyd-Hoare" logic
sometimes. (Another reason is that the original ideas of Hoare logic were seeded
by Floyd's work of a similar system for flowcharts.)
{{ [[X]] = x AND [[Y]] = y }}
TEMP ::= X;;
{{ ??? }}
EXISTS x0, [[x0]] = x AND [[Y]] = y AND [[TEMP]] = [[x]]
TEMP ::= X;;
{{ ??? }}
{{ 0 ≤ [[Y]] }}
X ::= Y;;
{{ ??? }}
EXISTS x0, 0 ≤ [[Y]] AND [[X]] = [[Y]]
X ::= Y;;
{{ ??? }}
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[n ≤ X]] }}
X ::= X - n
{{ ??? }}
EXISTS x0, n * [[Y]] + [[x0]] = m AND 0 ≤ [[x0]] AND [[n ≤ x0]] AND [[X]] = [[x0 - n]]
X ::= X - n
{{ ??? }}
{{ n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]] }}
Y ::= Y + 1
{{ ??? }}
EXISTS y0, n * [[y0]] + [[X]] + n = m AND 0 ≤ [[X]] AND [[Y]] = [[y0 + 1]]
Y ::= Y + 1
{{ ??? }}
{{ [[X]] = x AND [[Y]] = y }}
X ::= X + Y;;
{{ ??? }}
EXISTS x0, [[x0]] = x AND [[Y]] = y AND [[X]] = [[x0 + Y]]
X ::= X + Y;;
{{ ??? }}
Assignment rule (backward)
Axiom hoare_asgn_bwd : ∀P `(X: var) E,
{{ P [ X ⟼ E] }} X ::= E {{ P }} .
{{ P [ X ⟼ E] }} X ::= E {{ P }} .
Write down the precondition described by hoare_asgn_bwd.
Write down the precondition described by hoare_asgn_bwd.
{{ ??? }}
X ::= X + Y;;
{{ [[X]] = x + y AND [[Y]] = y }}
[[X + Y]] = x + y AND [[Y]] = y
X ::= X + Y;;
{{ [[X]] = x + y AND [[Y]] = y }}
{{ ??? }}
Y ::= Y + 1
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] }}
n * [[Y + 1]] + [[X]] = m AND 0 ≤ [[X]]
Y ::= Y + 1
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] }}
Consequence rule
Axiom hoare_consequence : ∀(P P' Q Q' : Assertion) c,
P ⊢ P' ->
{{P'}} c {{Q'}} ->
Q' ⊢ Q ->
{{P}} c {{Q}} .
Module Axiomatic_semantics.
Axiom hoare_seq : ∀(P Q R: Assertion) (c1 c2: com),
{{P}} c1 {{Q}} ->
{{Q}} c2 {{R}} ->
{{P}} c1;;c2 {{R}} .
Axiom hoare_skip : ∀P,
{{P}} Skip {{P}} .
Axiom hoare_if : ∀P Q b c1 c2,
{{ P AND [[b]] }} c1 {{ Q }} ->
{{ P AND NOT [[b]] }} c2 {{ Q }} ->
{{ P }} If b Then c1 Else c2 EndIf {{ Q }} .
Axiom hoare_while : ∀P b c,
{{ P AND [[b]] }} c {{P}} ->
{{P}} While b Do c EndWhile {{ P AND NOT [[b]] }} .
Axiom hoare_asgn_fwd : ∀P `(X: var) E,
{{ P }}
X ::= E
{{ EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] }} .
Axiom hoare_asgn_bwd : ∀P `(X: var) E,
{{ P [ X ⟼ E] }} X ::= E {{ P }} .
Axiom hoare_consequence : ∀(P P' Q Q' : Assertion) c,
P ⊢ P' ->
{{P'}} c {{Q'}} ->
Q' ⊢ Q ->
{{P}} c {{Q}} .
End Axiomatic_semantics.
Module div_mod_dec_again.
Import Axiomatic_semantics.
Coq proof time! Now, we are able to prove a nicer Hoare triple with simpler
hypothese.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Hypothesis derivation1: ∀m n: Z,
0 ≤ m AND [[X]] = m AND [[Y]] = 0 ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]].
Hypothesis derivation2: ∀m n: Z,
EXISTS z, n * [[Y]] + z = m AND 0 ≤ z AND n ≤ z AND [[X]] = z - n ⊢
n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]].
Hypothesis derivation3: ∀m n: Z,
EXISTS z, n * z + [[X]] + n = m AND 0 ≤ [[X]] AND [[Y]] = z + 1 ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]].
Hypothesis derivation4: ∀m n: Z,
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n.
Fact div_mod_dec_correct: ∀m n: Z,
{{ 0 ≤ m }}
X ::= m;;
Y ::= 0;;
While n ≤ X Do
X ::= X - n;;
Y ::= Y + 1
EndWhile
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n }} .
Proof.
intros.
eapply hoare_seq.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
Local Instance Y: var := new_var().
Hypothesis derivation1: ∀m n: Z,
0 ≤ m AND [[X]] = m AND [[Y]] = 0 ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]].
Hypothesis derivation2: ∀m n: Z,
EXISTS z, n * [[Y]] + z = m AND 0 ≤ z AND n ≤ z AND [[X]] = z - n ⊢
n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]].
Hypothesis derivation3: ∀m n: Z,
EXISTS z, n * z + [[X]] + n = m AND 0 ≤ [[X]] AND [[Y]] = z + 1 ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]].
Hypothesis derivation4: ∀m n: Z,
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] ⊢
n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n.
Fact div_mod_dec_correct: ∀m n: Z,
{{ 0 ≤ m }}
X ::= m;;
Y ::= 0;;
While n ≤ X Do
X ::= X - n;;
Y ::= Y + 1
EndWhile
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n }} .
Proof.
intros.
eapply hoare_seq.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
After eliminating the first assignment command using hoare_seq and
hoare_asgn_fwd, we see the substitution symbol and the existential quantifier
in our precondition. Our library PL.Imp provided the two tactics to simplify
such assertions.
eapply hoare_seq.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
apply hoare_consequence with
(n * [[Y]] + [[X]] = m AND 0 ≤ [[X]])%assert
(n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[ n ≤ X ]] )%assert.
1: { apply (derivation1 m n). }
2: { apply derivation4. }
apply hoare_while.
eapply hoare_seq.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
eapply hoare_consequence.
+ apply derivation2.
+ apply hoare_asgn_fwd.
+ assert_subst.
assert_simpl.
apply derivation3.
Qed.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
apply hoare_consequence with
(n * [[Y]] + [[X]] = m AND 0 ≤ [[X]])%assert
(n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[ n ≤ X ]] )%assert.
1: { apply (derivation1 m n). }
2: { apply derivation4. }
apply hoare_while.
eapply hoare_seq.
{ apply hoare_asgn_fwd. }
assert_subst.
assert_simpl.
eapply hoare_consequence.
+ apply derivation2.
+ apply hoare_asgn_fwd.
+ assert_subst.
assert_simpl.
apply derivation3.
Qed.
Now we try to prove the same Hoare triple again with forward proof style.
Fact div_mod_dec_correct_again: ∀m n: Z,
{{ 0 ≤ m }}
X ::= m;;
Y ::= 0;;
While n ≤ X Do
X ::= X - n;;
Y ::= Y + 1
EndWhile
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n }} .
Proof.
intros.
pose proof hoare_asgn_fwd
(n * [[Y]] + [[X]] = m AND
0 ≤ [[X]] AND [[n ≤ X]])%assert
X (X - n).
{{ 0 ≤ m }}
X ::= m;;
Y ::= 0;;
While n ≤ X Do
X ::= X - n;;
Y ::= Y + 1
EndWhile
{{ n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n }} .
Proof.
intros.
pose proof hoare_asgn_fwd
(n * [[Y]] + [[X]] = m AND
0 ≤ [[X]] AND [[n ≤ X]])%assert
X (X - n).
These two tactics assert_subst and assert_simpl can also simplify
assertions in assumptions
assert_subst in H.
assert_simpl in H.
pose proof hoare_asgn_fwd
(n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]])%assert
Y (Y + 1).
assert_subst in H0.
assert_simpl in H0.
pose proof hoare_consequence _ _ _ _ _
(derivation2 m n) H0 (derivation3 m n).
pose proof hoare_seq _ _ _ _ _ H H1.
clear H H0 H1.
assert_simpl in H.
pose proof hoare_asgn_fwd
(n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]])%assert
Y (Y + 1).
assert_subst in H0.
assert_simpl in H0.
pose proof hoare_consequence _ _ _ _ _
(derivation2 m n) H0 (derivation3 m n).
pose proof hoare_seq _ _ _ _ _ H H1.
clear H H0 H1.
It is unfortunate that we cannot achieve a Hoare triple for the while loop
here using H2 and hoare_while because the assertion that loop condition is
true
[[n ≤ X]]
has been simplified into n ≤ [[X]] . Thus, we assert the triple that we
want to prove.
assert ( {{n * [[Y]] + [[X]] = m AND 0 ≤ [[X]}} } While n ≤ X Do (X ::= X - n);; Y ::= Y + 1 EndWhile {{n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]}} }).
After assert, we first prove the asserted triple.
{
apply hoare_while.
assert_simpl.
exact H2.
}
clear H2.
apply hoare_while.
assert_simpl.
exact H2.
}
clear H2.
We then prove the original proof goal with an extra assumption—-the
asserted triple H.
pose proof hoare_asgn_fwd
(0 ≤ m)%assert
X
m.
assert_subst in H0.
assert_simpl in H0.
pose proof hoare_asgn_fwd
(0 ≤ m AND [[X]] = m)%assert
Y
0.
assert_subst in H1.
assert_simpl in H1.
pose proof hoare_consequence _ _ _ _ _
(derivation1 m n) H (derivation4 m n).
pose proof hoare_seq _ _ _ _ _ H1 H2.
pose proof hoare_seq _ _ _ _ _ H0 H3.
exact H4.
Qed.
End div_mod_dec_again.
(0 ≤ m)%assert
X
m.
assert_subst in H0.
assert_simpl in H0.
pose proof hoare_asgn_fwd
(0 ≤ m AND [[X]] = m)%assert
Y
0.
assert_subst in H1.
assert_simpl in H1.
pose proof hoare_consequence _ _ _ _ _
(derivation1 m n) H (derivation4 m n).
pose proof hoare_seq _ _ _ _ _ H1 H2.
pose proof hoare_seq _ _ _ _ _ H0 H3.
exact H4.
Qed.
End div_mod_dec_again.
Module derived_rules.
Import Assertion_S_Rules.
Import Axiomatic_semantics.
We know that an assertion can always derive itself. This property is called
derives_refl in our Imp library.
Check derives_refl.
(* : forall P : Assertion, P ⊢ P *)
(* : forall P : Assertion, P ⊢ P *)
Using it, we can derive two specialized consequence rule. The first one is a
single-sided consequence rule for preconditions.
Corollary hoare_consequence_pre: ∀P P' Q c,
P ⊢ P' ->
{{ P' }} c {{ Q }} ->
{{ P }} c {{ Q }} .
Proof.
intros.
eapply hoare_consequence.
+ exact H.
+ exact H0.
+ apply derives_refl.
Qed.
P ⊢ P' ->
{{ P' }} c {{ Q }} ->
{{ P }} c {{ Q }} .
Proof.
intros.
eapply hoare_consequence.
+ exact H.
+ exact H0.
+ apply derives_refl.
Qed.
Similarly, we have a single-sided consequence rule for postconditions
as well.
Corollary hoare_consequence_post: ∀P Q Q' c,
{{ P }} c {{ Q' }} ->
Q' ⊢ Q ->
{{ P }} c {{ Q }} .
Proof.
intros.
eapply hoare_consequence.
+ apply derives_refl.
+ exact H.
+ exact H0.
Qed.
{{ P }} c {{ Q' }} ->
Q' ⊢ Q ->
{{ P }} c {{ Q }} .
Proof.
intros.
eapply hoare_consequence.
+ apply derives_refl.
+ exact H.
+ exact H0.
Qed.
Since we prove these two rules from primary rules, we call them derived
rules (导出规则). There are other derived proof rules. They can be useful for
some special situations. The following rule is a weaker version of hoare_if
(we have shown why it is weak in our previous lectures). We can derive it from
our primary hoare_if rule now. But this proof is based on the following
properties of AND.
Check AND_left1.
(* : forall P Q R : Assertion,
P ⊢ R -> P AND Q ⊢ R *)
Check AND_left2.
(* : forall P Q R : Assertion,
Q ⊢ R -> P AND Q ⊢ R *)
Corollary hoare_if_weak : ∀P Q b c1 c2,
{{P}} c1 {{Q}} ->
{{P}} c2 {{Q}} ->
{{P}} If b Then c1 Else c2 EndIf {{Q}} .
Proof.
intros.
apply hoare_if.
+ eapply hoare_consequence_pre.
2: { exact H. }
apply AND_left1.
apply derives_refl.
+ eapply hoare_consequence_pre.
2: { exact H0. }
apply AND_left1.
apply derives_refl.
Qed.
(* : forall P Q R : Assertion,
P ⊢ R -> P AND Q ⊢ R *)
Check AND_left2.
(* : forall P Q R : Assertion,
Q ⊢ R -> P AND Q ⊢ R *)
Corollary hoare_if_weak : ∀P Q b c1 c2,
{{P}} c1 {{Q}} ->
{{P}} c2 {{Q}} ->
{{P}} If b Then c1 Else c2 EndIf {{Q}} .
Proof.
intros.
apply hoare_if.
+ eapply hoare_consequence_pre.
2: { exact H. }
apply AND_left1.
apply derives_refl.
+ eapply hoare_consequence_pre.
2: { exact H0. }
apply AND_left1.
apply derives_refl.
Qed.
Also, we have seen a lot of examples, in which we use hoare_seq and
hoare_asgn_fwd together when the first command is an assignment. We can pack
them together:
Corollary hoare_asgn_seq: ∀P `(X: var) E c Q,
{{ EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] }} c {{ Q }} ->
{{ P }} X ::= E ;; c {{ Q }} .
Proof.
intros.
eapply hoare_seq.
+ apply hoare_asgn_fwd.
+ exact H.
Qed.
{{ EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] }} c {{ Q }} ->
{{ P }} X ::= E ;; c {{ Q }} .
Proof.
intros.
eapply hoare_seq.
+ apply hoare_asgn_fwd.
+ exact H.
Qed.
What if the assignment is the only command? We have also seen a combination
of hoare_asgn_fwd and hoare_consequence.
Corollary hoare_asgn_conseq: ∀P `(X: var) E Q,
EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] ⊢ Q ->
{{ P }} X ::= E {{ Q }} .
Proof.
intros.
eapply hoare_consequence_post.
+ apply hoare_asgn_fwd.
+ exact H.
Qed.
EXISTS x, P [X ⟼ x] AND [[X]] = [[ E [X ⟼ x] ]] ⊢ Q ->
{{ P }} X ::= E {{ Q }} .
Proof.
intros.
eapply hoare_consequence_post.
+ apply hoare_asgn_fwd.
+ exact H.
Qed.
These derived rule can make Coq formalized proofs shorter; and more
importantly, they help to describe how we understand Hoare logic proofs. We do
not apply proof rules one by one in our mind, we use proof rule "combos"
instead. Now, let's redo our proofs about swapping.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
Hypothesis der1: ∀x y,
EXISTS x0, x0 = x AND [[Y]] = y AND [[TEMP]] = x0 AND [[X]] = [[Y]] ⊢
[[X]] = y AND [[TEMP]] = x.
Hypothesis der2: ∀x y,
[[X]] = y AND [[TEMP]] = x AND [[Y]] = [[TEMP]] ⊢
[[X]] = y AND [[Y]] = x.
Fact swaping_correct:
∀x y: Z,
{{ [[X]] = x AND [[Y]] = y }}
TEMP ::= X;;
X ::= Y;;
Y ::= TEMP
{{ [[X]] = y AND [[Y]] = x }} .
Proof.
(* WORKED IN CLASS *)
intros.
apply hoare_asgn_seq.
assert_subst.
assert_simpl.
apply hoare_asgn_seq.
assert_subst.
assert_simpl.
eapply hoare_consequence_pre.
{ apply der1. }
apply hoare_asgn_conseq.
assert_subst.
assert_simpl.
apply der2.
Qed.
End derived_rules.
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
Hypothesis der1: ∀x y,
EXISTS x0, x0 = x AND [[Y]] = y AND [[TEMP]] = x0 AND [[X]] = [[Y]] ⊢
[[X]] = y AND [[TEMP]] = x.
Hypothesis der2: ∀x y,
[[X]] = y AND [[TEMP]] = x AND [[Y]] = [[TEMP]] ⊢
[[X]] = y AND [[Y]] = x.
Fact swaping_correct:
∀x y: Z,
{{ [[X]] = x AND [[Y]] = y }}
TEMP ::= X;;
X ::= Y;;
Y ::= TEMP
{{ [[X]] = y AND [[Y]] = x }} .
Proof.
(* WORKED IN CLASS *)
intros.
apply hoare_asgn_seq.
assert_subst.
assert_simpl.
apply hoare_asgn_seq.
assert_subst.
assert_simpl.
eapply hoare_consequence_pre.
{ apply der1. }
apply hoare_asgn_conseq.
assert_subst.
assert_simpl.
apply der2.
Qed.
End derived_rules.
Decorated program as informal Hoare logic proof
/* 0 ≤ m */
X ::= m;;
Y ::= 0;;
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
While n ≤ X Do
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[n ≤ X]] */
X ::= X - n;;
Y ::= Y + 1
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
EndWhile
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n */.
X ::= m;;
Y ::= 0;;
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
While n ≤ X Do
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[n ≤ X]] */
X ::= X - n;;
Y ::= Y + 1
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
EndWhile
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n */.
/* 0 ≤ m */
X ::= m;;
/* EXISTS x, 0 ≤ m AND [[X]] = m */
/* 0 ≤ m AND [[X]] = m */
Y ::= 0;;
/* EXISTS y, 0 ≤ m AND [[X]] = m AND [[Y]] = 0 */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
While n ≤ X Do
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[n ≤ X]] */
X ::= X - n;;
/* EXISTS x, n * [[Y]] + [[x]] = m AND
0 ≤ [[x]] AND [[n ≤ x]] AND [[X]] = [[x - n]] */
/* EXISTS x, n * [[Y]] + x = m AND
0 ≤ x AND n ≤ x AND [[X]] = x - n */
/* n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]] */
Y ::= Y + 1
/* EXISTS y, n * [[y]] + [[X]] + n = m AND
0 ≤ [[X]] AND [[Y]] = [[y + 1]] */
/* EXISTS y, n * y + [[X]] + n = m AND
0 ≤ [[X]] AND [[Y]] = y + 1 */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
EndWhile
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n */.
X ::= m;;
/* EXISTS x, 0 ≤ m AND [[X]] = m */
/* 0 ≤ m AND [[X]] = m */
Y ::= 0;;
/* EXISTS y, 0 ≤ m AND [[X]] = m AND [[Y]] = 0 */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
While n ≤ X Do
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[n ≤ X]] */
X ::= X - n;;
/* EXISTS x, n * [[Y]] + [[x]] = m AND
0 ≤ [[x]] AND [[n ≤ x]] AND [[X]] = [[x - n]] */
/* EXISTS x, n * [[Y]] + x = m AND
0 ≤ x AND n ≤ x AND [[X]] = x - n */
/* n * [[Y]] + [[X]] + n = m AND 0 ≤ [[X]] */
Y ::= Y + 1
/* EXISTS y, n * [[y]] + [[X]] + n = m AND
0 ≤ [[X]] AND [[Y]] = [[y + 1]] */
/* EXISTS y, n * y + [[X]] + n = m AND
0 ≤ [[X]] AND [[Y]] = y + 1 */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] */
EndWhile
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND NOT [[n ≤ X]] */
/* n * [[Y]] + [[X]] = m AND 0 ≤ [[X]] AND [[X]] < n */.
Exercises
Exercise: 3 stars, standard (remainder_only)
Module remainder_only.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
In the this task, you can write hypothese about assignment commands without
proving them.
(* FILL IN HERE *)
Fact remainder_only_correct: ∀m n: Z,
{{ 0 ≤ m }}
X ::= m;;
While n ≤ X Do
X ::= X - n
EndWhile
{{ (EXISTS q, n * q + [[X]] = m) AND 0 ≤ [[X]] AND NOT [[n ≤ X]] }} .
Proof.
intros.
(* FILL IN HERE *) Admitted.
☐
Fact remainder_only_correct: ∀m n: Z,
{{ 0 ≤ m }}
X ::= m;;
While n ≤ X Do
X ::= X - n
EndWhile
{{ (EXISTS q, n * q + [[X]] = m) AND 0 ≤ [[X]] AND NOT [[n ≤ X]] }} .
Proof.
intros.
(* FILL IN HERE *) Admitted.
End remainder_only.
Exercise: 2 stars, standard (reduce_to_zero_alter1)
You are only allowed write assertion derivations as hypotheses in this exercise.
Module reduce_to_zero_alter1.
Import Axiomatic_semantics.
Import derived_rules.
Local Instance X: var := new_var().
Import Axiomatic_semantics.
Import derived_rules.
Local Instance X: var := new_var().
Hint: the following decorated program shows a proof skeleton.
/* True */
While !(X ≤ 0) Do
/* True AND [[ !(X ≤ 0) ]] */
/* True */
X ::= X - 1
/* EXISTS x, True AND [[X]] = [[x - 1]] */
/* True */
EndWhile
/* True AND NOT [[ !(X ≤ 0) ]] */
/* [[X]] ≤ 0 */.
While !(X ≤ 0) Do
/* True AND [[ !(X ≤ 0) ]] */
/* True */
X ::= X - 1
/* EXISTS x, True AND [[X]] = [[x - 1]] */
/* True */
EndWhile
/* True AND NOT [[ !(X ≤ 0) ]] */
/* [[X]] ≤ 0 */.
(* FILL IN HERE *)
Fact reduce_to_zero_correct:
{{ True }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] ≤ 0 }} .
Proof.
(* FILL IN HERE *) Admitted.
☐
Fact reduce_to_zero_correct:
{{ True }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] ≤ 0 }} .
Proof.
(* FILL IN HERE *) Admitted.
End reduce_to_zero_alter1.
Exercise: 3 stars, standard (reduce_to_zero_alter2)
You are only allowed write assertion derivations as hypotheses in this exercise.
Module reduce_to_zero_alter2.
Import Axiomatic_semantics.
Import derived_rules.
Local Instance X: var := new_var().
(* FILL IN HERE *)
Fact reduce_to_zero_correct:
{{ 0 ≤ [[X]] }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] = 0 }} .
Proof.
(* FILL IN HERE *) Admitted.
☐
Import Axiomatic_semantics.
Import derived_rules.
Local Instance X: var := new_var().
(* FILL IN HERE *)
Fact reduce_to_zero_correct:
{{ 0 ≤ [[X]] }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] = 0 }} .
Proof.
(* FILL IN HERE *) Admitted.
End reduce_to_zero_alter2.
(* 2021-03-07 20:15 *)
(* 2021-03-07 20:15 *)