Binary search Tree in Coq. Trouble to use ( e0 : (val ?= n) = true ) to prove val = n - coq

As I said I have on hypothesis
e0 : (val =? n) = true
and I have to prove val = n
Inductive is_found : nat -> abr -> bool -> Prop :=
|is_not_found_nil : forall (n : nat), (is_found n nil false)
|is_found_node_eq : forall (n val : nat) (fg fd : abr), val = n -> (is_found n (Node val fg fd) (val =? n))
|is_found_node_lt : forall (n val : nat) (fg fd : abr) (res : bool), val > n -> (is_found n fg res) -> (is_found n (Node val fg fd) res)
|is_found_node_gt : forall (n val : nat) (fg fd : abr) (res : bool), val < n -> (is_found n fd res) -> (is_found n (Node val fg fd) res).
(* fonction *)
Fixpoint find (n : nat) (a : abr) : bool :=
match a with
|nil => false
|(Node val f1 f2) => if (val =? n) then true else match (lt_dec val n) with
|left _ => (find n f2)
|right _ => (find n f1)
end
end.
Functional Scheme find_ind := Induction for find Sort Prop.
Goal forall (n : nat) (a : abr), (is_found n a (find n a)).
induction a.
simpl.
apply is_not_found_nil.
functional induction (find n (Node n0 a1 a2)) using find_ind.
apply is_not_found_nil.
rewrite <- e0.
apply is_found_node_eq.
3 subgoals
n, n0 : nat
a1, a2 : abr
IHa1 : is_found n a1 (find n a1)
IHa2 : is_found n a2 (find n a2)
val : nat
f1, f2 : abr
e0 : (val =? n) = true
______________________________________(1/3)
val = n
______________________________________(2/3)
is_found n (Node val f1 f2) (find n f2)
______________________________________(3/3)
is_found n (Node val f1 f2) (find n f1)

You want to use the lemma beq_nat_true.
If I execute
Require Import Coq.Arith.Arith.
Search "=?".
I see
Nat.eqb_refl: forall x : nat, (x =? x) = true
beq_nat_refl: forall n : nat, true = (n =? n)
Nat.eqb_sym: forall x y : nat, (x =? y) = (y =? x)
Nat.eqb_spec: forall x y : nat, Bool.reflect (x = y) (x =? y)
beq_nat_eq: forall n m : nat, true = (n =? m) -> n = m
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
Nat.eqb_eq: forall n m : nat, (n =? m) = true <-> n = m
beq_nat_false: forall n m : nat, (n =? m) = false -> n <> m
Nat.eqb_neq: forall x y : nat, (x =? y) = false <-> x <> y
Nat.eqb_compat:
Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq))
Nat.eqb
Nat.eqb_compare:
forall x y : nat, (x =? y) = match x ?= y with
| Eq => true
| _ => false
end
Nat.bit0_eqb: forall a : nat, Nat.testbit a 0 = (a mod 2 =? 1)
Nat.pow2_bits_eqb: forall n m : nat, Nat.testbit (2 ^ n) m = (n =? m)
Nat.setbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.setbit a n) m = ((n =? m) || Nat.testbit a m)%bool
Nat.clearbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.clearbit a n) m = (Nat.testbit a m && negb (n =? m))%bool
Nat.testbit_eqb: forall a n : nat, Nat.testbit a n = ((a / 2 ^ n) mod 2 =? 1)
You could also do
Search ((_ =? _) = true).
which gives you the lemmas which contain a subterm matching the pattern ((_ =? _) = true), which is the subset
Nat.eqb_refl: forall x : nat, (x =? x) = true
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
Nat.eqb_eq: forall n m : nat, (n =? m) = true <-> n = m
Of these, it looks like
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
does what you want. You should be able to solve your goal with any of
now apply beq_nat_true.
auto using beq_nat_true.
apply beq_nat_true, e0.
apply beq_nat_true in e0; exact e0.
apply beq_nat_true in e0; subst; reflexivity.
now apply beq_nat_true in e0.
If you want to turn this into a tactic, you can write something like
Ltac beq_nat_to_eq :=
repeat match goal with
| [ H : (_ =? _) = true |- _ ] => apply beq_nat_true in H
| [ H : (_ =? _) = false |- _ ] => apply beq_nat_false in H
end.

Related

Proof that "if m <= n then max(m, n) = n" in Coq

