Library tactics_example

From Ssreflect Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.

Goal forall n : nat, n + n = 2 * n.
Show Proof.
elim.
Show Proof.
done.
move=> n IH.
ring.
Qed.

Check nat_ind.
Check Wf_nat.lt_wf_ind.

Lemma mylt_wf_ind : forall (n : nat) (P : nat -> Prop),
(forall n0 : nat, (forall m : nat, (m < n0) -> P m) -> P n0) ->
P n.
Proof.
move=> n.
move: (leqnn n).
move: {-2}n.
move: n.
elim.
case=> //.
move=> _ P.
apply.
done.
move=> n IH m mn P HP.
move: (HP).
apply => k km.
apply IH => //.
rewrite -ltnS.
by apply: leq_trans mn.
Qed.

Lemma another_ind : forall (P : nat -> Prop),
P O -> P 1 ->
(forall m, P m -> P m.+2) ->
forall m, P m.
Proof.
move=> P P0 P1 IH m.
have : P m /\ P m.+1.
elim: m => // n [] H1 H2.
split=> //.
by apply IH.
by case.
Qed.

Fixpoint another_ind2 (P : nat -> Prop) (P0 : P 0) (P1 : P 1)
(H : forall m, P m -> P m.+2) m : P m :=
match m with
| O => P0
| 1 => P1
| n.+2 => H _ (another_ind2 P P0 P1 H n)
end.

Lemma yet_another_ind : forall (P : nat -> Prop),
P O -> P 1 ->
(forall m, P m /\ P m.+1 -> P m.+2) ->
forall m, P m.
Proof.
move=> P P0 P1 H n.
have : P n /\ P n.+1.
elim: n => // n [] H1 H2.
split => //.
by apply H.
by case.
Qed.

Module MutualNestedInductiveTypes.

Inductive tree (A : Set) : Set :=
node : A -> forest A -> tree A
with forest (A : Set) : Set :=
fnil : forest A
| fcons : tree A -> forest A -> forest A.

Check tree_ind.

Scheme tree_ind2 := Induction for tree Sort Prop
with forest_ind2 := Induction for forest Sort Prop.

Check tree_ind2.

Fixpoint tsize {A : Set} (t : tree A) : nat :=
match t with
| node a f => 1 + fsize f
end
with fsize {A : Set} (f : forest A) :=
match f with
| fnil => O
| fcons t f' => tsize t + fsize f'
end.

Fixpoint tflat {A : Set} (t : tree A) : seq A :=
match t with
| node a f => a :: fflat f
end
with fflat {A : Set} (f : forest A) :=
match f with
| fnil => nil
| fcons t f' => tflat t ++ fflat f'
end.

Lemma exo15 A (t : tree A) : tsize t = size (tflat t).
Proof.
apply: (tree_ind2 _ (fun t => tsize t = size (tflat t)) (fun f => fsize f = size (fflat f))) t => //.
Abort.

Inductive ltree (A : Set) : Set :=
lnode : A -> list (ltree A) -> ltree A.

Check ltree_ind.

Section ltree_ind2.

Variable A : Set.
Variable (P : ltree A -> Prop).
Variable (Q : list (ltree A) -> Prop).
Hypothesis H0 : Q nil.
Hypothesis H1 : forall (t : ltree A), P t -> forall l : list (ltree A), Q l -> Q (cons t l).
Hypothesis H : forall (a : A) (l : list (ltree A)), Q l -> P (lnode A a l).

Fixpoint ltree_ind2 (t : ltree A) : P t :=
match t with
| lnode a l =>
H a l
((fix l_ind (l' : list (ltree A)) : Q l' :=
match l' with
| nil => H0
| cons h' t' => H1 h' (ltree_ind2 h') t' (l_ind t')
end
) l)
end.

End ltree_ind2.

Fixpoint lsize {A : Set} (l : ltree A) : nat :=
match l with
| lnode a l =>
1 + foldr addn O (map lsize l)
end.

Fixpoint lflat {A : Set} (l : ltree A) : seq A :=
match l with
| lnode a l => a :: flatten (map lflat l)
end.

Lemma exo16 A (t : ltree A) : lsize t = size (lflat t).
Proof.
apply: (ltree_ind2 _ (fun t => lsize t = size (lflat t)) (fun l => foldr addn O (map lsize l) = size (flatten (map lflat l)))) t => //.
Abort.

End MutualNestedInductiveTypes.

Goal forall n : nat, n = 0 -> forall m : nat, m + n = m.
move=> n n0 m.
rewrite n0.
done.
Qed.

