From Coq Require Import Lia List Init.Nat PeanoNat.
From PCF2.external Require Import SR.
From PCF2.external.Synthetic Require Import Definitions DecidabilityFacts.
Set Default Goal Selector "!".
Ltac inv H := inversion H; subst; clear H.
Lemma iter_succ_r (n: nat) (A: Type) (f: A -> A) (x: A):
iter (S n) f x = iter n f (f x).
Proof.
now rewrite PeanoNat.Nat.iter_succ_r.
Qed.
Lemma iter_succ_l (n: nat) (A: Type) (f: A -> A) (x: A):
iter (S n) f x = f (iter n f x).
Proof.
now rewrite PeanoNat.Nat.iter_succ.
Qed.
Lemma rev_nth_error1 {A: Type} (l: list A) n (a: A):
n < length l -> nth_error l n = nth_error (rev l) (length l - S n).
Proof.
intros H. rewrite (nth_error_nth' (rev l) a). 2: simpl_list; lia.
rewrite <- rev_length.
rewrite <- rev_nth. 2: simpl_list; lia.
simpl_list. now rewrite <- nth_error_nth'.
Qed.
Lemma rev_nth_error2 {A: Type} (l: list A) n (a: A):
n < length l -> nth_error l (length l - S n) = nth_error (rev l) n.
Proof.
intros H. rewrite nth_error_nth' with (d := a). 2: lia.
rewrite <- rev_nth. 2: easy. rewrite <- nth_error_nth'.
1: easy. now simpl_list.
Qed.
Definition eq_dec X := decidable (fun p: X * X => fst p = snd p).
Lemma bool_eq_dec:
eq_dec bool.
Proof.
unfold eq_dec.
rewrite decidable_iff.
constructor. intros [b1 b2].
destruct b1, b2; firstorder; right; easy.
Qed.
Lemma list_eq_dec {A: Type}:
eq_dec A -> eq_dec (list A).
Proof.
intros dec_A. unfold eq_dec in *.
rewrite decidable_iff in dec_A. destruct dec_A as [dec_A].
rewrite decidable_iff. constructor.
intros [l1 l2]. induction l1 in l2 |-*.
- destruct l2; firstorder. now right.
- destruct l2. 1: now right.
destruct (IHl1 l2), (dec_A (a, a0)).
{left. cbn in *. intuition congruence. }
all: right; cbn in *; intuition congruence.
Qed.
Lemma pair_eq_dec {A B: Type}:
eq_dec A -> eq_dec B -> eq_dec (prod A B).
Proof.
intros dec_A dec_B. unfold eq_dec in *.
rewrite decidable_iff in dec_A. destruct dec_A as [dec_A].
rewrite decidable_iff in dec_B. destruct dec_B as [dec_B].
rewrite decidable_iff. constructor.
intros [[a1 b1] [a2 b2]]. destruct (dec_A (a1, a2)), (dec_B (b1, b2)).
all: cbn in *.
1: left; intuition congruence.
all: right; intuition congruence.
Qed.
Lemma rules_eq_decidable:
eq_dec (str * str).
Proof.
apply pair_eq_dec.
all: apply list_eq_dec, bool_eq_dec.
Qed.
Lemma list_eq {A: Type} (l l': list A):
length l = length l' -> (forall n a a', nth_error l n = Some a -> nth_error l' n = Some a' -> a = a') -> l = l'.
Proof.
intros len H. induction l as [| a l] in l', len, H |-*.
- now destruct l'.
- destruct l' as [| a' l'].
1: easy.
enough (H': a = a' /\ l = l').
{ destruct H' as [eq_1 eq_2]. now subst. }
split.
1: now apply (H 0).
apply IHl.
1: now injection len.
intros n s t H_s H_t. now apply (H (S n)).
Qed.
Lemma nat_ord_dec (n m: nat):
(n <= m) + (n > m).
Proof.
induction n in m |-*.
1: left; lia.
destruct m.
1: right; lia.
destruct (IHn m).
1: left; lia.
right; lia.
Qed.
Lemma leb_le_true:
forall n m, leb n m = true <-> n <= m.
Proof.
apply Nat.leb_le.
Qed.
Lemma leb_le_false:
forall n m, leb n m = false <-> n > m.
Proof.
intros n m. split.
- intros H. assert (H1: ~ leb n m = true) by now destruct (leb n m).
rewrite leb_le_true in H1. lia.
- intros H. assert (H1: ~ n <= m) by lia. rewrite <- leb_le_true in H1.
now destruct (leb n m).
Qed.
Lemma ltb_lt_true:
forall n m, ltb n m = true <-> n < m.
Proof.
apply Nat.ltb_lt.
Qed.
Lemma ltb_lt_false:
forall n m, ltb n m = false <-> n >= m.
Proof.
intros n m. split.
- intros H. assert (H1: ~ ltb n m = true) by now destruct (ltb n m).
rewrite ltb_lt_true in H1. lia.
- intros H. assert (H1: ~ n < m) by lia. rewrite <- ltb_lt_true in H1.
now destruct (ltb n m).
Qed.
Lemma arith_technical m n o:
n > m -> n <= m + o -> exists n', n' < o /\ n = m + 1 + n'.
Proof.
intros H1 H2. induction n in m, H1, H2 |-*.
- lia.
- destruct m.
+ exists n. lia.
+ assert (eq1: n > m) by lia. assert (eq2: n <= m + o) by lia.
destruct (IHn m eq1 eq2) as [n' Hn']. exists n'. lia.
Qed.
Lemma arith_technical' m n o:
n >= m -> n < m + o -> exists n', n' < o /\ n = m + n'.
Proof.
intros H1 H2. induction m in n, H1, H2 |-*.
- exists n. lia.
- destruct n.
+ exists m. lia.
+ assert (eq1: n >= m) by lia. assert (eq2: n < m + o) by lia.
destruct (IHm n eq1 eq2) as [n' Hn']. exists n'. lia.
Qed.
Definition diff n m := (n - m) + (m - n).
Lemma diff1 n m:
n >= m -> diff n m = n - m.
Proof.
intros ?. unfold diff. lia.
Qed.
Lemma diff2 n m:
n < m -> diff n m = m - n.
Proof.
intros ?. unfold diff. lia.
Qed.