Yesterday I asked a question here about a proof in Coq and the answer helped me a lot, I was able to solve many exercises alone and discover new features. Today I have another exercise, which states that For all m, n, if m <= n then max(m,n) = n. I tried to do induction after m, but I got stuck. Any help would be appreciated!
Fixpoint max (m n : Nat) : Nat :=
match m with
| O => n
| S m' => match n with
| O => m
| S n' => S (max m' n')
end
end.
Fixpoint le_Nat (m n : Nat) : bool :=
match m with
| O => true
| S m' => match n with
| O => false
| S n' => (le_Nat m' n')
end
end.
Lemma:
Lemma le_max_true :
forall m n,
le_Nat m n = true ->
max m n = n.
Proof.
...
Qed.
Let's consider the 4th sub-goal.
1 goal (ID 39)
m : nat
IHm : forall n : nat, le_nat m n = true -> max m n = n
n : nat
============================
le_nat m n = true -> S (max m n) = S n
rewrite IHm is able to replace (max m N) with N(for any N), under the condition le_nat m N = true.
By an intro H, you push an hypothesis of type le_nat m n = true into the context. Then your rewrite IHm generates two (trivial) sub-goals.
In short, in order to solve the 4th sub-goal, you may start with intro H; rewrite IHm.
If you forget the intro H, you get an unsolvable goal:
m : Nat
IHm : forall n : Nat, le_Nat m n = true -> max m n = n
n : Nat
============================
le_Nat m n = true
You need to do induction on both m and n (m and then n). After that, the goal is relatively straightforward.

Is CoInductive "extensionality" sound in Coq? Is it generalizable?

