Looking for some help understanding where I'm going from (Software Foundations, Binom.v) - coq

I am working through Software Foundations and am a bit stuck. Here is a link for reference: https://softwarefoundations.cis.upenn.edu/vfa-current/Binom.html
I am stuck on the proof "abs_perm," reproduced here.
Theorem abs_perm: forall p al bl,
priq p -> Abs p al -> Abs p bl -> Permutation al bl.
This is a "2 star" question, so it should be pretty easy. The fact that it is proving to be difficult makes me think that the issue is my "Abs" relation. My inductive relation is as follows:
Inductive priqueue_elems: list tree -> list key -> Prop :=
| priqueue_elems_base: priqueue_elems [] nil
| priqueue_elems_next_list: forall l b b' v,
priqueue_elems l b ->
Permutation b' (v::b) ->
priqueue_elems (insert v l) b'
The issue I end up having is that I get something like "insert x1 l1 = insert x2 l2" (via inversions in my proof) and I can't go anywhere from there.
insert in this case is not injective...it seems like insert x [] = insert x [Leaf].
The above relation allows me to directly know that I have "priq l" available, but priq is defined such that if there is more than one element, the first is a Leaf so...yeah.
I think the issue is with my relation (which is modeled after their tree_elems), but I'm having a bit of "proof block." My guess is that I shouldn't have insert in the relation construction, but it's unclear what other structure there is to the priqueue.
Another avenue would just to have it straight up on "list tree," but then it seems like well-formedness could be an issue.
Otherwise I need some sort of theorem on insert. I tried a bunch, but wasn't able to get a proof together.
For example,
Lemma equals_inserts_permute: forall l1 l2 p1 p2 v1 v2,
priqueue_elems l1 p1 ->
priqueue_elems l2 p2 ->
insert v1 l1 = insert v2 l2 -> Permutation (v1::p1) (v2::p2)
Which would give me the ability to relate insert that I need, but...I haven't been able to crack that proof either.
Would appreciate any help!

Related

Stuck with a proof

I'm fairly new to Coq, and was doing some Katas on CodeWars for fun and learning.
I'm stuck with one of them and want to hear some ideas from you.
So, I have:
Record iso (A B : Set) : Set :=
bijection {
A_to_B : A -> B;
B_to_A : B -> A;
A_B_A : forall a : A, B_to_A (A_to_B a) = a;
B_A_B : forall b : B, A_to_B (B_to_A b) = b
}.
(* nat_plus_nat : a set having size(nat) more elements than nat. (provided in preloaded) *)
Inductive nat_plus_nat : Set := left (n : nat) | right (n : nat).
Theorem nat_iso_natpnat : iso nat nat_plus_nat.
I have and idea, but I can't implement it, and I don't know if it's feasible. Basically, I want to map every odd nat to one constructor(left, for example) and every even nat to another(right, for example). Will this work? If no, how can it be done?
Right now I'm stuck with the fact, that A_to_B defined as fun n => if odd n then left n else right n and B_to_A defined as fun n => match n with | left n' => n' | right n' => n' end won't give me enough facts to eliminate some cases.
You need to do the math correctly first: find two functions that are inverse of each other.
You initial intent is correct: odd numbers to one side, even numbers to the other side, but what you store on each side should cover all the natural numbers, so you will probably have to divide by 2 somewhere.
For Coq usage, You should load the Arith package, by starting with the following line:
Require Import Arith.
This way, you can benefit from existing functions, like Nat.div2 and Nat.even and all the existing theorems about them. To find the relevant theorems, I suggest commands like:
Search Nat.even 2.
Search Nat.div2.
Last hint: proving properties of Nat.div2 by induction is rather difficult for beginners. Try to use the existing theorems as much as possible. If you choose to perform a proof by induction concerning div2, go look in the sources in file theories/Arith/Div2.v : the author of that file designed a specific induction theorem called ìnd_0_1_SS just for that purpose.

Surprising implicit assumptions in intuitionistic definitions

