Is Z.le as defined in the standard library proof irrelevant? - coq

In the Coq standard library, there is an enumerated type called comparison with three elements Eq,Lt,Gt. This is used to define the less-than or less-than-or-equal operators in ZArith: m < n is defined as m ?= n = Lt and m <= n is defined as m ?= n <> Gt. By virtue of Hedberg's theorem (UIP_dec in the standard library) I can prove that < is proof-irrelevant, but I run into issues when it comes to <=, since it is defined negatively. I find this particularly annoying, since if <= were defined in the, IMO, more natural way (m ?= n = Lt \/ m ?= n = Eq) I would be able to prove proof-irrelevance just fine.
Context: I'm using some previously written Coq files where the author uses proof irrelevance as a global axiom to avoid bringing in setoids, and for aesthetic reasons I would prefer to do without axioms. It seems then to me that my options are:
Hope that ultimately Z.le as currently defined is still proof-irrelevant
Use my own definition(s) so that proof irrelevance is provable (less satisfying since I'd like to stick to the standard library as much as possible)
Rework things with setoids

No, this is not provable in Coq. It depends on the axiom of function extensionality, which says that (forall x, f x = g x) -> f = g. It's quite easy to prove that all negations are proof irrelevant under this assumption (since False is proof irrelevant), and quite impossible to prove that any negations are proof irrelevant without it.

Related

Searching for a counterexample to a decidable predicate

It feels like the following Coq statement should be true constructively:
Require Import Decidable.
Lemma dec_search_nat_counterexample (P : nat -> Prop) (decH : forall i, decidable (P i))
: (~ (forall i, P i)) -> exists i, ~ P i.
If there were an upper bound, I'd expect to be able to show something of the form "suppose that not every i < N satisfies P i. Then there is an i < N where ~ P i". Indeed, you could actually write a function to find a minimal example by searching from zero.
Of course, there's not an upper bound for the original claim, but I feel like there should be an inductive argument to get there from the bounded version above. But I'm not clever enough to figure out how! Am I missing a clever trick? Or is there a fundamental reason that this cann't work, despite the well-orderedness of the natural numbers?
Reworked answer after Meven Lennon-Bertrand's comment
This statement is equivalent to Markov's principle with P and ~P exchanged. Since P is decidable we have P <-> (~ ~ P), so that one can do this replacement.
This paper (http://pauillac.inria.fr/~herbelin/articles/lics-Her10-markov.pdf) suggest that Markov's principle is not provable in Coq, since the author (one of the authors of Coq) suggests a new logic in this paper which allows to prove Markov's principle.
Old answer:
This is morally the "Limited Principle of Omniscience" - LPO (see https://en.wikipedia.org/wiki/Limited_principle_of_omniscience). It requires classical axioms to prove it in Coq - or you assert itself as an axiom.
See e.g.:
Require Import Coquelicot.Markov.
Check LPO.
Print Assumptions LPO.
Afair there is no standard library version of it.

Extensionality axiom: why is it not unsound

Axiom of extensionality says that two functions are equal if their actions on each argument of the domain are equal.
Axiom func_ext_dep : forall (A : Type) (B : A -> Type) (f g : forall x, B x),
(forall x, f x = g x) -> f = g.
Equality = on both side of the theorem statement is propositional equality (a datatype with a single eq_refl constructor).
Using this axiom it could be proven that f = a + b and g = b + a are propositionally equal.
But f and g are obviously not equal as data structures.
Could you please explain what I'm missing here?
Probably that function objects don't have normal form?
EDIT: After further discussion in the comments, the actual point of confusion was this:
Doesn't match a with... = match b with gives me False right away the same way as S S Z = S Z does?
You can pattern-match on nat, you can't on functions. Dependent pattern-matching is how we can prove injectivity and disjointness of constructors, whereas the only thing we can do with a function is to apply it. (See also How do we know all Coq constructors are injective and disjoint?)
Nevertheless, I hope the rest of the answer below is still instructive.
From the comments:
AFAIU, = has a very precise meaning in Coq/CIC - syntactic equality of normal forms.
That's not right. For example we can prove the following:
Lemma and_comm : forall a b : bool, (* a && b = b && a *)
match a with
| true => b
| false => false
end = match b with
| true => a
| false => false
end.
Proof.
destruct a, b; reflexivity.
Qed.
We can only use eq_refl when the two sides are syntactically equal, but there are more reasoning rules we can apply beyond the constructors of an inductive propositions, most notably dependent pattern-matching, and, if we admit it, functional extensionality.
But f and g are obviously not equal as data structures.
This statement seems to confuse provability and truth. It's important to distinguish these two worlds. (And I'm not a logician, so take what I'm going to say with a grain of salt.)
Coq is a symbol-pushing game, with well-defined rules to construct terms of certain types. This is provability. When Coq accepts a proof, all we know is that we constructed a term following the rules.
Of course, we also want those terms and types to mean something. When we prove a proposition, we expect that to tell us something about the state of the world. This is truth. And in a way, Coq has very little say in the matter. When we read f = g, we are giving a meaning to the symbol f, a meaning to g, and also a meaning to =. This is entirely up to us (well, there are always rules to follow), and there's more than one interpretation (or "model").
The "naive model" that most people have in mind views functions as relations (also called graphs) between inputs and outputs. In this model, functional extensionality holds: a function is no more than a mapping between inputs and outputs, so two functions with the same mappings are equal. Functional extensionality is sound in Coq (we can't prove False) because there is at least one model where it is valid.
In the model you have, a function is characterized by its code, modulo some equations. (This is more or less the "syntactic model", where we interpret every expression as itself, with the minimal possible amount of semantic behavior.) Then, indeed there are functions that are extensionally equal, but with different code. So functional extentionality is not valid in this model, but that doesn't mean it's false (i.e., that we can prove its negation) in Coq, as justified previously.
f and g are not "obviously not equal", because equality, like everything else, is relative to a particular interpretation.

Extensionally equal predicates and equality of universally quantified applications

I am trying to define a recursive predicate using well-founded fixpoints with the obligation to show F_ext when rewriting with Fix_eq. The CPDT says that most such obligations are dischargeable with straightforward proof automation, but unhappily this does not appear to be so for my predicate.
I have reduced the problem to the following lemma (from Proper (pointwise_relation A eq ==> eq) (#all A)). Is it provable in Coq without additional axioms?
Lemma ext_fa:
forall (A : Type) (f g : A -> Prop),
(forall x, f x = g x) ->
(forall x, f x) = (forall x, g x).
It can be shown with extensionality of predicates or functions, but since the conclusion is weaker than the usual one (f = g) I naively thought it would be possible to produce a proof without using additional axioms. After all, both sides of the equality only involve applications of f and g; how could any intensional differences be discerned?
Have I missed a simple proof or is the lemma unprovable?
You might be interested in this code I wrote a while ago, which includes variants of Fix_eq for various numbers of arguments, and don't depend on function extensionality. Note that you don't need to change Fix_F, and can instead just prove variants of Fix_eq.
To answer the question you asked, rather than solve your context, the lemma you state is called "forall extensionality".
It is present in Coq.Logic.FunctionalExtensionality, where the axiom of function extensionality is used to prove it. The fact that the standard library version uses an axiom to prove this lemma is, at the very least, strong evidence that it is not provable without axioms in Coq.
Here is a proof sketch of that fact. Since Coq is strongly normalizing*, every proof of x = y in the empty context is judgmentally equal to eq_refl. That is, if you can prove x = y in the empty context, then x and y are convertible. Let f x := inhabited (Vector.t (x + 1)) and let g x := inhabited (Vector.t (1 + x)). It is straightforward to prove forall x, f x = g x by induction on x. Therefore, if your lemma were true without axioms, we could get a proof of
(forall x, inhabited (Vector.t (x + 1))) = (forall x, inhabited (Vector.t (1 + x)))
in the empty context, and hence eq_refl ought to prove this statement. We can easily check and see that eq_refl does not prove this statement. So your lemma ext_fa is not provable without axioms.
Note that equality for functions and equality for types are severely under-specified in Coq. Essentially, the only types (or functions) that you can prove equal in Coq are the ones that are judgmentally equal (or, more precisely, the ones that are expressible as two judgmentally equal lambdas applied to provably-equal closed terms). The only types that you can prove not equal are the ones which are provably not isomorphic. The only functions that you can prove not equal are the ones which provably differ on some concrete element of the domain that you provide. There's a lot of space between the equalities that you can prove, and the inequalities you can prove, and you don't get to say anything about things in this space without axioms.
*Coq isn't actually strongly normalizing because there are some issues with coinductives. But modulo that, it's strongly normalizing.

How is "less than" defined for real numbers in Coq?

I am just wondering how is the "less than" relationship defined for real numbers.
I understand that for natural numbers (nat), < can be defined recursively in terms of one number being the (1+) successor S of another number. I heard that many things about real numbers are axiomatic in Coq and do not compute.
But I am wondering whether there is a minimum set of axioms for real numbers in Coq based upon which other properties/relations can be derived. (e.g. Coq.Reals.RIneq has it that Rplus_0_r : forall r, r + 0 = r. is an axiom, among others)
In particular, I am interested in whether the relationships such as < or <= can be defined on top of the equality relationship. For example, I can imagine that in conventional math, given two numbers r1 r2:
r1 < r2 <=> exists s, s > 0 /\ r1 + s = r2.
But does this hold in the constructive logic of Coq? And can I use this to at least do some reasoning about inequalities (instead of rewriting axioms all the time)?
Coq.Reals.RIneq has it that Rplus_0_r : forall r, r + 0 = r. is an axiom, among others
Nitpick: Rplus_0_r is not an axiom but Rplus_0_l is. You can get a list of them in the module Coq.Reals.Raxioms and a list of the parameters used in Coq.Reals.Rdefinitions.
As you can see "greater than (or equal)" and "less than or equal" are all defined in terms of "less than" which is postulated rather than introduced using the proposition you suggest.
It looks like Rlt could indeed be defined in the fashion you suggest: the two propositions are provably equivalent as shown below.
Require Import Reals.
Require Import Psatz.
Open Scope R_scope.
Goal forall (r1 r2 : R), r1 < r2 <-> exists s, s > 0 /\ r1 + s = r2.
Proof.
intros r1 r2; split.
- intros H; exists (r2 - r1); split; [lra | ring].
- intros [s [s_pos eq]]; lra.
Qed.
However you would still need to define what it means to be "strictly positive" for the s > 0 bit to make sense and it's not at all clear that you'd have fewer axioms in the end (e.g. the notion of being strictly positive should be closed under addition, multiplication, etc.).
Indeed, the Coq.Real library is a bit weak in the sense that it is totally specified as axioms, and at some (brief) points in the past it was even inconsistent.
So the definition of le is a bit "ad hoc" in the sense that from the point of view of the system it carries zero computational meaning, being just a constant and a few axioms. You could well add the axiom "x < x" and Coq could do nothing to detect it.
It is worth pointing to some alternative constructions of the Reals for Coq:
My favourite classical construction is the one done in the four Color theorem by Georges Gonthier and B. Werner: http://research.microsoft.com/en-us/downloads/5464e7b1-bd58-4f7c-bfe1-5d3b32d42e6d/
It only uses the excluded middle axiom (mainly to compare real numbers) so the confidence in its consistency is very high.
The best known axiom-free characterization of the reals is the C-CORN project, http://corn.cs.ru.nl/ but we aware that constructive analysis significantly differs from the usual one.

What forms of goal in Coq are considered to be "true"?

When I prove some theorem, my goal evolves as I apply more and more tactics. Generally speaking the goal tends to split into sub goals, where the subgoals are more simple. At some final point Coq decides that the goal is proven. How this "proven" goal may look like? These goals seems to be fine:
a = a. (* Any object is identical to itself (?) *)
myFunc x y = myFunc x y. (* Result of the same function with the same params
is always the same (?) *)
What else can be here or can it be that examples are fundamentally wrong?
In other words, when I finally apply reflexivity, Coq just says ** Got it ** without any explanation. Is there any way to get more details on what it actually did or why it decided that the goal is proven?
You're actually facing a very general notion that seems not so general because Coq has some user-friendly facility for reasoning with equality in particular.
In general, Coq accepts a goal as solved as soon as it receives a term whose type is the type of the goal: it has been convinced the proposition is true because it has been convinced the type that this proposition describes is inhabited, and what convinced it is the actual witness you helped build along your proof.
For the particular case of inductive datatypes, the two ways you are going to be able to proved the proposition P a b c are:
by constructing a term of type P a b c, using the constructors of the inductive type P, and providing all the necessary arguments.
or by reusing an existing proof or an axiom in the environment whose type you can get to match P a b c.
For the even more particular case of equality proofs (equality is just an inductive datatype in Coq), the same two ways I list above degenerate to this:
the only constructor of equality is eq_refl, and to apply it you need to show that the two sides are judgementally equal. For most purposes, this corresponds to goals that look like T a b c = T a b c, but it is actually a slightly more broad notion of equality (see below). For these, all you have to do is apply the eq_refl constructor. In a nutshell, that is what reflexivity does!
the second case consists in proving that the equality holds because you have other equalities in your context, nothing special here.
Now one part of your question was: when does Coq accept that two sides of an equality are equal by reflexivity?
If I am not mistaken, the answer is when the two sides of the equality are αβδιζ-convertible.
What this grossly means is that there is a way to make them syntactically equal by repeated applications of:
α : sane renaming of non-free variables
β : computing reducible expressions
δ : unfolding definitions
ι : simplifying matches
ζ : expanding let-bound expressions
[someone please correct me if more rules apply or if I got one wrong]
For instance some of the things that are not captured by these rules are:
equality of functions that do more or less the same thing in different ways:
(fun x => 0 + x) = (fun x => x + 0)
quicksort = mergesort
equality of terms that are stuck reducing but would be equal:
forall n, 0 + n = n + 0