My understanding is that the typical notion of equality is too weak to prove many intuitive equalities on possibly infinite coinductive terms. Therefore it is necessary to introduce a coinductive equality for the specific coinductive type in question.
For instance, I have the following coinductive definitions concerning infinite relation transition sequences:
Section Paths.
Context {state : Type}.
Variable R : relation state.
CoInductive path (s: state) : Type :=
| step : forall s', R s s' -> path s' -> path s.
CoInductive path_eq : forall {s}, path s -> path s -> Prop :=
| path_eq_intro : forall x y r p p',
path_eq p p' ->
path_eq (step x y r p) (step x y r p').
It would be quite desirable then to extend our core equality accordingly:
Axiom path_extensionality : forall s (p q: path s),
path_eq p q -> p = q.
While this axiom makes sense intuitively, are such coinductive extensionality principles known to be sound in general?
Also, I'm concerned that I would have to add a new axiom for each coinductive type I use. Is there a generic way to introduce an extensionality principle for arbitrary coinductive types?
While this axiom makes sense intuitively, are such coinductive extensionality principles known to be sound in general?
Yes. There's an isomorphism between coinductive types and function types. A coinductive type modulo coinductive extensionality is isomorphic to the type of functions from it's index type to its data type modulo function extensionality. So, for example, Stream A modulo EqSt (from Coq.Lists.Streams) is isomorphic to nat -> A modulo function extensionality. Your datatype modulo path_extensionality is roughly isomorphic to { st : nat -> state | forall n, R (st n) (st (S n)) } modulo function extensionality. The trick I'm pulling with your datatype here is to transform it into one that is parameterized instead of indexed; your datatype is morally parameterized over Stream state.
There's unfortunately no way to introduce all the extensionality axioms at once, unless you want to give up coinductives and switch to functions (in which case you can just use the standard library axiom Coq.Logic.FunctionalExtensionality.functional_extensionality_dep). However, you could use a weaker axiom combined with function extensionality: the weaker axiom for a given coinductive type would say that if you go from the coinductive to the corresponding function and then back, you get back what you started with. Another way of phrasing this is that you can axiomatize only one direction of the isomorphism, rather than both directions. This is weaker in the sense that each coinductive extensionality axiom implies function extensionality for the corresponding function type, but this axiom does not.
In case you want some code, here's some code showing the formal isomorphism for standard library streams and for your type (works in Coq 8.13):
Require Import Coq.Lists.Streams.
Require Import Coq.Setoids.Setoid.
Module StreamsExt.
Section __.
Context (A : Type).
Definition t := Stream A.
Definition index := nat.
Definition data := A.
(** inclusion, injection, section, monomorphism *)
(** From a function [nat -> A], we can build a [Stream A] *)
CoFixpoint sect (x : index -> data) : t
:= Streams.Cons (x 0) (sect (fun n => x (S n))).
(* surjection, retraction, epimorphism *)
(** From a [Stream A], we can get the nth element, building a function [nat -> A] *)
Fixpoint retr (x : t) (i : index) : data
:= match i with
| O => Streams.hd x
| S i => retr (Streams.tl x) i
end.
(** Two streams are coextensionally equal, then the corresponding functions are extensionally equal *)
Lemma iff_EqSt_pointwise_eq (s1 s2 : t) : Streams.EqSt s1 s2 <-> forall i, retr s1 i = retr s2 i.
Proof using Type.
split.
{ intros H i; revert s1 s2 H; induction i as [|i IHi]; cbn; intros s1 s2 [H1 H2]; auto. }
{ revert s1 s2; cofix CIH; intros s1 s2 H.
constructor.
{ specialize (H 0); cbn in H. assumption. }
{ specialize (fun i => H (S i)); cbn in H. auto. } }
Qed.
Lemma ext_from_funext
(funext : forall f g : index -> data, (forall x, f x = g x) -> f = g)
(axiom : forall x, sect (retr x) = x)
: forall (s1 s2 : t), EqSt s1 s2 -> s1 = s2.
Proof using Type.
intros s1 s2; rewrite iff_EqSt_pointwise_eq; intro H.
rewrite <- (axiom s1), <- (axiom s2); apply f_equal, funext, H.
Qed.
End __.
End StreamsExt.
Section Paths.
Context {state : Type}.
Variable R : relation state.
CoInductive path (s: state) : Type :=
| step : forall s', R s s' -> path s' -> path s.
CoInductive path_eq : forall {s}, path s -> path s -> Prop :=
| path_eq_intro : forall x y r p p',
path_eq p p' ->
path_eq (step x y r p) (step x y r p').
Definition next_state {s} (p : path s) : state
:= match p with
| #step _ s' _ _ => s'
end.
Definition unstep_rel {s} (p : path s) : R s (next_state p)
:= match p with
| #step _ _ r _ => r
end.
Definition unstep {s} (p : path s) : path (next_state p)
:= match p with
| #step _ _ _ p => p
end.
(* slightly nicer version of path_eq *)
Import EqNotations.
CoInductive path_eq' {s1 s2} (p1 : path s1) (p2 : path s2) (H : s1 = s2) : Prop :=
| path_eq'_intro :
forall (p : next_state p1 = next_state p2),
(rew [fun s => R s _] H in rew p in unstep_rel p1) = unstep_rel p2 ->
path_eq' (unstep p1) (unstep p2) p ->
path_eq' p1 p2 H.
CoFixpoint path_eq'_of_path_eq {s} {p1 p2 : path s}
: path_eq p1 p2 -> path_eq' p1 p2 eq_refl.
Proof using Type.
intro H; unshelve econstructor; destruct H.
{ cbn. reflexivity. }
{ cbn. reflexivity. }
{ cbn. apply path_eq'_of_path_eq, H. }
Qed.
Lemma next_state_eq_of_path_eq' {s1 s2} {p1 : path s1} {p2 : path s2} {H : s1 = s2}
: path_eq' p1 p2 H -> next_state p1 = next_state p2.
Proof using Type.
intro H'; destruct H'; assumption.
Defined.
Lemma rel_eq_of_path_eq' {s1 s2} {p1 : path s1} {p2 : path s2} {H : s1 = s2}
: forall p : path_eq' p1 p2 H, (rew [fun s => R s _] H in rew next_state_eq_of_path_eq' p in unstep_rel p1) = unstep_rel p2.
Proof using Type.
intro H'; destruct H'; cbn in *; assumption.
Defined.
CoFixpoint path_eq_of_path_eq' {s} {p1 p2 : path s}
: path_eq' p1 p2 eq_refl -> path_eq p1 p2.
Proof using Type.
intro H'; destruct p1, p2, H'; cbn in *; subst; cbn in *.
constructor; auto.
Qed.
Lemma iff_path_eq_path_eq'_eq_refl {s} (p1 p2 : path s)
: path_eq p1 p2 <-> path_eq' p1 p2 eq_refl.
Proof using Type.
split; first [ apply path_eq'_of_path_eq | apply path_eq_of_path_eq' ].
Qed.
Lemma iff_path_eq_path_eq' {s1 s2} (p1 : path s1) (p2 : path s2) (H : s1 = s2)
: path_eq (rew H in p1) p2 <-> path_eq' p1 p2 H.
Proof using Type.
subst; apply iff_path_eq_path_eq'_eq_refl.
Qed.
End Paths.
Module PathsExt.
Section __.
Context {state : Type}.
Variable R : relation state.
Definition t := { s : state & path R s }.
Definition fun_type := { st : nat -> state | forall n, R (st n) (st (S n)) }.
Definition mk_fun_type (st : nat -> state) (H : forall n, R (st n) (st (S n))) : fun_type
:= exist _ st H.
(** inclusion, injection, section, monomorphism *)
CoFixpoint sect' (x : fun_type) : path R (proj1_sig x 0)
:= step
R _ _
(proj2_sig x 0)
(sect' (mk_fun_type (fun i => proj1_sig x (S i)) (fun i => proj2_sig x (S i)))).
Definition sect (x : fun_type) : t := existT _ _ (sect' x).
(* surjection, retraction, epimorphism *)
Fixpoint retr_index (x : t) (i : nat) : state
:= match i with
| O => projT1 x
| S i => retr_index (existT _ _ (unstep _ (projT2 x))) i
end.
Fixpoint retr' (x : t) (i : nat) : R (retr_index x i) (retr_index x (S i))
:= match i with
| O => unstep_rel _ (projT2 x)
| S i => retr' (existT _ _ (unstep _ (projT2 x))) i
end.
Definition retr (x : t) : fun_type := mk_fun_type (retr_index x) (retr' x).
Import EqNotations.
(** Two paths are coextensionally equal, then the corresponding functions are extensionally equal *)
Definition t_eq (s1 s2 : t) : Prop
:= { p : projT1 s1 = projT1 s2 | path_eq' _ (projT2 s1) (projT2 s2) p }.
Definition fun_type_eq (s1 s2 : fun_type) : Prop
:= exists p : (forall i, proj1_sig s1 i = proj1_sig s2 i),
forall i, (rew [fun s => R s _] (p i) in rew (p (S i)) in proj2_sig s1 i) = proj2_sig s2 i.
Lemma iff_path_eq_pointwise_eq (s1 s2 : t) : t_eq s1 s2 <-> fun_type_eq (retr s1) (retr s2).
Proof using Type.
split; cbv [t_eq fun_type_eq].
{ intro H; unshelve eexists; intro i; revert s1 s2 H; induction i as [|i IHi]; cbn; intros [s1 s1'] [s2 s2'] [H1 H2];
cbn in *.
{ assumption. }
{ apply IHi; cbn.
unshelve eexists; destruct H2; eassumption. }
{ cbn. destruct H2; assumption. }
{ cbn in *. apply IHi. } }
{ intros [H1 H2].
exists (H1 0).
revert s1 s2 H1 H2; cofix CIH; intros.
unshelve econstructor.
{ exact (H1 1). }
{ exact (H2 O). }
{ apply (CIH _ _ (fun i => H1 (S i)) (fun i => H2 (S i))). } }
Defined.
Lemma ext_from_funext'
(funext_fun_type : forall f g, fun_type_eq f g -> f = g)
(axiom : forall x, sect (retr x) = x)
(funext_fun_type_pr : forall f g p q, f_equal (fun a => proj1_sig a 0) (funext_fun_type f g (ex_intro _ p q)) = p 0)
(axiom_pr1 : forall x, f_equal (#projT1 _ _) (axiom x) = eq_refl)
: forall (p1 p2 : t) (H : t_eq p1 p2), { pf : p1 = p2 | f_equal (#projT1 _ _) pf = proj1_sig H }.
Proof using Type.
intros p1 p2.
intro H; unshelve eexists.
{ apply iff_path_eq_pointwise_eq, funext_fun_type, (f_equal sect) in H.
etransitivity; [ | apply axiom ]; etransitivity; [ symmetry; apply axiom | ].
exact H. }
{ cbv zeta beta.
rewrite !eq_trans_map_distr, <- !eq_sym_map_distr, !axiom_pr1; cbn [eq_sym].
rewrite !eq_trans_refl_l, !eq_trans_refl_r, !f_equal_compose.
cbn [projT1 sect].
cbv [iff_path_eq_pointwise_eq]; cbn.
rewrite funext_fun_type_pr.
cbn.
destruct p1, p2, H; cbn; reflexivity. }
Qed.
Lemma f_equal_projT1_eq_sigT {A P u v p q}
: f_equal (#projT1 _ _) (#eq_sigT A P u v p q) = p.
Proof using Type. destruct u, v; cbn in *; subst; cbn; reflexivity. Qed.
Lemma ext_from_funext''
(funext_nat : forall f g : nat -> state, (forall x, f x = g x) -> f = g)
(funext_rel : forall F (f g : forall n : nat, R (F n) (F (S n))), (forall x, f x = g x) -> f = g)
(axiom : forall x, sect (retr x) = x)
(funext_nat_f_equal : forall f g p x, f_equal (fun f => f x) (funext_nat f g p) = p x)
(axiom_pr1 : forall x, f_equal (#projT1 _ _) (axiom x) = eq_refl)
: forall {s} (p1 p2 : path R s), path_eq R p1 p2 -> p1 = p2.
Proof using Type.
intros s p1 p2 H.
apply iff_path_eq_path_eq'_eq_refl in H.
unshelve epose proof (ext_from_funext' _ _ _ _ (existT _ _ _) (existT _ _ _) (exist _ eq_refl H)) as H'; try eassumption; revgoals.
{ destruct H' as [H0 H']; cbn in *.
induction H0 using (#eq_sigT_ind _ _ _ _); cbn [projT1 projT2] in *.
rewrite f_equal_projT1_eq_sigT in H'; subst; cbn in *.
reflexivity. }
all: revgoals.
{ cbv [fun_type_eq].
intros [f1 f2] [g1 g2] [H1 H2]; cbn in *.
apply eq_sig_uncurried; cbn.
exists (funext_nat _ _ H1).
apply funext_rel; intro n.
etransitivity; [ | apply H2 ].
transitivity (rew [fun s => R s _] f_equal (fun f => f _) (funext_nat _ _ H1) in rew [R _] f_equal (fun f => f _) (funext_nat _ _ H1) in f2 n).
{ generalize (funext_nat _ _ H1); intro; subst; reflexivity. }
{ rewrite <- (funext_nat_f_equal _ _ H1 n), <- (funext_nat_f_equal _ _ H1 (S n)); reflexivity. } }
{ intros; cbn.
destruct f, g; cbn in *.
move funext_nat at bottom.
generalize (funext_nat_f_equal _ _ p).
generalize (funext_nat _ _ p).
clear funext_nat funext_nat_f_equal.
intro; subst; cbn in *.
intro funext_nat_f_equal.
destruct funext_rel; cbn; apply funext_nat_f_equal. }
Qed.
(* quoting myself at https://github.com/HoTT/HoTT/issues/757#issue-76140493 *)
Definition good_funext_of_funext {A B}
(funext : forall f g : A -> B, (forall x, f x = g x) -> f = g)
(funext_dep : forall (f : A -> B) (F G : forall x : A, {x0 : B & f x = x0}),
(forall x, F x = G x) -> F = G)
: { funext : forall f g : A -> B, (forall x, f x = g x) -> f = g
| (forall f g p, funext f g (fun x => f_equal (fun f => f x) p) = p)
/\ (forall f g p x, f_equal (fun f => f x) (funext f g p) = p x) }.
Proof using Type.
exists (fun f g p => eq_trans (eq_sym (funext _ _ (fun _ => eq_refl))) (funext f g p)).
split.
{ intros; subst; cbn; apply eq_trans_sym_inv_l. }
{ intros f g p.
pose (fun x => existT _ (g x) (p x)) as p'.
change p with (fun x => projT2 (p' x)).
change g with (fun x => projT1 (p' x)).
clearbody p'; clear p g.
assert (H'' : forall x, existT _ (f x) eq_refl = p' x).
{ intro x.
destruct (p' x) as [? []]; reflexivity. }
intro x.
apply funext_dep in H''; subst p'; cbn.
rewrite eq_trans_sym_inv_l; reflexivity. }
Qed.
Lemma ext_from_funext_specific
(funext_nat : forall f g : nat -> state, (forall x, f x = g x) -> f = g)
(funext_nat_sig : forall (f : nat -> state) (F G : forall x : nat, {x0 : state & f x = x0}),
(forall x, F x = G x) -> F = G)
(funext_rel : forall F (f g : forall n : nat, R (F n) (F (S n))), (forall x, f x = g x) -> f = g)
(axiom : forall x, projT2 (sect (retr x)) = projT2 x)
: forall {s} (p1 p2 : path R s), path_eq R p1 p2 -> p1 = p2.
Proof using Type.
unshelve eapply ext_from_funext''.
{ unshelve eapply good_funext_of_funext.
{ exact funext_nat. }
{ exact funext_nat_sig. } }
{ intro x.
unshelve eapply eq_sigT.
{ reflexivity. }
{ apply axiom. } }
{ apply funext_rel. }
{ cbn; intros f g p n.
set (fs := good_funext_of_funext _ _).
destruct fs as [fs [H1 H2]].
apply H2. }
{ cbv beta.
intro; apply f_equal_projT1_eq_sigT. }
Qed.
Lemma ext_from_funext_dep
(funext_dep : forall A B (f g : forall a : A, B a), (forall x, f x = g x) -> f = g)
(axiom : forall x, projT2 (sect (retr x)) = projT2 x)
: forall {s} (p1 p2 : path R s), path_eq R p1 p2 -> p1 = p2.
Proof using Type.
apply ext_from_funext_specific; try first [ intros *; apply funext_dep | apply axiom ].
Qed.
Lemma f_equal_id {A x y p} : #f_equal A A id x y p = p.
Proof using Type. destruct p; reflexivity. Qed.
(** A more conceptually separated version of this is at
https://github.com/HoTT/HoTT/blob/master/theories/Metatheory/FunextVarieties.v
*)
Lemma ext_from_funext
(funext : forall A B (f g : A -> B), (forall x, f x = g x) -> f = g)
(axiom : forall x, projT2 (sect (retr x)) = projT2 x)
: forall {s} (p1 p2 : path R s), path_eq R p1 p2 -> p1 = p2.
Proof using Type.
apply ext_from_funext_dep; [ | apply axiom ].
intros A B f g H.
pose (existT (fun F : A -> { x : A & { y : B x & f x = y } } => (fun x => projT1 (F x)) = id)
(fun x : A => existT _ x (existT _ (f x) eq_refl))
eq_refl) as F.
pose (existT (fun G : A -> { x : A & { y : B x & f x = y } } => (fun x => projT1 (G x)) = id)
(fun x : A => existT _ x (existT _ (g x) (H x)))
eq_refl) as G.
cut (F = G).
{ intro H'.
change ((rew [fun F => forall x, B (F x)] projT2 F in (fun x => projT1 (projT2 (projT1 F x)))) =
(rew [fun F => forall x, B (F x)] projT2 G in (fun x => projT1 (projT2 (projT1 G x))))).
clearbody F G; subst G; reflexivity. }
{ clearbody F G.
pose (fun F : A -> {x : A & {y : B x & f x = y}} => fun x => projT1 (F x)) as postcomp_projT1.
pose (fun F : A -> A
=> (fun x : A => existT (fun x : A => {y : B x & f x = y}) (F x) (existT _ _ eq_refl))) as inv.
assert (H' : forall F, inv (postcomp_projT1 F) = F).
{ clear -funext.
intro F.
apply funext; intro x.
subst inv postcomp_projT1; cbn.
destruct (F x) as [? [? []]]; cbn; reflexivity. }
simple refine (let H'' : forall F, postcomp_projT1 (inv F) = F := _ in _).
{ reflexivity. }
cut (forall Fid (F : {G : A -> {x : A & {y : B x & f x = y}} & postcomp_projT1 G = Fid}),
F = existT _ (fun x => existT _ _ (existT _ _ eq_refl)) eq_refl).
{ intro contr; etransitivity; [|symmetry]; apply contr. }
{ clear F G.
intros Fid F.
refine (eq_sym (#eq_trans _ _ (existT _ _ (H'' Fid)) _ _ (eq_sym _))).
{ apply eq_sigT_uncurried; subst inv postcomp_projT1; cbn.
exists eq_refl; cbv.
reflexivity. }
{ simple refine (let H''' : forall F, inv (postcomp_projT1 F) = F := fun F => eq_trans (eq_trans (f_equal inv (f_equal postcomp_projT1 (eq_sym (H' F)))) (f_equal inv (H'' _))) (H' F) in
_).
clearbody H''.
apply eq_sigT_uncurried; cbn.
exists (eq_trans (eq_sym (H''' _)) (f_equal inv (projT2 F))).
destruct F as [F ?]; subst.
subst H'''; cbn.
clear -funext H' H''.
clearbody inv postcomp_projT1.
clear -funext H' H''.
match goal with
| [ |- rew ?p in eq_refl = ?H ] => cut (f_equal postcomp_projT1 (eq_sym p) = H); [ generalize p | ]
end.
{ clear.
generalize (H'' (postcomp_projT1 F)).
generalize (inv (postcomp_projT1 F)).
intros; subst; cbn; reflexivity. }
rewrite !eq_sym_involutive, !eq_trans_map_distr.
cut (eq_trans
(f_equal postcomp_projT1 (f_equal inv (H'' (postcomp_projT1 F)))) (f_equal postcomp_projT1 (H' F)) =
eq_trans (f_equal postcomp_projT1 (f_equal inv (f_equal postcomp_projT1 (H' F)))) (H'' (postcomp_projT1 F))).
{ rewrite <- !eq_sym_map_distr.
intro H.
rewrite <- eq_trans_assoc, H, !eq_trans_assoc, eq_trans_sym_inv_l, eq_trans_refl_l.
reflexivity. }
generalize (f_equal postcomp_projT1 (H' F)).
generalize (postcomp_projT1 F).
cut (forall a b (e : postcomp_projT1 (inv a) = b),
eq_trans (f_equal postcomp_projT1 (f_equal inv (H'' a))) e = eq_trans (f_equal postcomp_projT1 (f_equal inv e)) (H'' b)).
{ clear; intros H ??; apply H. }
intros; subst b; cbn.
rewrite eq_trans_refl_l.
rewrite f_equal_compose.
set (F' := fun a => postcomp_projT1 (inv a)).
change (forall F, F' F = F) in H''.
change (f_equal F' (H'' a) = H'' (F' a)).
assert (Hid : F' = id) by (apply funext, H'').
clearbody F'; subst F'.
rewrite f_equal_id; reflexivity. } } }
Qed.
End __.
End PathsExt.

How to prove all proofs of le equal?

I'm basically trying to prove
Theorem le_unique {x y : nat} (p q : x <= y) : p = q.
without assuming any axioms (e.g. proof irrelevance). In particular, I've tried to get through le_unique by induction and inversion, but it never seems to get far
Theorem le_unique (x y : nat) (p q : x <= y) : p = q.
Proof.
revert p q.
induction x as [ | x rec_x]. (* induction on y similarly fruitless; induction on p, q fails *)
- destruct p as [ | y p].
+ inversion q as [ | ]. (* destruct q fails and inversion q makes no progress *)
admit.
+ admit.
- admit.
Admitted.
In the standard library, this lemma can be found as Peano_dec.le_unique in the module Coq.Arith.Peano_dec.
As for a relatively simple direct proof, I like to go by induction on p itself.
After proving by hand a few induction principles that Coq doesn't automatically generate, and remembering that proofs of equality on nat are unique, the proof is a relatively straightforward induction on p followed by cases on q, giving four cases two of which are absurd.
Below is a complete Coq file proving le_unique.
Import EqNotations.
Require Eqdep_dec PeanoNat.
Lemma nat_uip {x y : nat} (p q : x = y) : p = q.
apply Eqdep_dec.UIP_dec.
exact PeanoNat.Nat.eq_dec.
Qed.
(* Generalize le_ind to prove things about the proof *)
Lemma le_ind_dependent :
forall (n : nat) (P : forall m : nat, n <= m -> Prop),
P n (le_n n) ->
(forall (m : nat) (p : n <= m), P m p -> P (S m) (le_S n m p)) ->
forall (m : nat) (p : n <= m), P m p.
exact (fun n P Hn HS => fix ind m p : P m p := match p with
| le_n _ => Hn | le_S _ m p => HS m p (ind m p) end).
Qed.
(*
Here we give an proof-by-cases principle for <= which keeps both the left
and right hand sides fixed.
*)
Lemma le_case_remember (x y : nat) (P : x <= y -> Prop)
(IHn : forall (e : y = x), P (rew <- e in le_n x))
(IHS : forall y' (q' : x <= y') (e : y = S y'), P (rew <- e in le_S x y' q'))
: forall (p : x <= y), P p.
exact (fun p => match p with le_n _ => IHn | le_S _ y' q' => IHS y' q' end eq_refl).
Qed.
Theorem le_unique {x y : nat} (p q : x <= y) : p = q.
revert q.
induction p as [|y p IHp] using le_ind_dependent;
intro q;
case q as [e|x' q' e] using le_case_remember.
- rewrite (nat_uip e eq_refl).
reflexivity.
- (* x = S x' but x <= x', so S x' <= x', which is a contradiction *)
exfalso.
rewrite e in q'.
exact (PeanoNat.Nat.nle_succ_diag_l _ q').
- (* S y' = x but x <= y', so S y' <= y', which is a contradiction *)
exfalso; clear IHp.
rewrite <- e in p.
exact (PeanoNat.Nat.nle_succ_diag_l _ p).
- injection e as e'.
(* We now get rid of e as equal to (f_equal S e'), and then destruct e'
now that it is an equation between variables. *)
assert (f_equal S e' = e).
+ apply nat_uip.
+ destruct H.
destruct e'.
change (le_S x y p = le_S x y q').
f_equal.
apply IHp.
Qed.
Inspired by Eqdep_dec (and with a lemma from it), I've been able to cook this proof up. The idea is that x <= y can be converted to exists k, y = k + x, and roundtripping through this conversion produces a x <= y that is indeed = to the original.
(* Existing lemmas (e.g. Nat.le_exists_sub) seem unusable (declared opaque) *)
Fixpoint le_to_add {x y : nat} (prf : x <= y) : exists k, y = k + x :=
match prf in _ <= y return exists k, y = k + x with
| le_n _ => ex_intro _ 0 eq_refl
| le_S _ y prf =>
match le_to_add prf with
| ex_intro _ k rec =>
ex_intro
_ (S k)
match rec in _ = z return S y = S z with eq_refl => eq_refl end
end
end.
Fixpoint add_to_le (x k : nat) : x <= k + x :=
match k with
| O => le_n x
| S k => le_S x (k + x) (add_to_le x k)
end.
Theorem rebuild_le
{x y : nat} (prf : x <= y)
: match le_to_add prf return x <= y with
| ex_intro _ k prf =>
match prf in _ = z return x <= z -> x <= y with
| eq_refl => fun p => p
end (add_to_le x k)
end = prf.
Proof.
revert y prf.
fix rec 2. (* induction is not enough *)
destruct prf as [ | y prf].
- reflexivity.
- specialize (rec y prf).
simpl in *.
destruct (le_to_add prf) as [k ->].
subst prf.
reflexivity.
Defined.
Then, any two x <= ys will produce the same k, by injectivity of +. The decidability of = on nat tells us that the produced equalities are also equal. Thus, the x <= ys map to the same exists k, y = k + x, and mapping that equality back tells us the x <= ys were also equal.
Theorem le_unique (x y : nat) (p q : x <= y) : p = q.
Proof.
rewrite <- (rebuild_le p), <- (rebuild_le q).
destruct (le_to_add p) as [k ->], (le_to_add q) as [l prf].
pose proof (f_equal (fun n => n - x) prf) as prf'.
simpl in prf'.
rewrite ?Nat.add_sub in prf'.
subst l.
apply K_dec with (p := prf).
+ decide equality.
+ reflexivity.
Defined.
I'm still hoping there's a better (i.e. shorter) proof available.

how to simplify a equality statement

In hypothesis, I have a natural number that cannot be zero.When we add this number
to an another function,whose output is also natural number. I have to prove that result of addition of these two values equal to zero is false. I should not dig about f,because addition of anything in non zero term ,become equal to zero is false statement.
`H : (m =? 0) = false
(f+ m =? 0) = false`
Short answer:
Require Import Lia.
rewrite !Nat.eqb_neq; lia.
Long answer:
I feel sorry that this question arises. Historically, most of the reasoning in Coq about equality is done with the eq concept, with the notation m = n, not with the boolean equality, on which you rely here. It is also important to know that Coq has a specific notation for "disequality" or "non-equality" : m <> n stands for ~ (m = n).
So if you add typed the following statement instead, there would be an easy solution:
Require Import Arith Lia.
Lemma example1 f m : m <> 0 -> f + m <> 0.
Proof. lia. Qed.
Unfortunately, this does not work for the way you express your statement:
Lemma example2 f m : (m =? 0) = false -> (f + m =? 0) = false.
Proof.
Fail lia.
If you call Search with the following pattern, you see that the boolean comparison expression is logically equivalent to basic equality, but only if you use specific theorems to express this:
Search (_ =? _).
Nat.eqb_refl: forall x : nat, (x =? x) = true
beq_nat_refl: forall n : nat, true = (n =? n)
Nat.eqb_sym: forall x y : nat, (x =? y) = (y =? x)
Nat.eqb_spec: forall x y : nat, Bool.reflect (x = y) (x =? y)
beq_nat_eq: forall n m : nat, true = (n =? m) -> n = m
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
Nat.eqb_eq: forall n m : nat, (n =? m) = true <-> n = m
beq_nat_false: forall n m : nat, (n =? m) = false -> n <> m
Nat.eqb_neq: forall x y : nat, (x =? y) = false <-> x <> y
Nat.pow2_bits_eqb: forall n m : nat, Nat.testbit (2 ^ n) m = (n =? m)
Nat.bit0_eqb: forall a : nat, Nat.testbit a 0 = (a mod 2 =? 1)
Nat.eqb_compare:
forall x y : nat, (x =? y) = match x ?= y with
| Eq => true
| _ => false
end
Nat.setbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.setbit a n) m = ((n =? m) || Nat.testbit a m)%bool
Nat.clearbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.clearbit a n) m = (Nat.testbit a m && negb (n =? m))%bool
Nat.testbit_eqb: forall a n : nat, Nat.testbit a n = ((a / 2 ^ n) mod 2 =? 1)
But there is no theorem that expresses the interaction of addition with equality to 0. You can also see this using a more precise pattern.
Search (_ =? _) 0 (_ + _).
This returns nothing.
On the other hand, if you type
Search (_ = _) 0 (_ + _).
You see many theorems, one of which is relevant to your problem.
Nat.eq_add_0: forall n m : nat, n + m = 0 <-> n = 0 /\ m = 0
And this one is enough to solve the problem, if it is expressed with _ = _ instead of _ =? _. So to solve your specific problem, we need first to transform comparisons using _ =? _ into equality statements,and then do logical reasoning using the available theorems. In the first search result, we have the theorem Nat.eqb_neq that is adapted to your situation. Continuing on the proof of example2 above, we can write:
Rewrite !Nat.eqb_neq.
The goal becomes:
f, m : nat
============================
m <> 0 -> f + m <> 0
Now, we could do logical reasoning using the theorem Nat.eq_add_0.
rewrite Nat.eq_add_0.
We can finish the proof by small step like this.
intros mn0 [fis0 mis0]; case mn0; assumption.
we can also ask an automatic tool to finish the proof for us:
tauto.
But going a little backward in time, we can also observe the statement after rewriting with Nat.eqb_neq. This is a statement in linear arithmetic (it contains comparisons, natural numbers, and no product between variables). This statement is in the scope of a tactic for this theory, the one used most often now is lia.

Split conjunction goal into subgoals

Consider the following toy exercise:
Theorem swap_id: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H.
At this point I have the following:
1 subgoal
m, n : nat
H : m = n
______________________________________(1/1)
(m, n) = (n, m)
I would like to split the goal into two subgoals, m = n and n = m. Is there a tactic which does that?
Solve using the f_equal tactic:
Theorem test: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H. f_equal.
With state:
2 subgoals
m, n : nat
H : m = n
______________________________________(1/2)
m = n
______________________________________(2/2)
n = m