Lecture notes 20190315
First Order Logic 1
Remark. Some material in this lecture is from << Software Foundation >>
volume 1 and volume 2.
Require Import PL.Imp4.
Review: Hoare logic
Module swapping_asgn_fwd.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
We want to prove that
We can write a decorated program to illustrate our proof.
∀x y: Z,
{{ [[X]] == x AND [[Y]] == y }}
TEMP ::= X;;
X ::= Y;;
Y ::= TEMP
{{ [[X]] == y AND [[Y]] == x }}.
{{ [[X]] == x AND [[Y]] == y }}
TEMP ::= X;;
X ::= Y;;
Y ::= TEMP
{{ [[X]] == y AND [[Y]] == x }}.
/* [[X]] == x AND [[Y]] == y */
TEMP ::= X;;
/* EXISTS t, [[X]] == x AND [[Y]] == y AND [[TEMP]] == [[X]] */
/* [[X]] == x AND [[Y]] == y AND [[TEMP]] == [[X]] */
X ::= Y;;
/* EXISTS x0, [[x0]] == x AND [[Y]] == y AND
[[TEMP]] == [[x0]] AND [[X]] == [[Y]] */
/* [[Y]] == y AND [[TEMP]] == x AND [[X]] == [[Y]] */
Y ::= TEMP
/* EXISTS y0, [[y0]] == y AND [[TEMP]] == x AND
[[X]] == [[y0]] AND [[Y]] == [[TEMP]] */
/* [[X]] == y AND [[Y]] == x */.
TEMP ::= X;;
/* EXISTS t, [[X]] == x AND [[Y]] == y AND [[TEMP]] == [[X]] */
/* [[X]] == x AND [[Y]] == y AND [[TEMP]] == [[X]] */
X ::= Y;;
/* EXISTS x0, [[x0]] == x AND [[Y]] == y AND
[[TEMP]] == [[x0]] AND [[X]] == [[Y]] */
/* [[Y]] == y AND [[TEMP]] == x AND [[X]] == [[Y]] */
Y ::= TEMP
/* EXISTS y0, [[y0]] == y AND [[TEMP]] == x AND
[[X]] == [[y0]] AND [[Y]] == [[TEMP]] */
/* [[X]] == y AND [[Y]] == x */.
Hypothesis derivation1: ∀x y: Z,
EXISTS x0, [[x0]] == x AND [[Y]] == y AND
[[TEMP]] == [[x0]] AND [[X]] == [[Y]] ⊢
[[Y]] == y AND [[TEMP]] == x AND [[X]] == [[Y]].
Hypothesis derivation2: ∀x y: Z,
EXISTS y0, [[y0]] == y AND [[TEMP]] == x AND [[X]] == [[y0]] 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.
intros.
eapply hoare_seq.
apply hoare_asgn_fwd.
assert_subst.
assert_simpl.
eapply hoare_seq.
apply hoare_asgn_fwd.
assert_subst.
eapply hoare_consequence.
apply derivation1.
apply hoare_asgn_fwd.
assert_subst.
apply derivation2.
Qed.
End swapping_asgn_fwd.
Module swapping_asgn_bwd.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
EXISTS x0, [[x0]] == x AND [[Y]] == y AND
[[TEMP]] == [[x0]] AND [[X]] == [[Y]] ⊢
[[Y]] == y AND [[TEMP]] == x AND [[X]] == [[Y]].
Hypothesis derivation2: ∀x y: Z,
EXISTS y0, [[y0]] == y AND [[TEMP]] == x AND [[X]] == [[y0]] 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.
intros.
eapply hoare_seq.
apply hoare_asgn_fwd.
assert_subst.
assert_simpl.
eapply hoare_seq.
apply hoare_asgn_fwd.
assert_subst.
eapply hoare_consequence.
apply derivation1.
apply hoare_asgn_fwd.
assert_subst.
apply derivation2.
Qed.
End swapping_asgn_fwd.
Module swapping_asgn_bwd.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance TEMP: var := new_var().
We can also use hoare_asgn_bwd to prove it. Here is the decorated program.
/* [[X]] == x AND [[Y]] == y */
/* [[Y]] == y AND [[X]] == x */.
TEMP ::= X;;
/* [[Y]] == y AND [[TEMP]] == x */.
X ::= Y;;
/* [[X]] == y AND [[TEMP]] == x */.
Y ::= TEMP
/* [[X]] == y AND [[Y]] == x */.
/* [[Y]] == y AND [[X]] == x */.
TEMP ::= X;;
/* [[Y]] == y AND [[TEMP]] == x */.
X ::= Y;;
/* [[X]] == y AND [[TEMP]] == x */.
Y ::= TEMP
/* [[X]] == y AND [[Y]] == x */.
Hypothesis derivation1: ∀x y: Z,
[[X]] == x AND [[Y]] == y ⊢
[[Y]] == y AND [[X]] == x.
Hypothesis derivation2: ∀x y: Z,
[[X]] == y AND [[Y]] == x ⊢
[[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.
intros.
pose proof hoare_asgn_bwd
([[X]] == y AND [[Y]] == x)%assert
Y
TEMP.
assert_subst in H.
pose proof hoare_asgn_bwd
([[X]] == y AND [[TEMP]] == x)%assert
X
Y.
assert_subst in H0.
pose proof hoare_asgn_bwd
([[Y]] == y AND [[TEMP]] == x)%assert
TEMP
X.
assert_subst in H1.
pose proof hoare_seq _ _ _ _ _ H0 H.
pose proof hoare_seq _ _ _ _ _ H1 H2.
pose proof hoare_consequence _ _ _ _ _
(derivation1 x y) H3 (derivation2 x y).
exact H4.
Qed.
End swapping_asgn_bwd.
Module test_prime.
Local Instance A: var := new_var().
Local Instance N: var := new_var().
Local Instance Res: var := new_var().
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
[[X]] == x AND [[Y]] == y ⊢
[[Y]] == y AND [[X]] == x.
Hypothesis derivation2: ∀x y: Z,
[[X]] == y AND [[Y]] == x ⊢
[[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.
intros.
pose proof hoare_asgn_bwd
([[X]] == y AND [[Y]] == x)%assert
Y
TEMP.
assert_subst in H.
pose proof hoare_asgn_bwd
([[X]] == y AND [[TEMP]] == x)%assert
X
Y.
assert_subst in H0.
pose proof hoare_asgn_bwd
([[Y]] == y AND [[TEMP]] == x)%assert
TEMP
X.
assert_subst in H1.
pose proof hoare_seq _ _ _ _ _ H0 H.
pose proof hoare_seq _ _ _ _ _ H1 H2.
pose proof hoare_consequence _ _ _ _ _
(derivation1 x y) H3 (derivation2 x y).
exact H4.
Qed.
End swapping_asgn_bwd.
Module test_prime.
Local Instance A: var := new_var().
Local Instance N: var := new_var().
Local Instance Res: var := new_var().
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
The following program will test whether A is a prime number or not, very
slowly.
Although it is a little bit longer than our previous examples, we can still
prove it correct.
Coq's formal proof of this program will be part of your second homework.
N ::= 2;;
Res ::= 0;;
While !(A == N) Do
X ::= A;;
Y ::= 0;;
While N ≤ X Do
X ::= X - N;;
Y ::= Y + 1
EndWhile;;
If (X == 0)
Then Res ::= 1
Else Skip
EndIf;;
N ::= N + 1
EndWhile.
Res ::= 0;;
While !(A == N) Do
X ::= A;;
Y ::= 0;;
While N ≤ X Do
X ::= X - N;;
Y ::= Y + 1
EndWhile;;
If (X == 0)
Then Res ::= 1
Else Skip
EndIf;;
N ::= N + 1
EndWhile.
/* [[A]] == m AND 2 ≤ m */
N ::= 2;;
Res ::= 0;;
/* [[A]] == m AND 2 ≤ m AND [[N]] == 2 AND [[Res]] == 0 */
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) */
While !(A == N) Do
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[!(A == N)]] */
X ::= A;;
Y ::= 0;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] */
While N ≤ X Do
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND [[N ≤ X]] */
X ::= X - N;;
Y ::= Y + 1
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] */
EndWhile;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND NOT [[N ≤ X]] */
If (X == 0)
Then
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND
NOT [[N ≤ X]] AND [[X == 0]] */
Res ::= 1
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
Else
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND
NOT [[N ≤ X]] AND NOT [[X == 0]] */
Skip
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
EndIf;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
N ::= N + 1
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) */
EndWhile
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
NOT [[ !(A == N) ]] */
N ::= 2;;
Res ::= 0;;
/* [[A]] == m AND 2 ≤ m AND [[N]] == 2 AND [[Res]] == 0 */
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) */
While !(A == N) Do
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[!(A == N)]] */
X ::= A;;
Y ::= 0;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] */
While N ≤ X Do
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND [[N ≤ X]] */
X ::= X - N;;
Y ::= Y + 1
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] */
EndWhile;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND NOT [[N ≤ X]] */
If (X == 0)
Then
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND
NOT [[N ≤ X]] AND [[X == 0]] */
Res ::= 1
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
Else
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
[[N]] * [[Y]] + [[X]] == m AND 0 ≤ [[X]] AND
NOT [[N ≤ X]] AND NOT [[X == 0]] */
Skip
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
EndIf;;
/* [[A]] == m AND [[N]] < [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N + 1]] AND k * q == m)) */
N ::= N + 1
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) */
EndWhile
/* [[A]] == m AND [[N]] ≤ [[A]] AND 2 ≤ m AND
(([[Res]] == 1 AND EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m) OR
([[Res]] == 0 AND NOT EXISTS k, EXISTS q,
2 ≤ k AND k < [[N]] AND k * q == m)) AND
NOT [[ !(A == N) ]] */
End test_prime.
Summary
- assertions (including syntactic substitution and assertion derivation)
- Hoare triples
- axiomatic semantics.
- intros
- apply
- pose proof
- exact
- eapply
- assert.
Assertion entailment
Module reduce_to_zero_alter2.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Hypothesis derivation1:
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Hypothesis derivation2:
0 ≤ [[X]] AND NOT [[! (X ≤ 0)]] ⊢ [[X]] == 0.
Hypothesis derivation3:
0 ≤ [[X]] AND [[! (X ≤ 0)]] ⊢ 0 ≤ [[X]] - 1.
Hypothesis derivation4:
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Fact reduce_to_zero_correct:
{{ 0 ≤ [[X]] }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] == 0 }}.
Proof.
assert ({{0 ≤ [[X]] AND [[! (X ≤ 0)]}}} X ::= X - 1 {{0 ≤ [[X]}}}).
{
pose proof hoare_asgn_bwd
(0 ≤ [[X]])%assert
X
(X - 1).
assert_subst in H.
assert_simpl in H.
eapply hoare_consequence.
apply derivation3.
exact H.
apply derivation4.
}
apply hoare_consequence with
(0 ≤ [[X]])%assert
(0 ≤ [[X]] AND NOT [[ !(X ≤ 0) ]])%assert.
apply derivation1.
apply hoare_while.
apply H.
apply derivation2.
Qed.
Import Axiomatic_semantics.
Local Instance X: var := new_var().
Hypothesis derivation1:
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Hypothesis derivation2:
0 ≤ [[X]] AND NOT [[! (X ≤ 0)]] ⊢ [[X]] == 0.
Hypothesis derivation3:
0 ≤ [[X]] AND [[! (X ≤ 0)]] ⊢ 0 ≤ [[X]] - 1.
Hypothesis derivation4:
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Fact reduce_to_zero_correct:
{{ 0 ≤ [[X]] }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] == 0 }}.
Proof.
assert ({{0 ≤ [[X]] AND [[! (X ≤ 0)]}}} X ::= X - 1 {{0 ≤ [[X]}}}).
{
pose proof hoare_asgn_bwd
(0 ≤ [[X]])%assert
X
(X - 1).
assert_subst in H.
assert_simpl in H.
eapply hoare_consequence.
apply derivation3.
exact H.
apply derivation4.
}
apply hoare_consequence with
(0 ≤ [[X]])%assert
(0 ≤ [[X]] AND NOT [[ !(X ≤ 0) ]])%assert.
apply derivation1.
apply hoare_while.
apply H.
apply derivation2.
Qed.
The question is: do we really need to put such derivation into hypothesis?
Can we prove them instead? The answer is yes.
Lemma der1:
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Proof.
0 ≤ [[X]] ⊢ 0 ≤ [[X]].
Proof.
Obviously, this proof goal is equivalent to say: for any integer x, if
0 ≤ x then 0 ≤ x. The following tactic entailer provided by our Imp
library apply this transition for us.
entailer.
Now, we know that we should use "intros" to drag this universally
quantified variable X' above the line.
intros.
Oops, it does more!! But that is reasonable. Proving A → B (reads "A
implies B" is equivalent with proving B with assumption A. At this,
position, we know what to do now:
exact H.
Qed.
Lemma der2:
0 ≤ [[X]] AND NOT [[! (X ≤ 0)]] ⊢ [[X]] == 0.
Proof.
entailer.
intros.
Qed.
Lemma der2:
0 ≤ [[X]] AND NOT [[! (X ≤ 0)]] ⊢ [[X]] == 0.
Proof.
entailer.
intros.
The symbol "/\" (see the assumption H) represents "and" in Coq and the
symbol "~" represents negation or "not". We know that this proof goal is true
But at this position, what we have already learnt cannot help us much. The
following tactic "omega" is to solve linear programming problems. Let's try
it.
omega.
Bingo!
Qed.
Let's try it again.
Lemma der3:
0 ≤ [[X]] AND [[! (X ≤ 0)]] ⊢ 0 ≤ [[X]] - 1.
Proof.
entailer.
intros.
omega.
Qed.
0 ≤ [[X]] AND [[! (X ≤ 0)]] ⊢ 0 ≤ [[X]] - 1.
Proof.
entailer.
intros.
omega.
Qed.
Now we have got all four hypotheses proved.
End reduce_to_zero_alter2.
Here are more examples.
Module more_entailments.
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
Local Instance X: var := new_var().
Local Instance Y: var := new_var().
The following derivation is used in verifying slow_sub:
{{ True }}
X ::= m;;
Y ::= p;;
While !(X == 0) Do
Y ::= Y - 1;;
X ::= X - 1
EndWhile
{{ [[Y]] - [[X]] == p - m AND NOT [[ !(X == 0) ]] }}.
X ::= m;;
Y ::= p;;
While !(X == 0) Do
Y ::= Y - 1;;
X ::= X - 1
EndWhile
{{ [[Y]] - [[X]] == p - m AND NOT [[ !(X == 0) ]] }}.
Lemma der1: ∀m: Z,
True ⊢ [[m]] == m.
Proof.
intros.
entailer.
omega.
Qed.
Lemma der2: ∀m p: Z,
[[X]] == m AND [[Y]] == p ⊢ [[Y]] - [[X]] == p - m.
Proof.
intros.
entailer.
intros.
omega.
Qed.
Lemma der3: ∀m p: Z,
[[Y]] - [[X]] == p - m AND [[ !(X == 0) ]] ⊢
[[Y-1]] - [[X]] == p - m - 1.
Proof.
intros.
entailer.
intros.
omega.
Qed.
Lemma der4: ∀m p: Z,
[[Y]] - [[X]] == p - m - 1 ⊢
[[Y]] - [[X - 1]] == p - m.
Proof.
intros.
entailer.
intros.
omega.
Qed.
End more_entailments.
True ⊢ [[m]] == m.
Proof.
intros.
entailer.
omega.
Qed.
Lemma der2: ∀m p: Z,
[[X]] == m AND [[Y]] == p ⊢ [[Y]] - [[X]] == p - m.
Proof.
intros.
entailer.
intros.
omega.
Qed.
Lemma der3: ∀m p: Z,
[[Y]] - [[X]] == p - m AND [[ !(X == 0) ]] ⊢
[[Y-1]] - [[X]] == p - m - 1.
Proof.
intros.
entailer.
intros.
omega.
Qed.
Lemma der4: ∀m p: Z,
[[Y]] - [[X]] == p - m - 1 ⊢
[[Y]] - [[X - 1]] == p - m.
Proof.
intros.
entailer.
intros.
omega.
Qed.
End more_entailments.
Proving True
{{ True }}
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] ≤ 0 }}
We need to reason about True for many times. If you forget, here is the
decorated program:
While !(X ≤ 0) Do
X ::= X - 1
EndWhile
{{ [[X]] ≤ 0 }}
/* 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 */.
True ⊢ True
True AND [[! (X ≤ 0)]] ⊢ True
EXISTS x, True AND [[X]] == x - 1 ⊢ True
True AND NOT [[! (X ≤ 0)]] ⊢ [[X]] ≤ 0.
True AND [[! (X ≤ 0)]] ⊢ True
EXISTS x, True AND [[X]] == x - 1 ⊢ True
True AND NOT [[! (X ≤ 0)]] ⊢ [[X]] ≤ 0.
Module reduce_to_zero_alter1.
Local Instance X: var := new_var().
Lemma der1:
True ⊢ True.
Proof.
intros.
entailer.
intros.
exact H.
Qed.
Local Instance X: var := new_var().
Lemma der1:
True ⊢ True.
Proof.
intros.
entailer.
intros.
exact H.
Qed.
But actually, we do not need to derive True from something else. It is by
itself true.
Lemma der2:
True AND [[! (X ≤ 0)]] ⊢ True.
Proof.
entailer.
intros.
True AND [[! (X ≤ 0)]] ⊢ True.
Proof.
entailer.
intros.
In Coq, I is a proof of True. Whenever you want to prove True, use
exact I.
exact I.
Qed.
Qed.
Now we can prove the rest two hypotheses.
Lemma der3:
EXISTS x, True AND [[X]] == x - 1 ⊢ True.
Proof.
entailer.
intros.
exact I.
Qed.
Lemma der4:
True AND NOT [[! (X ≤ 0)]] ⊢ [[X]] ≤ 0.
Proof.
entailer.
intros.
omega.
Qed.
End reduce_to_zero_alter1.
EXISTS x, True AND [[X]] == x - 1 ⊢ True.
Proof.
entailer.
intros.
exact I.
Qed.
Lemma der4:
True AND NOT [[! (X ≤ 0)]] ⊢ [[X]] ≤ 0.
Proof.
entailer.
intros.
omega.
Qed.
End reduce_to_zero_alter1.
The tactic exact I is also useful in normal Coq proofs.
Theorem True_is_true: True.
Proof.
exact I.
Qed.
Fact stupid_fact: ∀x y:Z, x = y → True.
Proof.
intros.
exact I.
Qed.
Proof.
exact I.
Qed.
Fact stupid_fact: ∀x y:Z, x = y → True.
Proof.
intros.
exact I.
Qed.
Conjunction
Lemma True2: True ∧ True.
Proof.
split.
exact I.
exact I.
Qed.
Lemma and_intro : ∀A B : Prop, A → B → A ∧ B.
Proof.
intros A B HA HB. split.
- apply HA.
- apply HB.
Qed.
Example and_exercise :
∀n m : Z, n + 2*m = 0 → 2*n + m = 0 → n = 0 ∧ True.
Proof.
intros.
split.
omega.
exact I.
Qed.
Proof.
split.
exact I.
exact I.
Qed.
Lemma and_intro : ∀A B : Prop, A → B → A ∧ B.
Proof.
intros A B HA HB. split.
- apply HA.
- apply HB.
Qed.
Example and_exercise :
∀n m : Z, n + 2*m = 0 → 2*n + m = 0 → n = 0 ∧ True.
Proof.
intros.
split.
omega.
exact I.
Qed.
To use a conjunctive hypothesis to help prove something else, we use the
destruct tactic.
Lemma and_example2 :
∀n m : Z, n = 0 ∧ (True → m = 0) → n + m = 0.
Proof.
intros.
destruct H.
pose proof H0 I.
omega.
Qed.
Lemma and_example2' :
∀n m : Z, n = 0 ∧ (True → m = 0) → n + m = 0.
Proof.
intros.
destruct H as [Hn H].
pose proof H I as Hm.
omega.
Qed.
Theorem and_commut : ∀P Q : Prop,
P ∧ Q → Q ∧ P.
Proof.
intros.
destruct H as [HP HQ].
split.
- exact HQ.
- exact HP.
Qed.
∀n m : Z, n = 0 ∧ (True → m = 0) → n + m = 0.
Proof.
intros.
destruct H.
pose proof H0 I.
omega.
Qed.
Lemma and_example2' :
∀n m : Z, n = 0 ∧ (True → m = 0) → n + m = 0.
Proof.
intros.
destruct H as [Hn H].
pose proof H I as Hm.
omega.
Qed.
Theorem and_commut : ∀P Q : Prop,
P ∧ Q → Q ∧ P.
Proof.
intros.
destruct H as [HP HQ].
split.
- exact HQ.
- exact HP.
Qed.
Theorem and_assoc : ∀P Q R : Prop,
P ∧ (Q ∧ R) → (P ∧ Q) ∧ R.
Proof.
intros.
destruct H as [HP [HQ HR]].
(* FILL IN HERE *) Admitted.
☐
P ∧ (Q ∧ R) → (P ∧ Q) ∧ R.
Proof.
intros.
destruct H as [HP [HQ HR]].
(* FILL IN HERE *) Admitted.
Disjunction
Lemma or_example :
∀n m : Z, n = 0 ∨ m = 0 → n * m = 0.
Proof.
intros.
destruct H.
- rewrite H.
omega.
- rewrite H.
omega.
Qed.
Lemma or_example2 :
∀P Q R: Prop, (P → R) → (Q → R) → (P ∨ Q → R).
Proof.
intros.
destruct H1 as [HP | HQ].
- apply H.
exact HP.
- pose proof H0 HQ.
exact H1.
Qed.
∀n m : Z, n = 0 ∨ m = 0 → n * m = 0.
Proof.
intros.
destruct H.
- rewrite H.
omega.
- rewrite H.
omega.
Qed.
Lemma or_example2 :
∀P Q R: Prop, (P → R) → (Q → R) → (P ∨ Q → R).
Proof.
intros.
destruct H1 as [HP | HQ].
- apply H.
exact HP.
- pose proof H0 HQ.
exact H1.
Qed.
Conversely, to show that a disjunction holds, we need to show that
one of its sides does. This is done via two tactics, left and
right. As their names imply, the first one requires
proving the left side of the disjunction, while the second
requires proving its right side. Here is a trivial use...
Lemma or_introl : ∀A B : Prop, A → A ∨ B.
Proof.
intros.
left.
exact H.
Qed.
Lemma or_intror : ∀A B : Prop, B → A ∨ B.
Proof.
intros.
right.
exact H.
Qed.
Proof.
intros.
left.
exact H.
Qed.
Lemma or_intror : ∀A B : Prop, B → A ∨ B.
Proof.
intros.
right.
exact H.
Qed.
Theorem or_commut : ∀P Q : Prop,
P ∨ Q → Q ∨ P.
Proof.
(* FILL IN HERE *) Admitted.
☐
P ∨ Q → Q ∨ P.
Proof.
(* FILL IN HERE *) Admitted.
Implication
Theorem modus_ponens: ∀P Q: Prop,
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
pose proof H0 H.
exact H1.
Qed.
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
pose proof H0 H.
exact H1.
Qed.
But we can also prove it in alternative ways.
Theorem modus_ponens_alter1: ∀P Q: Prop,
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
revert H.
exact H0.
Qed.
Theorem modus_ponens_alter2: ∀P Q: Prop,
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
specialize (H0 H).
exact H0.
Qed.
(* Fri Mar 15 07:58:05 UTC 2019 *)
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
revert H.
exact H0.
Qed.
Theorem modus_ponens_alter2: ∀P Q: Prop,
P ∧ (P → Q) → Q.
Proof.
intros.
destruct H.
specialize (H0 H).
exact H0.
Qed.
(* Fri Mar 15 07:58:05 UTC 2019 *)