Proving Gauss' theorem for nat in Coq - coq

I'd like to prove Gauss' theorem for nat.
In plain (non-precise) language it says: if a divides b*c and none of a's factors are in b then they must all be in c.
Require Import NPeano.
Theorem Gauss_nat: forall (a b c:nat), gcd a b = 1 -> (a | (b*c)) -> (a | c).
The theorem is already defined for integers Z, see here in the Coq manual. But I need it for nat. The recommendations I have gotten so far is to use Bezout's lemma which states that
Lemma Bezout: forall (a b c:Z), Z.gcd a b = c -> exists u v, u*a+v*b=c.
However, I can't use it directly for nats since the coefficients u and v might be negative and thus it doesn't hold for nat.
Is there another proof that does not use integers in the proof?
EDIT:
As was pointed out in a comment by Mark Dickinson, the theorem and lemma are already in Coq's library. They are in NPeano, named Nat.gcd_bezout and Nat.gauss.

If you just want to obtain the result for nat, and not really avoid the use of Z, you can just reuse the proof in the standard library. Here's a sketch of how you could proceed, relying on two auxiliary lemmas:
Require Import NPeano.
Require Import ZArith.
Require Import ZArith.Znumtheory.
Require Import Omega.
Close Scope Z_scope.
Lemma Zdiv_Ndiv a b : (a | b) <-> (Z.of_nat a | Z.of_nat b)%Z.
Proof. Admitted.
Lemma Zgcd_Ngcd a b : Z.of_nat (gcd a b) = Z.gcd (Z.of_nat a) (Z.of_nat b).
Proof. Admitted.
Theorem Gauss_nat a b c : gcd a b = 1 -> (a | (b*c)) -> (a | c).
Proof.
rewrite Zdiv_Ndiv, Zdiv_Ndiv, Nat2Z.inj_mul.
intros H1 H2.
assert (H3 : Z.of_nat (gcd a b) = 1%Z) by (rewrite H1; reflexivity).
rewrite Zgcd_Ngcd in H3.
apply (Gauss _ _ _ H2).
now rewrite <- Zgcd_1_rel_prime.
Qed.

Related

Using or_comm in Coq

I want to prove the following theorem:
Theorem T14 : forall s t u,
S u s t <-> S u t s.
Where S is defined like this:
Definition S u s t := forall v,
((ObS u v) <-> (ObS v s \/ ObS v t)).
The first tactics I used are:
Proof.
intros s t u.
unfold S.
And my goal is now:
1 subgoal
s, t, u : Entity
______________________________________(1/1)
(forall v : Entity, ObS u v <-> ObS v s \/ ObS v t) <->
(forall v : Entity, ObS u v <-> ObS v t \/ ObS v s)
It feels like the proof can be finished if I use the commutativity of the OR operator, and then apply the tauto tactic. However, I don't know how to rewrite the inner bit of only the right part of the equivalence. Is it possible?
This can be done using generalized rewriting.
Require Setoid.
Use setoid_rewrite because you are rewriting under a binder (forall v). (Without binders, rewrite would be sufficient).
It works out-of-the-box in this case, but when your project gets more sophisticated, with your own combinators/logical connectives, some work will be necessary to ensure that "rewriting" is sound. The reference manual describes the set up required by generalized rewriting.
(* 1 *)
Require Import Setoid.
Parameter T : Type.
Parameter ObS : T -> T -> Prop.
Definition S u s t := forall v,
((ObS u v) <-> (ObS v s \/ ObS v t)).
Theorem T14 : forall s t u,
S u s t <-> S u t s.
Proof.
intros s t u.
unfold S.
(* 2 *)
setoid_rewrite (or_comm (ObS _ s)).
reflexivity.
Qed.

What is the right proof term so that the ssreflect tutorial work with the exact: hAiB example?

