Lecture notes 20190531
More Semantics 4 Termination
Require Import Coq.Relations.Relation_Operators.
Require Import Coq.Relations.Relation_Definitions.
Require Export Coq.ZArith.ZArith.
Require Export Coq.Strings.String.
Require Export Coq.Logic.Classical.
Arguments clos_refl_trans {A} _ _ _.
Arguments clos_refl_trans_1n {A} _ _ _.
Arguments clos_refl_trans_n1 {A} _ _ _.
Open Scope Z.
Require Import Coq.Relations.Relation_Definitions.
Require Export Coq.ZArith.ZArith.
Require Export Coq.Strings.String.
Require Export Coq.Logic.Classical.
Arguments clos_refl_trans {A} _ _ _.
Arguments clos_refl_trans_1n {A} _ _ _.
Arguments clos_refl_trans_n1 {A} _ _ _.
Open Scope Z.
Termination
Total Correctness
Unchanged rules
Axiom hoare_skip : ∀P,
{{P}} Skip {{P}}.
Axiom hoare_seq : ∀(P Q R: Assertion) (c1 c2: com),
{{P}} c1 {{Q}} →
{{Q}} c2 {{R}} →
{{P}} c1;;c2 {{R}}.
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_consequence : ∀(P P' Q Q' : Assertion) c,
P ⊢ P' →
{{P'}} c {{Q'}} →
Q' ⊢ Q →
{{P}} c {{Q}}.
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 }}.
{{P}} Skip {{P}}.
Axiom hoare_seq : ∀(P Q R: Assertion) (c1 c2: com),
{{P}} c1 {{Q}} →
{{Q}} c2 {{R}} →
{{P}} c1;;c2 {{R}}.
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_consequence : ∀(P P' Q Q' : Assertion) c,
P ⊢ P' →
{{P'}} c {{Q'}} →
Q' ⊢ Q →
{{P}} c {{Q}}.
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 }}.
While loop rule
Axiom hoare_while_partial : ∀I b c,
{{ I AND [[b]] }} c {{ I }} →
{{ I }} While b Do c EndWhile {{ I AND NOT [[b]] }}.
{{ I AND [[b]] }} c {{ I }} →
{{ I }} While b Do c EndWhile {{ I AND NOT [[b]] }}.
Axiom hoare_while_total : ∀I V b c,
(∀T:Z,
{{ I AND [[b]] AND V == T }} c {{ I AND 0 ≤ V AND V < T }}) →
{{ I }} While b Do c EndWhile {{ I AND NOT [[b]] }}.
Here, the loop variable V is a integer term in the assertion language that
talks about program variables. This rule says, if the loop variant strictly
decreases in every execution of loop body, the loop will always terminate.
(∀T:Z,
{{ I AND [[b]] AND V == T }} c {{ I AND 0 ≤ V AND V < T }}) →
{{ I }} While b Do c EndWhile {{ I AND NOT [[b]] }}.
Examples
{{ 0 < [[X]] }}
While !(X == 0) Do
X ::= X - 1
EndWhile
{{ [[X]] == 0 }}.
While !(X == 0) Do
X ::= X - 1
EndWhile
{{ [[X]] == 0 }}.
{{ 0 ≤ m }}
X ::= m;;
Y ::= p;;
While !(X == 0) Do
Y ::= Y - 1;;
X ::= X - 1
EndWhile
{{ [[Y]] - [[X]] == p - m AND [[X]] == 0 }}.
X ::= m;;
Y ::= p;;
While !(X == 0) Do
Y ::= Y - 1;;
X ::= X - 1
EndWhile
{{ [[Y]] - [[X]] == p - m AND [[X]] == 0 }}.
{{ 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 }}.
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 }}.
Programs With Addresses And Dereferences
Definition var: Type := nat.
Inductive aexp : Type :=
| ANum (n : Z)
| AId (X : var)
| APlus (a1 a2 : aexp)
| AMinus (a1 a2 : aexp)
| AMult (a1 a2 : aexp)
| ADeref (a1: aexp) (* <-- new *)
| AAddr (a1: aexp). (* <-- new *)
Inductive bexp : Type :=
| BTrue
| BFalse
| BEq (a1 a2 : aexp)
| BLe (a1 a2 : aexp)
| BNot (b : bexp)
| BAnd (b1 b2 : bexp).
Inductive com : Type :=
| CSkip
| CAss (a1 a2 : aexp) (* <-- new *)
| CSeq (c1 c2 : com)
| CIf (b : bexp) (c1 c2 : com)
| CWhile (b : bexp) (c : com).
Inductive aexp : Type :=
| ANum (n : Z)
| AId (X : var)
| APlus (a1 a2 : aexp)
| AMinus (a1 a2 : aexp)
| AMult (a1 a2 : aexp)
| ADeref (a1: aexp) (* <-- new *)
| AAddr (a1: aexp). (* <-- new *)
Inductive bexp : Type :=
| BTrue
| BFalse
| BEq (a1 a2 : aexp)
| BLe (a1 a2 : aexp)
| BNot (b : bexp)
| BAnd (b1 b2 : bexp).
Inductive com : Type :=
| CSkip
| CAss (a1 a2 : aexp) (* <-- new *)
| CSeq (c1 c2 : com)
| CIf (b : bexp) (c1 c2 : com)
| CWhile (b : bexp) (c : com).
We assume that the value of variables of 0, 1, ... are stored at address
1, 2, ... etc. Address 0 is for null pointer.
Definition var2addr (X: var): Z := Z.of_nat X + 1.
Program States With Permission
Definition state: Type := Z → option Z.
For a state st and an address p, st p = Some _ means that we have
read/write permission of p. Otherwise, st p = None and we do not have read
or write permission of it.
Now, we try to write down its denotational semantics. We start from integer
expressions.
Denotational Semantics
Module FirstTry_aeval.
Inductive aeval : aexp → state → Z → Prop :=
| E_ANum n st:
aeval (ANum n) st n
| E_AId X st n:
st (var2addr X) = Some n →
aeval (AId X) st n
| E_APlus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (APlus e1 e2) st (n1 + n2)
| E_AMinus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (AMinus e1 e2) st (n1 - n2)
| E_AMult (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (AMult e1 e2) st (n1 * n2)
| E_ADeref (e1: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : st n1 = Some n2) :
aeval (ADeref e1) st n2.
End FirstTry_aeval.
Inductive aeval : aexp → state → Z → Prop :=
| E_ANum n st:
aeval (ANum n) st n
| E_AId X st n:
st (var2addr X) = Some n →
aeval (AId X) st n
| E_APlus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (APlus e1 e2) st (n1 + n2)
| E_AMinus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (AMinus e1 e2) st (n1 - n2)
| E_AMult (e1 e2: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : aeval e2 st n2) :
aeval (AMult e1 e2) st (n1 * n2)
| E_ADeref (e1: aexp) (n1 n2: Z) st
(H1 : aeval e1 st n1)
(H2 : st n1 = Some n2) :
aeval (ADeref e1) st n2.
End FirstTry_aeval.
The problem here is that we have no way to talk about AAddr here. Because
the value of AAddr E is not depended on E's value but about E's address.
Thus, we need to define two evaluation relation mutually inductively.
Inductive aevalR : aexp → state → Z → Prop :=
| E_ANum n st:
aevalR (ANum n) st n
| E_AId X st n:
st (var2addr X) = Some n →
aevalR (AId X) st n
| E_APlus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (APlus e1 e2) st (n1 + n2)
| E_AMinus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMinus e1 e2) st (n1 - n2)
| E_AMult (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMult e1 e2) st (n1 * n2)
| E_ADeref (e1: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : st n1 = Some n2) :
aevalR (ADeref e1) st n2
| E_AAddre (e1: aexp) (n1: Z) st
(H1 : aevalL e1 st n1):
aevalR (AAddr e1) st n1
with aevalL : aexp → state → Z → Prop :=
| EA_AId X st:
aevalL (AId X) st (var2addr X)
| EA_ADeref (e1: aexp) (n1: Z) st
(H1 : aevalR e1 st n1) :
aevalL (ADeref e1) st n1.
| E_ANum n st:
aevalR (ANum n) st n
| E_AId X st n:
st (var2addr X) = Some n →
aevalR (AId X) st n
| E_APlus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (APlus e1 e2) st (n1 + n2)
| E_AMinus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMinus e1 e2) st (n1 - n2)
| E_AMult (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMult e1 e2) st (n1 * n2)
| E_ADeref (e1: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : st n1 = Some n2) :
aevalR (ADeref e1) st n2
| E_AAddre (e1: aexp) (n1: Z) st
(H1 : aevalL e1 st n1):
aevalR (AAddr e1) st n1
with aevalL : aexp → state → Z → Prop :=
| EA_AId X st:
aevalL (AId X) st (var2addr X)
| EA_ADeref (e1: aexp) (n1: Z) st
(H1 : aevalR e1 st n1) :
aevalL (ADeref e1) st n1.
Then, we can easily define bexp's denotations.
Inductive beval : bexp → state → bool → Prop :=
| E_BTrue st:
beval BTrue st true
| E_BFalse st:
beval BFalse st false
| E_BEqTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 = n2) :
beval (BEq e1 e2) st true
| E_BEqFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≠ n2) :
beval (BEq e1 e2) st false
| E_BLeTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 < n2) :
beval (BLe e1 e2) st true
| E_BLeFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≥ n2) :
beval (BLe e1 e2) st false
| E_BNot (e: bexp) (b: bool) st
(H1 : beval e st b):
beval (BNot e) st (negb b)
| E_BAnd (e1 e2: bexp) (b1 b2: bool) st
(H1 : beval e1 st b1)
(H2 : beval e2 st b2):
beval (BAnd e1 e2) st (andb b1 b2).
(* Sat Jun 8 04:35:31 UTC 2019 *)
| E_BTrue st:
beval BTrue st true
| E_BFalse st:
beval BFalse st false
| E_BEqTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 = n2) :
beval (BEq e1 e2) st true
| E_BEqFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≠ n2) :
beval (BEq e1 e2) st false
| E_BLeTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 < n2) :
beval (BLe e1 e2) st true
| E_BLeFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≥ n2) :
beval (BLe e1 e2) st false
| E_BNot (e: bexp) (b: bool) st
(H1 : beval e st b):
beval (BNot e) st (negb b)
| E_BAnd (e1 e2: bexp) (b1 b2: bool) st
(H1 : beval e1 st b1)
(H2 : beval e2 st b2):
beval (BAnd e1 e2) st (andb b1 b2).
(* Sat Jun 8 04:35:31 UTC 2019 *)