How to finish the TLAPS proof for a refinement mapping involving records? - theorem-proving

I have some difficulty in proving a refinement mapping involving records.
Below are the simplified illustrating TLA specs#github (Note that this post is also in tlaplus-googlegroup, without replies yet.):
SimpleVoting.tla:
It maintains for each participant a maxBal which is a natural number.
In IncreaseMaxBal(p, b), maxBal[p] is increased to a larger value b.
---------------------------- MODULE SimpleVoting ----------------------------
EXTENDS Naturals
-----------------------------------------------------------------------------
CONSTANT Participant
VARIABLE maxBal
TypeOK == maxBal \in [Participant -> Nat]
-----------------------------------------------------------------------------
Init == maxBal = [p \in Participant |-> 0]
IncreaseMaxBal(p, b) ==
/\ maxBal[p] < b
/\ maxBal' = [maxBal EXCEPT ![p] = b]
-----------------------------------------------------------------------------
Next == \E p \in Participant, b \in Nat : IncreaseMaxBal(p, b)
Spec == Init /\ [][Next]_maxBal
=============================================================================
Record.tla:
It maintains a 2D "array" state, where state[p][q] is the State of q from the view of p and a State is a record:
State == [maxBal : Nat, maxVBal : Nat].
In Prepare(p, b), state[p][p].maxBal is increased to a larger value b.
------------------------------- MODULE Record -------------------------------
EXTENDS Naturals, TLAPS
---------------------------------------------------------------------------
CONSTANTS Participant \* the set of partipants
VARIABLES state \* state[p][q]: the state of q \in Participant from the view of p \in Participant
State == [maxBal: Nat, maxVBal: Nat]
TypeOK == state \in [Participant -> [Participant -> State]]
---------------------------------------------------------------------------
InitState == [maxBal |-> 0, maxVBal |-> 0]
Init == state = [p \in Participant |-> [q \in Participant |-> InitState]]
Prepare(p, b) ==
/\ state[p][p].maxBal < b
/\ state' = [state EXCEPT ![p][p].maxBal = b]
---------------------------------------------------------------------------
Next == \E p \in Participant, b \in Nat : Prepare(p, b)
Spec == Init /\ [][Next]_state
---------------------------------------------------------------------------
Intuitively, Record maintains maxBal[p] of SimpleVoting as state[p][p].maxBal. Therefore, I want to show that Record refines SimpleVoting under the following refinement mapping:
maxBal == [p \in Participant |-> state[p][p].maxBal]
SV == INSTANCE SimpleVoting
However, step <3>2 in the following proof fails.
THEOREM Spec => SV!Spec
<1>1. Init => SV!Init
BY DEF Init, SV!Init, maxBal, InitState
<1>2. [Next]_state => [SV!Next]_maxBal
<2>1. UNCHANGED state => UNCHANGED maxBal
BY DEF maxBal
<2>2. Next => SV!Next
<3> SUFFICES ASSUME NEW p \in Participant, NEW b \in Nat,
Prepare(p, b)
PROVE SV!IncreaseMaxBal(p, b)
BY DEF Next, SV!Next
<3>1. maxBal[p] < b
BY DEF Prepare, maxBal
<3>2. maxBal' = [maxBal EXCEPT ![p] = b] \* failed here!
BY DEF Prepare, maxBal
<3>3. QED
BY <3>1, <3>2 DEF SV!IncreaseMaxBal
<2>3. QED
BY <2>1, <2>2
<1>3. QED
The obligation at <3>2 is as follows. Isn't the state' = [state EXCEPT ![p] = ...] in the assumption the same as the conclusion [p_1 \in Participant |-> state[p_1][p_1].maxBal]' ...? What is missing? What is wrong with my proof?
ASSUME NEW CONSTANT Participant,
NEW VARIABLE state,
NEW CONSTANT p \in Participant,
NEW CONSTANT b \in Nat,
/\ state[p][p].maxBal < b
/\ state'
= [state EXCEPT
![p] = [state[p] EXCEPT
![p] = [state[p][p] EXCEPT !.maxBal = b]]]
PROVE [p_1 \in Participant |-> state[p_1][p_1].maxBal]'
= [[p_1 \in Participant |-> state[p_1][p_1].maxBal] EXCEPT ![p] = b]

Related

Decide equality with some predicate