I was going through the tutorial https://hal.inria.fr/inria-00407778/document for ssreflect and they have the proof:
Variables A B C : Prop.
Hypotheses (hAiBiC : A -> B -> C) (hAiB : A -> B) (hA : A).
Lemma HilbertS2 :
C.
Proof.
apply: hAiBiC; first by apply: hA.
exact: hAiB.
Qed.
but it doesn't actually work since the goal is
B
which puzzled me...what is this not working because the coq version changed? Or perhaps something else? What was the exact argument supposed to be anyway?
I think I do understand what the exact argument does. It completes the current subgoal by making sure the proof term (program) given has the type of the current goal. e.g.
Theorem add_easy_induct_1_exact:
forall n:nat,
n + 0 = n.
Proof.
exact (fun n : nat =>
nat_ind (fun n0 : nat => n0 + 0 = n0) eq_refl
(fun (n' : nat) (IH : n' + 0 = n') =>
eq_ind_r (fun n0 : nat => S n0 = S n') eq_refl IH) n).
Qed.
for the proof of addition's commutativity.
Module ssreflect1.
(* Require Import ssreflect ssrbool eqtype ssrnat. *)
From Coq Require Import ssreflect ssrfun ssrbool.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Theorem three_is_three:
3 = 3.
Proof. by []. Qed.
(*
https://stackoverflow.com/questions/71388591/what-does-apply-tactic-on-its-own-do-in-coq-i-e-without-specifying-a-rul
*)
Lemma HilbertS :
forall A B C : Prop,
(A -> B -> C) -> (A -> B) -> A -> C.
(* A ->(B -> C)*)
Proof.
move=> A B C. (* since props A B C are the 1st things in the assumption stack, this pops them and puts them in the local context, note using the same name as the proposition name.*)
move=> hAiBiC hAiB hA. (* pops the first 3 premises from the hypothesis stack with those names into the local context *)
move: hAiBiC. (* put hAiBiC tactic back *)
apply.
by [].
(* move: hAiB.
apply. *)
by apply: hAiB.
(* apply: hAiB.
by [].dd *)
Qed.
Variables A B C : Prop.
Hypotheses (hAiBiC : A -> B -> C) (hAiB : A -> B) (hA : A).
Lemma HilbertS2 :
C.
Proof.
apply: hAiBiC; first by apply: hA.
exact: hAiB.
Qed.
Lemma HilbertS2 :
C.
Proof.
(* apply: hAiBiC; first by apply: hA. *)
apply: hAiBiC. (* usually we think of : as pushing to the goal stack, so match c with conclusion in
selected hypothesis hAiBiC and push the replacement, so put A & B in local context. *)
by apply: hA. (* discharges A *)
exact: hAiB.
End ssreflect1.
full script I was using. Why does that not put the hypothesis in the local context?
The reason why your example fails is probably that you did not open a section. The various hypotheses that you declare are then treated as "axioms" and not in the context of the goal.
On the other hand, if you start a section before the fragment of text that you posted, everything works, because then the goal before the exact: hAiB. tactic also contains hypothesis hA, which is necessary for exact: to succeed.
Here is the full script (tested on coq 8.15.0)
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Section sandbox.
Variables A B C : Prop.
Hypotheses (hAiBiC : A -> B -> C) (hAiB : A -> B) (hA : A).
Lemma HilbertS2 :
C.
Proof.
apply: hAiBiC; first by apply: hA.
exact: hAiB.
Qed.
End sandbox.

Coinductive principle for streams

I am trying to prove the following principle for stream predicates (defined in the standard library).
From Coq Require Import Streams.
Lemma mystream_ind :
forall A (P : Stream A -> Prop),
(forall s, ForAll P (tl s) -> ForAll P s) ->
forall s, ForAll P s.
Proof.
intros A P H.
cofix Cof.
destruct s as [a s].
constructor; auto.
destruct (H (Cons a s) (Cof s)); auto.
Fail Guarded.
Abort.
From my understanding of the syntactical guard conditions imposed by cofix, I will never be able to complete the proof this way because in the proof term, Cof s must appear under H, which is not a constructor nor a match, etc.
Is there another way to do it in Coq? I defined ForAll as an explicit fixpoint with paco and tried to prove the principle, without success (I couldn't instantiate H at all).
EDIT: this lemma is not provable as False can be derived from it by taking P := fun s => False (thank you Maƫlan).

Disjunctive Syllogism tactic in Coq?

I am learning propositional logic and the rules of inference. The Disjunctive Syllogism rule states that if we have in our premises (P or Q), and also (not P); then we can reach Q.
I can not for the life of me figure out how to do this in Coq. Let's say I have :
H : A \/ B
H0 : ~ A
______________________________________(1/1)
What tactic should I use to reach
H1 : B.
As an extra, I would be glad if someone could share with me the Coq tactic equivalents of basic inference rules, like modus tollens, or disjunctive introduction etc. Is there maybe a plugin I can use?
Coq does not have this tactic built-in, but fortunately you can define your own tactics. Notice that
destruct H as [H1 | H1]; [contradiction |].
puts H1 : B in the context, just as you asked. So you can create an alias for this combined tactic:
Ltac disj_syllogism AorB notA B :=
destruct AorB as [? | B]; [contradiction |].
Now we can easily imitate the disjunctive syllogism rule like so:
Section Foo.
Context (A B : Prop) (H : A \/ B) (H0 : ~ A).
Goal True.
disj_syllogism H H0 H1.
End Foo.
Let me show a couple less automated approaches:
Ltac disj_syllogism AorB notA B :=
let A := fresh "A" in
destruct AorB as [A | B]; [contradiction (notA A) |].
This approach does not ask Coq to find a contradiction, it provides it directly to the contradiction tactic (notA A term). Or we could have used an explicit term with the pose proof tactic:
Ltac disj_syllogism AorB notA B :=
pose proof (match AorB with
| or_introl a => False_ind _ (notA a)
| or_intror b => b
end) as B.
I hope this helps. I'm not sure if some extra explanation is needed -- feel free to ask for clarification and I'll update my answer.
I think you maybe have the wrong expectations on how Coq works? The general way of proving this is essentially a truth-table on the different possibilities:
Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
intuition.
Show Proof.
Qed.
(fun (a b : Prop) (H : (a \/ b) /\ ~ a) =>
and_ind
(fun (H0 : a \/ b) (H1 : ~ a) =>
or_ind (fun H2 : a => let H3 : False := H1 H2 in False_ind b H3)
(fun H2 : b => H2) H0) H)
If you look at the resulting proof-term, you see the Coq is essentially taking apart the boolean the constructors. We can do this manually and get the same proof-term:
Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
intros a b H.
induction H.
induction H.
contradict H. exact H0.
exact H.
Qed.
Whereas e.g. modus ponens corresponds to an apply in Coq, I don't think this is "built in" in any direct way.
Afterwards, you can use this lemma (and I'm sure there's a corresponding version somewhere in the standard library) to derive your additional hypothesis through apply.

Is one being penalized by using 'same_relation' (and possibly other library definitions)?

Given any programming language, whenever a standard library function exists, we should most likely use it rather than write our own code. One would think that this advice applies equally to Coq. However, I recently forced myself to use the same_relation predicate of the Relation module, and I am left with the feeling of being worse off. So I must be missing something, hence my question. To illustrate what I mean let us consider to possible relations:
Require Import Relations. (* same_relation *)
Require Import Setoids.Setoid. (* seems to be needed for rewrite *)
Inductive rel1 {A:Type} : A -> A -> Prop :=
| rel1_refl : forall x:A, rel1 x x. (* for example *)
Inductive rel2 {A:Type} : A -> A -> Prop :=
| rel2_refl : forall x:A, rel2 x x. (* for example *)
The specific details of these relations do not matter here, as long as rel1 and rel2 are equivalent. Now, if I want to ignore the Coq library, I could simply state:
Lemma L1: forall (A:Type)(x y:A), rel1 x y <-> rel2 x y.
Proof.
(* some proof *)
Qed.
and if I want to follow my instinct and use the Coq library:
Lemma L2: forall (A:Type), same_relation A rel1 rel2.
Proof.
(* some proof *)
Qed.
In the simplest of cases, it seems that having proven lemma L1 or Lemma L2 is equally beneficial:
Lemma application1: forall (A:Type) (x y:A),
rel1 x y -> rel2 x y (* for example *)
Proof.
intros A x y H. apply L1 (* or L2 *) . exact H.
Qed.
Whether I decide to use apply L1 or apply L2 makes no difference...
However in practice, we are likely to be faced with a more complicated goal:
Lemma application2: forall (A:Type) (x y:A) (p:Prop),
p /\ rel1 x y -> p /\ rel2 x y.
Proof.
intros A x y p H. rewrite <- L1. exact H.
Qed.
My point here is that replacing rewrite <- L1 by rewrite <- L2 will fail. This is also true of the previous example, but at least I was able to use apply rather than rewrite. I cannot use apply in this case (unless I go through the trouble of splitting my goal). So it seems that I have lost the convenience of using rewrite, if I only have Lemma L2.
Using rewrite on results which are an equivalence (not just an equality) is very convenient. It seems that wrapping an equivalence into the predicate same_relation takes away this convenience. Was I right to follow my instinct and force myself to use same_relation? More generally, is it so true that if a construct is defined in the standard Coq library, I should use it, rather than define my own version of it?
You pose two questions, I try to answer separately:
Regarding your rewrite problem, this problem is natural as the definition of same_relation goes as double inclusion. I agree that maybe a definition using iff would be more convenient. It would really depend on the kind of goals you have. A possible solution for your problem is to define a view:
Lemma L1 {A:Type} {x y:A} : rel1 x y <-> rel2 x y.
Proof.
Admitted.
Lemma L2 {A:Type} : same_relation A rel1 rel2.
Proof.
Admitted.
Lemma U {T} {R1 R2 : relation T} :
same_relation _ R1 R2 -> forall x y, R1 x y <-> R2 x y.
Proof. now destruct 1; intros x y; split; auto. Qed.
Lemma application2 {A:Type} {x y:A} {p:Prop} :
p /\ rel1 x y -> p /\ rel2 x y.
Proof. now rewrite (U L2). Qed.
Note also that rewriting with a <-> relation is not really based on equality, but on "setoid rewriting". In fact, the following doesn't hold in Coq A <-> B -> A = B.
Regarding your second question, whether to use the Coq standard library is a highly subjective topic. I personally rarely use it, I prefer a different library called math-comp, but YMMV. Regarding relations, mathcomp is mostly specialized into boolean relations rel x y = x -> y -> bool, thus, equivalence is simply defined as equality, typically, given r1 r2 you'd write r1 =2 r2.
IMHO in the end, such choices are highly dependent on your application domain.
[edit]: Note that the Relation library is dated:
Naive set theory in Coq. Coq V6.1. This work was started in July 1993 by F. Prost.
So indeed, it may not be the best modern base to build Coq developments on.