How to switch types in Lean theorem prover when constants are involved? - theorem-proving

For a newcomer working through the LEAN documentation, it is sometimes quite frustrating to see that some simple problems turn into real bottlenecks when more difficult ones have apparently been solved. Here is what was supposed to be a simple self-produced exercise that turned into a few hours of frustration (there's no other way to LEARN, of course):
theorem prByCont : ∀ P : Prop, ( P → false ) → ¬ P :=
λ (P : Prop) (prf : P → false), prf
#check prByCont
example ( a b : ℕ ) (p: a = 2) (q: b=3) : ¬ (a ≥ b) :=
begin
apply prByCont,
assume h : a ≥ b,
have order : 2 < 3 := dec_trivial,
contradiction
end
The problem seems to be that order has type 2<3 but what is needed is a<b, and although it looks to me that it should be clear that a=2 and b=3, LEAN doesn't think so. Please help me see what I'm missing here!

Related

Real numbers in Coq

In https://www.cs.umd.edu/~rrand/vqc/Real.html#lab1 one can read:
Coq's standard library takes a very different approach to the real numbers: An axiomatic approach.
and one can find the following axiom:
Axiom
completeness :
∀E:R → Prop,
bound E → (∃x : R, E x) → { m:R | is_lub E m }.
The library is not mentioned but in Why are the real numbers axiomatized in Coq? one can find the same description :
I was wondering whether Coq defined the real numbers as Cauchy sequences or Dedekind cuts, so I checked Coq.Reals.Raxioms and... none of these two. The real numbers are axiomatized, along with their operations (as Parameters and Axioms). Why is it so?
Also, the real numbers tightly rely on the notion of subset, since one of their defining properties is that is every upper bounded subset has a least upper bound. The Axiom completeness encodes those subsets as Props."
Nevertheless, whenever I look at https://coq.inria.fr/library/Coq.Reals.Raxioms.html I do not see any axiomatic approach, in particular we have the following lemma:
Lemma completeness :
forall E:R -> Prop,
bound E -> (exists x : R, E x) -> { m:R | is_lub E m }.
Where can I find such an axiomatic approach of the real numbers in Coq?
The description you mention is outdated indeed, because since I asked the question you linked, I rewrote the axioms defining Coq's standard library real numbers in a more standard way. The real numbers are now divided into 2 layers
constructive real numbers, that are defined in terms of Cauchy sequences and that use no axioms at all;
classical real numbers, that are a quotient set of constructive reals, and that do use 3 axioms to prove the least upper bound theorem that you mention.
Coq easily gives you the axioms underlying any term by the Print Assumptions command:
Require Import Raxioms.
Print Assumptions completeness.
Axioms:
ClassicalDedekindReals.sig_not_dec : forall P : Prop, {~ ~ P} + {~ P}
ClassicalDedekindReals.sig_forall_dec
: forall P : nat -> Prop,
(forall n : nat, {P n} + {~ P n}) -> {n : nat | ~ P n} + {forall n : nat, P n}
FunctionalExtensionality.functional_extensionality_dep
: forall (A : Type) (B : A -> Type) (f g : forall x : A, B x),
(forall x : A, f x = g x) -> f = g
As you can see these 3 axioms are purely logical, they do not speak about real numbers at all. They just assume a fragment of classical logic.
If you want an axiomatic definition of the reals in Coq, I provided one for the constructive reals
Require Import Coq.Reals.Abstract.ConstructiveReals.
And this becomes an interface for classical reals if you assume the 3 axioms above.
These descriptions are outdated. It used to be the case that the type R of real numbers was axiomatized, along with its basic properties. But nowadays (since 2019?) it is defined in terms of more basic axioms, more or less like one would do in traditional mathematics.

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.

I can't solve an error "Universes are unbound"

I'm developing a library for googology in Coq. I ran into a problem.
Set Universe Polymorphism.
Set Polymorphic Inductive Cumulativity.
Inductive Sum#{i j} (A : Type#{i}) (B : Type#{j}) : Type#{max(i,j)}
:= left : A -> Sum A B | right : B -> Sum A B.
Definition Foo#{i j k l} (A : Type#{i}) (B : Type#{j}) (C : Type#{k}) : Type#{l}
:= Sum#{i _} A (Sum#{j k} B C).
I expected _ to be filled with max(j,k). However, I got an error:
Universes {***} are unbounded.
Is there a way to express these constraints well?
I feel it makes sense to add ij that satisfies i <= ij and j <= ij. I should have thought more.

Cardinality of finFieldType / Euler's criterion

I am trying to prove a very limited form of Euler's criterion:
Variable F : finFieldType.
Hypothesis HF : (1 != -1 :> F).
Lemma euler (a : F) : a^+(#|F|.-1./2) = -1 -> forall x, x^+2 != a.
I have the bulk of the proof done already, but I am left with odd (#|F|.-1) = 0, that is, #|F|.-1 is even. (I'm not interested in characteristic 2). I can't seem to find useful facts in the math comp library about the cardinality of finFieldTypes. For example, I would expect a lemma saying there exists a p such that prime p and #|F| = p. Am I missing something here?
By the way, I could also have totally missed an already existing proof of Euler's criterion in the math comp library itself.
I am not aware of a proof of Euler's criterion, but I found two lemmas, in finfield, that give you the two results that you expected in order to finish your proof (the second one may not be presented as you expected):
First, you have the following lemma which gives you the prime p corresponding to the characteristic of your field F (as long as it is a finFieldType):
Lemma finCharP : {p | prime p & p \in [char F]}.
Then, another lemma gives you the cardinality argument :
Let n := logn p #|R|.
Lemma card_primeChar : #|R| = (p ^ n)%N.
The problem with the second lemma is that your field should be recognized as a PrimeCharType, which roughly corresponds to a ringType with an explicit characteristic. But given the first lemma, you are able to give such a structure to your field (which canonically has a ringType), on the fly. A possible proof could be the following
Lemma odd_card : ~~ odd (#|F|.-1).
Proof.
suff : odd (#|F|) by have /ltnW/prednK {1}<- /= := finRing_gt1 F.
have [p prime_p char_F] := (finCharP F); set F_pC := PrimeCharType p_char.
have H : #|F| = #|F_primeChar| by []; rewrite H card_primeChar -H odd_exp => {H F_pC}.
apply/orP; right; have := HF; apply: contraR=> /(prime_oddPn prime_p) p_eq2.
by move: char_F; rewrite p_eq2=> /oppr_char2 ->.
Qed.

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!