-
Notifications
You must be signed in to change notification settings - Fork 46
/
nm.v
98 lines (83 loc) · 3.29 KB
/
nm.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
(** Proving Termination of Normalization Functions for Conditional Expressions, L. Paulson *)
From Equations Require Import Equations.
Require Import List Program.Syntax Arith Lia.
Inductive exp := At | If : exp -> exp -> exp -> exp.
Equations exp_size : exp -> nat :=
exp_size At := 1;
exp_size (If e1 e2 e3) := exp_size e1 * (1 + exp_size e2 + exp_size e3).
Transparent exp_size.
Lemma exp_size_pos (x : exp) : (0 < exp_size x)%nat.
Proof. funelim (exp_size x); auto; try lia. apply Nat.mul_pos_pos; auto. lia. Qed.
Hint Resolve exp_size_pos : core.
Set Program Mode.
Lemma size_1:
forall y z : exp, exp_size y < S (exp_size y + exp_size z + 0).
Proof.
intros y z. lia.
Qed.
Lemma size_2:
forall y z : exp, exp_size z < S (exp_size y + exp_size z + 0).
Proof.
intros y z. lia.
Qed.
Lemma size_3 u v w y z : exp_size (If v y z) < exp_size (If (If u v w) y z).
Proof.
simp exp_size.
assert (1 + exp_size y + exp_size z > 0) by lia. revert H.
generalize (1 + exp_size y + exp_size z). intros n Hn.
generalize (exp_size_pos u). intros.
rewrite 2 Nat.mul_add_distr_l.
nia.
Qed.
Lemma size_4 u v w y z : exp_size (If w y z) < exp_size (If (If u v w) y z).
Proof.
simp exp_size.
assert (1 + exp_size y + exp_size z > 0) by lia. revert H.
generalize (1 + exp_size y + exp_size z). intros n Hn.
generalize (exp_size_pos u). intros.
rewrite 2 Nat.mul_add_distr_l.
nia.
Qed.
Lemma size_5:
forall u v w y z x : exp,
exp_size x <= exp_size (If v y z) ->
forall x0 : exp, exp_size x0 <= exp_size (If w y z) -> exp_size (If u x x0) < exp_size (If (If u v w) y z).
Proof.
intros u v w y z x l x0 l0.
simp exp_size. rewrite <- Nat.mul_assoc. apply mult_lt_compat_l; auto.
eapply Nat.le_lt_trans with (1 + exp_size (If v y z) + exp_size (If w y z)). lia.
simp exp_size. simpl. rewrite Nat.mul_add_distr_r.
generalize (exp_size_pos y). lia.
Qed.
Lemma size_6:
forall u v w y z x : exp,
exp_size x <= exp_size (If v y z) ->
forall x0 : exp,
exp_size x0 <= exp_size (If w y z) ->
forall x1 : exp, exp_size x1 <= exp_size (If u x x0) -> exp_size x1 <= exp_size (If (If u v w) y z).
Proof.
intros u v w y z x l x0 l0 x1 l1.
simp exp_size. transitivity (exp_size (If u x x0)); auto.
simp exp_size. simp exp_size in *. rewrite <- Nat.mul_assoc. apply mult_le_compat_l.
transitivity (1 + (exp_size v * (1 + exp_size y + exp_size z)) + (exp_size w * (1 + exp_size y + exp_size z))).
lia. lia.
Defined.
Equations? nm_dep (e : exp) : { e' : exp | exp_size e' <= exp_size e } by wf (exp_size e) lt :=
nm_dep At := At;
nm_dep (If At y z) := If At (nm_dep y) (nm_dep z);
nm_dep (If (If u v w) y z) with nm_dep (If v y z), nm_dep (If w y z) :=
{ | exist _ t Ht | exist _ e He := nm_dep (If u t e) }.
Proof.
apply size_1. apply size_2.
all:repeat destruct nm_dep; simpl; try solve [simp exp_size; simpl; try lia].
apply size_3. apply size_4. apply size_5; auto. simpl in *. eapply size_6; eauto.
Defined.
Equations nm (e : exp) : exp :=
nm At := At;
nm (If At y z) := If At (nm_dep y) (nm_dep z);
nm (If (If u v w) y z) := nm_dep (If u (nm_dep (If v y z)) (nm_dep (If w y z))).
Lemma nm_eq e : nm e = nm_dep e.
Proof. funelim (nm_dep e); simp nm. simpl. rewrite Heq, Heq0. simpl. reflexivity. Qed.
Extraction nm_dep.
Transparent nm.
Eval vm_compute in nm (If (If At At At) At At).