I would like to prove that equality is decidable for those a that satisfy some predicate P:
Variable C: Type.
Inductive A: Type:=
| A0: C -> A.
Variable P: A -> Prop.
Variable P_dec: forall a: A, {P a} + {~ P a}.
Definition A_dec: forall a b, {a = b} + {a <> b} + {~ P a}.
But using decide equality, I lose the information that a satisfies P:
intros. destruct (P_dec a). left. decide equality.
I get
a, b: A
p: P a
c, c0: C
----------
{c = c0} + {c <> c0}
and I cannot use the fact that we have P (A0 c). It seems to me that somehow I am legitimate to assume that a = P c - how can I proceed to get this information?
Do you have any hypothesis on C? For instance :
Variable Ceqdec : forall c c':C, {c = c'}+{c <> c'}.
Some types don't have this possibility (e.g; C = nat->nat)
About your other question :
You may start your proof with intros [c] [c0] in order to decompose aand b.

The type checker's behavior while pattern matching in Coq

I'm trying to examine how the type checker works on the following function, but can't understand
how the type checker works in the second (the nested) match clause:
Definition plus_O_2 :=
(fix F (m : mynat) : m == plus m O :=
match m as m0 with
| O as m2 => myeq_refl O : m2 == plus m2 O
| S x as m2 => ((match F x in (m0 == m1) return (S m0 == S m1) with
| myeq_refl x0 => myeq_refl (S x0)
end) : m2 == plus m2 O)
end) : forall n : mynat, n == plus n O.
This is a function that provides proof that forall n : mynat, n == plus n O, where mynat, ==, plus are self-defined natural numbers, equality, and addition:
Inductive mynat :=
| O
| S (x:mynat).
Fixpoint plus (a b:mynat) :=
match a with
| O => b
| S n => S (plus n b)
end.
Inductive myeq {X:Type} : X -> X -> Prop :=
| myeq_refl : forall x, myeq x x.
Notation "x == y" := (myeq x y)
(at level 70, no associativity)
: type_scope.
(The definition for myeq and the corresponding Notation statement was referenced from Software Foundations Vol.1, https://softwarefoundations.cis.upenn.edu/lf-current/ProofObjects.html).
What I'm trying to understand is how Coq manages to type check this function. Here's what I understand of now:
F first receives m. It is expected to return a value of type m == plus m O (The proposition we want to show).
m passes through pattern matching.
If m is O (meant to represent zero), it returns myeq_refl O.
myeq_refl O has type O == O. Meanwhile, from F's definition, it is expected to have type O == plus O O. (My guess is that,) Coq compares these types while type checking, and notices that plus O O is equivalent to O by its definition, so it passes the type check.
If m is of form S x, a second pattern matching starts running.
F x will have the form x == plus x O. This structure is captured in the in clause, and the return clause specifies that the returning type will be S x == S (plus x O).
(I don't understand what happens here)
Since both patterns end up with the type m == plus m O, the function has the type forall n : mynat, n == plus n O.
Now, my questions are, what exactly happens with the type checker in where I wrote "I don't understand what happens here?" Particularly,
In my understanding, as the in clause specifies, F x is expected to have the type m0 == m1. Meanwhile, the matching clause myeq_refl x0 seems to have the type x0 == x0, where both sides are equal. Why does Coq's type checker match these two seemingly different types?
After the match (after =>), the match clause outputs myeq_refl (S x0), which should have type S x0 == S x0. Meanwhile, the return clause stipulates that the returning type should be S m0 == S m1, which in my understanding should be equivalent to S x == S (plus x O). These types, at first glance, seem different. How does Coq find out that these types are in fact equivalent?
Particularly, the second type seems to have a more complicated structure than the original proposition we want to show, n == plus n O, which should mean that Coq should not immediately be able to find that this is in fact equivalent to n == n.
The occurences of m0 and m1 inside the clause in m0 == m1 are actually binding occurences of the variables for the pattern matching construct (in particular for the return clause). Your code is actually the same as
Definition plus_O_2 :=
(fix F (m : mynat) : m == plus m O :=
match m as m0 with
| O as m2 => myeq_refl O : m2 == plus m2 O
| S x as m2 => ((match F x in (p == q) return (S p == S q) with
| myeq_refl x0 => myeq_refl (S x0)
end) : m2 == plus m2 O)
end) : forall n : mynat, n == plus n O.
where I renamed the name of the variables in the inner match.
Now the constructor myeq_refl x is by construction of type x == x which should also be p == q so in that branch, it is enough to build a term of type (S p == S q)[x/p, x/q] (where brackets denote substitution), that is of type S x == S x. Since myeq_refl is the only constructor of this inductive type, you are done with this match once you have provided such a witness.

Supplying section arguments for examples

Consider this section:
Section MyMap.
Variables D R : Type.
Fixpoint mymap (f : D -> R) (l : list D) : list R :=
match l with
| nil => nil
| d :: t => f d :: mymap f t
end.
End MyMap.
Here I've used Variables to declare my domain and range types. As a sanity check on the definition of my function, I would like to include an Example:
Example example_map_S : mymap S [0; 1; 2] = [1; 2; 3].
Proof.
simpl; trivial.
Qed.
However it seems I can't do so within my section. Instead I get:
Error: The term "S" has type "nat -> nat" while it is expected to have type "D -> R".
That's not too surprising, so let's try it another way:
Example example_map_S : #mymap nat nat S [0; 1; 2] = [1; 2; 3].
Proof.
simpl; trivial.
Qed.
Which produces:
Error: The term "nat" has type "Set" while it is expected to have type "D -> R".
I suppose that's fair, section-ized Variables aren't the same thing as implicit arguments. But it still leaves the question!
How can I supply concrete Variables to a term before closing the section, in order to create useful Examples?
Section MyMap.
...
If we check the type of mymap inside the section, we get
Check mymap.
(* mymap : (D -> R) -> list D -> list R *)
Of course, we can't unify D and R with nat, since D and R are some locally postulated types.
However, we can sort of simulate your example in this generalized setting, showing the expected property of the mymap function:
Example example_nil (f : D -> R) :
mymap f [] = [] := eq_refl.
Example example_3elems (f : D -> R) (d0 d1 d2 : D) :
mymap f [d0; d1; d2] = [f d0; f d1; f d2] := eq_refl.
End MyMap.

Function of comparison coq

I want to make a function of natural numbers comparison in coq
I declare a Set of invariant contain sup, inf, egal
Inductive invr:Type:=inf | sup | egal.
And I define a function comparaison
Definition comparaison (inv:invr)(a b:nat):bool:=
match invr with
|inf => if (a < b) then true else false
|sup => if (a > b) then true else false
|egal=> if (a = b) then true else false
end.
But it does not work! Thanks for your response.
You are trying to match type (set) invr with its constructors values instead of variable inv, so you get an error
The term "invr" has type "Set" while it is expected to have type
"invr".
You need to do the matching for inv, not invr
Definition comparaison (inv:invr)(a b:nat):bool:=
match inv with
|inf => if (a < b) then true else false
|sup => if (a > b) then true else false
|egal=> if (a = b) then true else false
end.
Also make sure that you have <, >, = notations are defined to return bool, because by default they return Prop, which can't be used in if/else. So you need to use beq_nat, and leb from Arith.
Simplified final version (removed redundant if/else branches).
Require Import Coq.Arith.Arith.
Inductive invr : Type:= inf | sup | egal.
Definition comparaison (inv:invr)(a b:nat):bool:=
match inv with
|inf => leb a b
|sup => leb b a
|egal=> beq_nat a b
end.
This is a typical beginner mistake.
< stands for lt, which has type:
lt : nat -> nat -> Prop
That is, a < b is just a proposition, not a procedure that computes whether a is less than b!
The same goes for equality.
What you want to use is a function that computes the truth of these propositions, either as a boolean or as a richer type:
In the library Arith:
beq_nat: nat -> nat -> bool
leb: nat -> nat -> bool
(* or the more informative versions which return proofs of what they decide *)
eq_nat_dec: forall n m : nat, {n = m} + {n <> m}
lt_dec: forall n m : nat, {n < m} + {~ n < m}
So the following is a valid expression:
if beq_nat a b then true else false
Also note that the following is a valid expression equivalent to the precedent one (since beq_nat returns a bool):
beq_nat a b

Inside a branch of a match block, how do I use the assertion that the matched expression is equal to the branch's data constructor expression?

I am trying to develop a programming style that is based on preventing bad input as soon as possible. For example, instead of the following plausible definition for the predecessor function on the natural numbers:
Definition pred1 n :=
match n with
| O => None
| S n => Some n
end.
I want to write it as follows:
Theorem nope n (p : n = O) (q : n <> O) : False.
contradict q.
exact p.
Qed.
Definition pred2 n (q : n <> O) :=
match n with
| S n => n
| O =>
let p := _ in
match nope n p q with end
end.
But I have no idea what to replace _ with. My intuition suggests me that there must be some assumption : n = O available in the | O => branch. Does Coq indeed introduce such an assumption? If so, what is its name?
Coq doesn't automatically introduce such hypothesis, but you can introduce it explicitly by using the full form of the match construction:
Definition pred2 n (q : n <> O) :=
match n as n' return n = n' -> nat with
| S p => fun _ => p
| O => fun Heq => match q Heq with end
end (eq_refl n).
Explanations:
return introduces a type annotation with the type of the whole match ... end expression;
as introduces a variable name that can be used in this type annotation and will be substituted with the left hand side in each branch. Here,
in the first branch, the right hand side has type n = S p -> nat;
in the second branch, the right hand side has type n = O -> nat. Therefore, q Heq has type False and can be matched.
More information in the reference manual, in the chapter on Extended pattern-matching.