Goal forall n : nat, n = 0 -> forall m : nat, n + m = n.
move=> n n0 m.
rewrite n0.
Undo.
rewrite {1}n0.
Undo.
rewrite {2}n0.
Undo.
rewrite {-2}n0.
Undo.
Abort.

Goal forall x y : nat,
(forall t u, t + u = u + t) ->
x + y = y + x.
move=> x y H.
Fail rewrite {2}H.
rewrite [y + _]H.
done.
Qed.

Goal forall x y : nat,
(forall t u, t + u * 0 = t) ->
x + y * 4 + 2 * 0 = x + 2 * 0.
Proof.
move=> x y H.
Fail rewrite [x + _]H.
rewrite [x + 2 * _]H.
Abort.

Goal forall (a b c : nat),
(a + b) + (2 * (b + c)) = 0.
move=> a b c.
rewrite [in X in _ + X]addnC.
Abort.

Goal forall n : nat, n + n = 2 * n.
elim.
rewrite muln0.
done.
move=> n IH.
rewrite mulnS.
rewrite -IH.
done.
Qed.

Lemma undup_filter {A : eqType} (P : pred A) (s : seq A) :
undup (filter P s) = filter P (undup s).
Proof.
elim: s => // h t IH /=.
case: ifP => /= [Ph | Ph].
- case: ifP => [Hh | Hh].
+ have : h \in t.
move: Hh; by rewrite mem_filter => /andP [].
by move=> ->.
+ have : h \in t = false.
apply: contraFF Hh; by rewrite mem_filter Ph.
move=> -> /=; by rewrite Ph IH.
- case: ifP => // ht.
by rewrite IH /= Ph.
Qed.

Fixpoint flat {A : eqType} (l : seq (seq A)) : seq A :=
if l is h :: t then h ++ flat t else [::].

Lemma exo17 {A : eqType} (s : seq (seq A)) a :
reflect (exists2 s', s' \in s & a \in s') (a \in flat s).
Proof.
elim: s.
right.
by case.
move=> h t IH.
rewrite /= mem_cat.
apply: (iffP idP).
case/orP.
move=> H.
exists h.
by rewrite in_cons eqxx.
done.
case/IH.
move=> /= s st ys.
exists s.
by rewrite in_cons st orbT.
done.
case=> s'.
rewrite in_cons.
case/orP.
move=> s'h as'.
apply/orP.
left.
move/eqP : s'h.
move=> <-.
done.
move=> s't as'.
apply/orP.
right.
apply/IH.
by exists s'.
Qed.

Goal forall a b c a' b' c', a + b + c = a' + b' + c'.
move=> a b c a' b' c'.
congr (_ + _ + _).
Abort.

Goal forall s1 s2 : seq nat, rev (s1 ++ s2) = rev s2 ++ rev s1.
move=> s1.
move H : (size s1) => n.
move: n s1 H.
elim.
case => //.
rewrite /=.
move=> _ s2.
by rewrite cats0.
move=> n IH.
case=> // h t.
case=> tn.
move=> s2.
rewrite /=.
rewrite rev_cons.
rewrite IH //.
rewrite rcons_cat.
by rewrite rev_cons.
Qed.

Goal forall a b : nat,
a <> b.
move=> a b.
case H : a => [|n].
Show 2.
Abort.

Module Wlog.

Section wlog.

Variable a : nat.
Hypothesis a1 : 1 < a.

Lemma artificial (k l : nat) : k < l \/ l < k -> a ^ k != a ^ l.
Proof.
wlog : k l / k < l.
move=> H.
case=> kl.
apply H => //; by left.
rewrite eq_sym.
apply H => //; by left.
move=> kl _.
by rewrite eqn_exp2l // neq_ltn kl.
Qed.

End wlog.

Lemma leq_min m n1 n2 : (m <= minn n1 n2) = (m <= n1) && (m <= n2).
Proof.
wlog : n1 n2 / n2 <= n1.
move=> H.
have : n2 <= n1 \/ n1 <= n2 by apply/orP/leq_total.
case=> n12.
by apply H.
rewrite minnC andbC; by apply H.
move=> n12.
rewrite /minn.
rewrite ltnNge.
rewrite n12.
rewrite /=.
case mn2 : (m <= n2).
by rewrite (leq_trans mn2 n12).
by rewrite andbC.
Qed.

End Wlog.

Search (_ < _)%N.
Search (_ < _ = _)%N.

Search _ (_ <= _)%N.
Search _ (_ <= _)%N "-"%N.
Search _ (_ <= _)%N "-"%N addn.