I'm trying to make sense of something that surprised me. Consider the following two definitions.
Require Import List.
Variable A:Type.
Inductive NoDup : list A -> Prop :=
NoDup_nil : NoDup nil
| NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x :: l).
Inductive Dup : list A -> Prop :=
Dup_hd : forall x l, In x l -> Dup (x :: l)
| Dup_tl : forall x l, Dup l -> Dup (x :: l).
My first intuition was that they say the same thing (but negated). However, #Arthur Azevedo De Amorim showed that they are not exactly equivalent (or see here). If ~ NoDup l -> Dup l then it must be the case that forall (a b:A), ~ a <> b -> a = b. Thus, an extra assumption on the type A sneaks in if one uses ~ NoDup rather than Dup when stating one's proof goal.
I tried to spot where this extra assumption is introduced, to get a mental model of what happened, so I will see it myself next time. My current explanation is that
it is the ~ In x l argument to NoDup_cons that is responsible, because
~ In x l terms can only be created if one can prove that a certain x is different from the first element in the list, the second element in the list, etc.
So when I destruct a term om type NoDup (_::_) I get a term ~ In _ _ that can only have been created for a type A for which ~ a <> b -> a = b must hold.
Q: is that an ok 'informal' way to think about it, or is there a better way to understand it, so I don't fall into that trap again?
Also, I found that the Coq library contains NoDup and not Dup, so perhaps some lemmas are weaker than they need to be, because they were formulated using NoDup instead of Dup. However, they could be formulated with Dup because ~Dup l -> NoDup l.
I think the lesson to take out of this example is that you need to be more careful when thinking about negations in intuitionistic logic. In particular, your statement "they say the same thing (but negated)" makes sense in classical logic: it means either of the equivalent statements P <-> ~Q or ~P <-> Q. However, in intuitionistic logic these two statements are not equivalent, so you would have to be more specific about which of these two (if either) is actually true.
In this case, it is true that NoDup l is equivalent to ~ Dup l. What is not true in general is that Dup l is a normal proposition (recall that a proposition P is called normal if ~~P -> P, in which case it's easy to conclude that P <-> ~~P). Therefore, ~ NoDup l is equivalent to ~~ Dup l, which in general is a strictly weaker statement than Dup l.
One possible way to think about the difference between the two is: from a concrete proof of Dup l, it would be possible to extract a pair of indices such that the corresponding entries of l are equal (not literally as a function in Coq due to the restrictions on eliminating from Prop to Type, but you could definitely prove a lemma that there exists such a pair of indices). On the other hand, a concrete proof of ~ NoDup l simply gives a way to take a purported proof of NoDup l and derive a contradiction from it - from which you can't necessarily extract any particular pair of indices.
(I do agree it's somewhat odd that the standard library has only NoDup and not Dup.)

How does elim work in Coq on /\ and \/?

In Coq Tutorial, section 1.3.1 and 1.3.2, there are two elim applications:
The first one:
1 subgoal
A : Prop
B : Prop
C : Prop
H : A /\ B
============================
B /\ A
after applying elim H,
Coq < elim H.
1 subgoal
A : Prop
B : Prop
C : Prop
H : A /\ B
============================
A -> B -> B /\ A
The second one:
1 subgoal
H : A \/ B
============================
B \/ A
After applying elim H,
Coq < elim H.
2 subgoals
H : A \/ B
============================
A -> B \/ A
subgoal 2 is:
B -> B \/ A
There are three questions. First, in the second example, I don't understand what inference rule (or, logical identity) is applied to the goal to generate the two subgoals. It is clear to me for the first example, though.
The second question, according to the manual of Coq, elim is related to inductive types. Therefore, it appears that elim cannot be applied here at all, because I feel that there are no inductive types in the two examples (forgive me for not knowing the definition of inductive types). Why can elim be applied here?
Third, what does elim do in general? The two examples here don't show a common pattern for elim. The official manual seems to be designed for very advanced users, since they define a term upon several other terms that are defined by even more terms, and their language is ambiguous.
Thank you so much for answering!
Jian, first let me note that the manual is open source and available at https://github.com/coq/coq ; if you feel that the wording / definition order could be improved please open an issue there or feel free to submit a pull request.
Regarding your questions, I think you would benefit from reading some more comprehensive introduction to Coq such as "Coq'art", "Software Foundations" or "Programs and Proofs" among others.
In particular, the elim tactic tries to apply the so called "elimination principle" for a particular type. It is called elimination because in a sense, the rule allows you to "get rid" of that particular object, allowing you to continue on the proof [I recommend reading Dummett for a more throughout discussion of the origins of logical connectives]
In particular, the elimination rule for the ∨ connective is usually written by logicians as follows:
A B
⋮ ⋮
A ∨ B C C
────────────────
C
that is to say, if we can derive C independently from A and B, then we can derive it from A ∨ B. This looks obvious, doesn't it?
Going back to Coq, it turns out that this rule has a computational interpretation thanks to the "Curry-Howard-Kolmogorov" equivalence. In fact, Coq doesn't provide most of the standard logical connectives as a built in, but it allow us to define them by means of "Inductive" datatypes, similar to those in Haskell or OCaml.
In particular, the definition of ∨ is:
Inductive or (A B : Prop) : Prop :=
| or_introl : A -> A \/ B
| or_intror : B -> A \/ B
that is to say, or A B is the piece of data that either contains an A or a B, together with a "tag", that allows us to "match" to know which one do we really have.
Now, the "elimination principle for or" has type:
or_ind : forall A B P : Prop, (A -> P) -> (B -> P) -> A \/ B -> P
The great thing of Coq is that such principle is not a "built-in", just a regular program! Think, could you write the code of the or_ind function? I'll give you a hint:
Definition or_ind A B P (hA : A -> P) (hB : B -> P) (orW : A ‌\/ B) :=
match orW with
| or_introl aW => ?
| or_intror bW => ?
end.
Once this function is defined, all that elim does, is to apply it, properly instantiating the variable P.
Exercise: solve your second example using apply and ord_ind instead of elim. Good luck!

Strong Induction on Lists

I'm trying to prove that a proposition P holds for every element of a type A. Unfortunately, I only know how to prove P for a given a:A if I have access to proofs of P for all a' less than a.
This should be provable by induction on a list containing all elements of A, starting with the smallest element in A and then incrementally proving that P holds for all other elements, but I just can't get it to work.
Formally, the problem is the following:
Parameter A : Type.
Parameter lt : A -> A -> Prop.
Notation "a < b" := (lt a b).
Parameter P : A -> Prop.
Parameter lma : forall a, (forall a', a' < a -> P a') -> P a.
Goal forall a, P a.
I may have made a mistake formalizing this problem. Feel free to assume reasonable constraints on the inputs, e.g. A can be assumed to be enumerable, lt can be transitive, decidable ...
This looks at lot like well founded induction. If you can prove that your lt function is well-founded, then your goal becomes trivial. You can find example of such proofs on naturals here
You also have to prove that the relation is well-founded. There's a relevant standard library module. From there, you should prove well_founded A for your A type, and then you can use well_founded_ind to prove P for all values.

Can I extract a Coq proof as a Haskell function?

Ever since I learned a little bit of Coq I wanted to learn to write a Coq proof of the so-called division algorithm that is actually a logical proposition: forall n m : nat, exists q : nat, exists r : nat, n = q * m + r
I recently accomplished that task using what I learned from Software Foundations.
Coq being a system for developing constructive proofs, my proof is in effect a method to construct suitable values q and r from values m and n.
Coq has an intriguing facility for "extracting" an algorithm in Coq's algorithm language (Gallina) to general-purpose functional programming languages including Haskell.
Separately I have managed to write the divmod operation as a Gallina Fixpoint and extract that. I want to note carefully that that task is not what I'm considering here.
Adam Chlipala has written in Certified Programming with Dependent Types that "Many fans of the Curry-Howard correspondence support the idea of extracting programs from proofs. In reality, few users of Coq and related tools do any such thing."
Is it even possible to extract the algorithm implicit in my proof to Haskell? If it is possible, how would it be done?
Thanks to Prof. Pierce's summer 2012 video 4.1 as Dan Feltey suggested, we see that the key is that the theorem to be extracted must provide a member of Type rather than the usual kind of propositions, which is Prop.
For the particular theorem the affected construct is the inductive Prop ex and its notation exists. Similarly to what Prof. Pierce has done, we can state our own alternate definitions ex_t and exists_t that replace occurrences of Prop with occurrences of Type.
Here is the usual redefinition of ex and exists similarly as they are defined in Coq's standard library.
Inductive ex (X:Type) (P : X->Prop) : Prop :=
ex_intro : forall (witness:X), P witness -> ex X P.
Notation "'exists' x : X , p" := (ex _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
Here are the alternate definitions.
Inductive ex_t (X:Type) (P : X->Type) : Type :=
ex_t_intro : forall (witness:X), P witness -> ex_t X P.
Notation "'exists_t' x : X , p" := (ex_t _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
Now, somewhat unfortunately, it is necessary to repeat both the statement and the proof of the theorem using these new definitions.
What in the world??
Why is it necessary to make a reiterated statement of the theorem and a reiterated proof of the theorem, that differ only by using an alternative definition of the quantifier??
I had hoped to use the existing theorem in Prop to prove the theorem over again in Type. That strategy fails when Coq rejects the proof tactic inversion for a Prop in the environment when that Prop uses exists and the goal is a Type that uses exists_t. Coq reports "Error: Inversion would require case analysis on sort Set which is not allowed
for inductive definition ex." This behavior occurred in Coq 8.3. I am not certain that it
still occurs in Coq 8.4.
I think the need to repeat the proof is actually profound although I doubt that I personally am quite managing to perceive its profundity. It involves the facts that Prop is "impredicative" and Type is not impredicative, but rather, tacitly "stratified". Predicativity is (if I understand correctly) vulnerability to Russell's paradox that the set S of sets that are not members of themselves can neither be a member of S, nor a non-member of S. Type avoids Russell's paradox by tacitly creating a sequence of higher types that contain lower types. Because Coq is drenched in the formulae-as-types interpretation of the Curry-Howard correspondence, and if I am getting this right, we can even understand stratification of types in Coq as a way to avoid Gödel incompleteness, the phenomenon that certain formulae express constraints on formulae such as themselves and thereby become unknowable as to their truth or falsehood.
Back on planet Earth, here is the repeated statement of the theorem using "exists_t".
Theorem divalg_t : forall n m : nat, exists_t q : nat,
exists_t r : nat, n = plus (mult q m) r.
As I have omitted the proof of divalg, I will also omit the proof of divalg_t. I will only mention that we do have the good fortune that proof tactics including "exists" and "inversion" work just the same with our new definitions "ex_t" and "exists_t".
Finally, the extraction itself is accomplished easily.
Extraction Language Haskell.
Extraction "divalg.hs" divalg_t.
The resulting Haskell file contains a number of definitions, the heart of which is the reasonably nice code, below. And I was only slightly hampered by my near-total ignorance of the Haskell programming language. Note that Ex_t_intro creates a result whose type is Ex_t; O and S are the zero and the successor function from Peano arithmetic; beq_nat tests Peano numbers for equality; nat_rec is a higher-order function that recurs over the function among its arguments. The definition of nat_rec is not shown here. At any rate it is generated by Coq according to the inductive type "nat" that was defined in Coq.
divalg :: Nat -> Nat -> Ex_t Nat (Ex_t Nat ())
divalg n m =
case m of {
O -> Ex_t_intro O (Ex_t_intro n __);
S m' ->
nat_rec (Ex_t_intro O (Ex_t_intro O __)) (\n' iHn' ->
case iHn' of {
Ex_t_intro q' hq' ->
case hq' of {
Ex_t_intro r' _ ->
let {k = beq_nat r' m'} in
case k of {
True -> Ex_t_intro (S q') (Ex_t_intro O __);
False -> Ex_t_intro q' (Ex_t_intro (S r') __)}}}) n}
Update 2013-04-24: I know a bit more Haskell now. To assist others in reading the extracted code above, I'm presenting the following hand-rewritten code that I claim is equivalent and more readable. I'm also presenting the extracted definitions Nat, O, S, and nat_rec that I did not eliminate.
-- Extracted: Natural numbers (non-negative integers)
-- in the manner in which Peano defined them.
data Nat =
O
| S Nat
deriving (Eq, Show)
-- Extracted: General recursion over natural numbers,
-- an interpretation of Nat in the manner of higher-order abstract syntax.
nat_rec :: a1 -> (Nat -> a1 -> a1) -> Nat -> a1
nat_rec f f0 n =
case n of {
O -> f;
S n0 -> f0 n0 (nat_rec f f0 n0)}
-- Given non-negative integers n and m, produce (q, r) with n = q * m + r.
divalg_t :: Nat -> Nat -> (Nat, Nat)
divalg_t n O = (O, n) -- n/0: Define quotient 0, remainder n.
divalg_t n (S m') = divpos n m' -- n/(S m')
where
-- Given non-negative integers n and m',
-- and defining m = m' + 1,
-- produce (q, r) with n = q * m + r
-- so that q = floor (n / m) and r = n % m.
divpos :: Nat -> Nat -> (Nat, Nat)
divpos n m' = nat_rec (O, O) (incrDivMod m') n
-- Given a non-negative integer m' and
-- a pair of non-negative integers (q', r') with r <= m',
-- and defining m = m' + 1,
-- produce (q, r) with q*m + r = q'*m + r' + 1 and r <= m'.
incrDivMod :: Nat -> Nat -> (Nat, Nat) -> (Nat, Nat)
incrDivMod m' _ (q', r')
| r' == m' = (S q', O)
| otherwise = (q', S r')
The current copy of Software Foundations dated July 25, 2012, answers this quite concisely in the late chapter "Extraction2". The answer is that it can certainly be done, much like this:
Extraction Language Haskell
Extraction "divalg.hs" divalg
One more trick is necessary. Instead of a Prop, divalg must be a Type. Otherwise it will be erased in the process of extraction.
Uh oh, #Anthill is correct, I haven't answered the question because I don't know how to explain how Prof. Pierce accomplished that in his NormInType.v variant of his Norm.v and MoreStlc.v.
OK, here's the rest of my partial answer anyway.
Where "divalg" appears above, it will be necessary to provide a space-separated list of all of the propositions (which must each be redefined as a Type rather than a Prop) on which divalg relies. For a thorough, interesting, and working example of a proof extraction, one may consult the chapter Extraction2 mentioned above. That example extracts to OCaml, but adapting it for Haskell is simply a matter of using Extraction Language Haskell as above.
In part, the reason that I spent some time not knowing the above answer is that I have been using the copy of Software Foundations dated October 14, 2010, that I downloaded in 2011.