File: div_mod.ml

package info (click to toggle)
hol88 2.02.19940316-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 63,052 kB
  • ctags: 19,365
  • sloc: ml: 199,939; ansic: 9,300; sh: 7,118; makefile: 6,076; lisp: 2,747; yacc: 894; sed: 201; cpp: 87; awk: 5
file content (215 lines) | stat: -rw-r--r-- 10,129 bytes parent folder | download | duplicates (11)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                            %
%   FILE:         div_mod.ml                                                 %
%   EDITOR:       Paul Curzon                                                %
%   DATE:         April 1993                                                 %
%   DESCRIPTION : Theorems about DIV and MOD		     		     %
%                                                                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%*********************************  HISTORY  ********************************%
%									     %
%   This file is based on the theory of 				     %
%                                                                            %
%   Wai Wong                                                                 %
%                                                                            %
%****************************************************************************%

system `rm -f div_mod.th`;;

new_theory `div_mod`;;


%****************************************************************************%
%                                                                            %
% AUTHOR        : Wai Wong                                                   %
% DATE          : April 1993                                                 %
%                                                                            %
%****************************************************************************%

let SUC_MOD = prove_thm(`SUC_MOD`,
    "!n m. (SUC n) < m ==> ((SUC n) MOD m = SUC (n MOD m))",
    REPEAT STRIP_TAC THEN IMP_RES_TAC SUC_LESS
    THEN IMP_RES_TAC LESS_MOD THEN ASM_REWRITE_TAC[]);;

let NOT_MULT_LESS_0 = PROVE(
    "!m n. (0 < m) /\ (0 < n) ==> 0 < (m * n)",
    REPEAT INDUCT_TAC THEN REWRITE_TAC[NOT_LESS_0]
    THEN STRIP_TAC THEN REWRITE_TAC[MULT_CLAUSES;ADD_CLAUSES;LESS_0]);;

let MOD_MULT_MOD = prove_thm(`MOD_MULT_MOD`,
    "!m n. (0 < n) /\ (0 < m)  ==> !x. ((x MOD (n * m)) MOD n = x  MOD n)",
    REPEAT GEN_TAC THEN DISCH_TAC
    THEN FIRST_ASSUM (ASSUME_TAC o (MATCH_MP NOT_MULT_LESS_0)) THEN GEN_TAC
    THEN POP_ASSUM (CHOOSE_TAC o (MATCH_MP (SPECL ["x:num";"m * n"]DA)))
    THEN POP_ASSUM (CHOOSE_THEN STRIP_ASSUME_TAC)
    THEN SUBST1_TAC (ASSUME"x = (q * (n * m)) + r")
    THEN POP_ASSUM (SUBST1_TAC o (SPEC "q:num") o (MATCH_MP MOD_MULT))
    THEN PURE_ONCE_REWRITE_TAC [MULT_SYM]
    THEN PURE_ONCE_REWRITE_TAC [GSYM MULT_ASSOC]
    THEN PURE_ONCE_REWRITE_TAC [MULT_SYM]
    THEN STRIP_ASSUME_TAC (ASSUME  "0 < n /\ 0 < m")
    THEN PURE_ONCE_REWRITE_TAC[UNDISCH_ALL(SPEC_ALL MOD_TIMES)]
    THEN REFL_TAC);;

let MULT_LEFT_1 = GEN_ALL (el 3 (CONJ_LIST 6 (SPEC_ALL MULT_CLAUSES)));;
let MULT_RIGHT_1 = GEN_ALL (el 4 (CONJ_LIST 6 (SPEC_ALL MULT_CLAUSES)));;

% MULT_DIV = |- !n q. 0 < n ==> ((q * n) DIV n = q) %
let MULT_DIV = save_thm(`MULT_DIV`,
    GEN_ALL (PURE_REWRITE_RULE[ADD_0]
    (CONV_RULE RIGHT_IMP_FORALL_CONV (SPECL["n:num";"0"] DIV_MULT))));;

% |- !q. q DIV (SUC 0) = q %
let DIV_ONE = save_thm(`DIV_ONE`,
    GEN_ALL (REWRITE_RULE[CONV_RULE (ONCE_DEPTH_CONV num_CONV) MULT_RIGHT_1]
    (MP (SPECL ["SUC 0"; "q:num"] MULT_DIV) (SPEC "0" LESS_0))));;

% LESS_DIV_EQ_ZERO = |- !r n. r < n ==> (r DIV n = 0) %
let LESS_DIV_EQ_ZERO = save_thm(`LESS_DIV_EQ_ZERO`,
    GEN_ALL (DISCH_ALL (PURE_REWRITE_RULE[MULT;ADD]
    (SPEC "0"(UNDISCH_ALL (SPEC_ALL  DIV_MULT))))));;

% SUC_MOD_SELF = |- !n. (SUC n) MOD (SUC n) = 0 %
let SUC_MOD_SELF = save_thm(`SUC_MOD_SELF`,
    GEN_ALL (REWRITE_RULE[MULT_CLAUSES]
    (SPEC "1"(MP (SPEC "SUC n" MOD_EQ_0) (SPEC "n:num" LESS_0)))));;

%  SUC_DIV_SELF = |- !n. (SUC n) DIV (SUC n) = 1 %
let SUC_DIV_SELF = save_thm(`SUC_DIV_SELF`,
    GEN_ALL (SYM (PURE_REWRITE_RULE[MULT_SUC_EQ]
    (TRANS (SPEC "SUC n" MULT_LEFT_1)
    (REWRITE_RULE[ADD_CLAUSES;SUC_MOD_SELF] (CONJUNCT1(SPEC "SUC n"
    (MP (SPEC "SUC n" DIVISION) (SPEC "n:num" LESS_0)))))))));;

let ADD_DIV_SUC_DIV = prove_thm(`ADD_DIV_SUC_DIV`,
    "!n. 0 < n ==> !r. (((n + r) DIV n) = SUC (r DIV n))",
    let MULT_LEM = SYM (PURE_ONCE_REWRITE_RULE[ADD_SYM]
    	(el 5 (CONJ_LIST 6 (SPECL["q:num";"n:num"] MULT_CLAUSES)))) in
    CONV_TAC (ONCE_DEPTH_CONV RIGHT_IMP_FORALL_CONV)
    THEN REPEAT GEN_TAC THEN ASM_CASES_TAC "r < n" THENL[
      IMP_RES_THEN SUBST1_TAC LESS_DIV_EQ_ZERO THEN DISCH_TAC
      THEN SUBST_OCCS_TAC [[1],(SYM (SPEC"n:num" MULT_LEFT_1))]
      THEN CONV_TAC (ONCE_DEPTH_CONV num_CONV)
      THEN MATCH_MP_TAC DIV_MULT THEN FIRST_ASSUM ACCEPT_TAC;
      DISCH_THEN (CHOOSE_TAC o (MATCH_MP (SPEC "r:num" DA)))
      THEN POP_ASSUM (CHOOSE_THEN STRIP_ASSUME_TAC)
      THEN SUBST1_TAC (ASSUME "r = (q * n) + r'")
      THEN PURE_ONCE_REWRITE_TAC[ADD_ASSOC]
      THEN SUBST1_TAC MULT_LEM
      THEN IMP_RES_THEN (\t. REWRITE_TAC[t]) DIV_MULT]);;

let ADD_DIV_ADD_DIV = prove_thm(`ADD_DIV_ADD_DIV`,
    "!n. 0 < n ==> !x r. ((((x * n) + r) DIV n) = x + (r DIV n))",
    CONV_TAC (REDEPTH_CONV RIGHT_IMP_FORALL_CONV)
    THEN REPEAT GEN_TAC THEN ASM_CASES_TAC "r < n" THENL[
      IMP_RES_THEN SUBST1_TAC LESS_DIV_EQ_ZERO THEN DISCH_TAC
      THEN PURE_ONCE_REWRITE_TAC[ADD_0]
      THEN MATCH_MP_TAC DIV_MULT THEN FIRST_ASSUM ACCEPT_TAC;
      DISCH_THEN (CHOOSE_TAC o (MATCH_MP (SPEC "r:num" DA)))
      THEN POP_ASSUM (CHOOSE_THEN STRIP_ASSUME_TAC)
      THEN SUBST1_TAC (ASSUME "r = (q * n) + r'")
      THEN PURE_ONCE_REWRITE_TAC[ADD_ASSOC]
      THEN PURE_ONCE_REWRITE_TAC[GSYM RIGHT_ADD_DISTRIB]
      THEN IMP_RES_THEN (\t. REWRITE_TAC[t]) DIV_MULT]);;

let SUC_DIV_CASES = prove_thm(`SUC_DIV_CASES`,
    "!n. 0 < n ==> 
     !x. ((SUC x) DIV n  = x DIV n) \/ ((SUC x) DIV n = SUC(x DIV n))",
    let ADD_lemma = GEN_ALL (SYM (el 4 (CONJ_LIST 4 ADD_CLAUSES))) in
    REPEAT STRIP_TAC THEN IMP_RES_THEN 
      (\t. (REPEAT_TCL CHOOSE_THEN (CONJUNCTS_THEN2 SUBST1_TAC ASSUME_TAC)
    	(SPEC "x:num" t))) DA
    THEN PURE_ONCE_REWRITE_TAC[ADD_lemma]
    THEN IMP_RES_THEN (\t.REWRITE_TAC[t]) ADD_DIV_ADD_DIV
    THEN DISJ_CASES_THEN2 ASSUME_TAC (\t.SUBST_OCCS_TAC[[3],SYM t])
      (PURE_ONCE_REWRITE_RULE[LESS_OR_EQ](MATCH_MP LESS_OR (ASSUME " r < n")))
    THENL[
      DISJ1_TAC THEN IMP_RES_TAC LESS_DIV_EQ_ZERO
      THEN ASM_REWRITE_TAC[ADD_0];
      DISJ2_TAC THEN PURE_ONCE_REWRITE_TAC[SUC_DIV_SELF]
      THEN IMP_RES_TAC LESS_DIV_EQ_ZERO
      THEN ASM_REWRITE_TAC[ADD_CLAUSES;(GSYM ADD1)]]);;

let Less_lemma = PROVE(
    "!m n. m < n ==> ?p. (n = m + p) /\ 0 < p",
    GEN_TAC THEN INDUCT_TAC THENL[
      REWRITE_TAC[NOT_LESS_0];
      REWRITE_TAC[LESS_THM]
      THEN DISCH_THEN (DISJ_CASES_THEN2 SUBST1_TAC ASSUME_TAC) THENL[
    	EXISTS_TAC "1" THEN CONV_TAC ((RAND_CONV o RAND_CONV)num_CONV)
    	THEN REWRITE_TAC[LESS_0;ADD1];
    	RES_TAC THEN EXISTS_TAC "SUC p"
    	THEN ASM_REWRITE_TAC[ADD_CLAUSES;LESS_0]]]);;

let LESS_MONO_DIV = PROVE(
    "!n. 0 < n ==> !p q. p < q ==> ((p DIV n) <= (q DIV n))",
    CONV_TAC (REDEPTH_CONV RIGHT_IMP_FORALL_CONV)
    THEN REPEAT GEN_TAC THEN DISCH_TAC
    THEN DISCH_THEN ((CHOOSE_THEN (CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC)) o
    	(MATCH_MP Less_lemma))
    THEN REPEAT_TCL CHOOSE_THEN (CONJUNCTS_THEN2 SUBST1_TAC ASSUME_TAC)
    	(SPEC "p:num" (MATCH_MP DA (ASSUME "0 < n")))
    THEN IMP_RES_THEN (\t.REWRITE_TAC[t]) DIV_MULT
    THEN PURE_ONCE_REWRITE_TAC[GSYM ADD_ASSOC]
    THEN IMP_RES_TAC ADD_DIV_ADD_DIV
    THEN ASM_REWRITE_TAC[LESS_EQ_ADD]);;

let LESS_EQ_MONO_DIV = prove_thm(`LESS_EQ_MONO_DIV`,
    "!n. 0 < n ==> !p q. p <= q ==> ((p DIV n) <= (q DIV n))",
    CONV_TAC (REDEPTH_CONV RIGHT_IMP_FORALL_CONV)
    THEN REPEAT GEN_TAC THEN DISCH_TAC
    THEN DISCH_THEN (\t. DISJ_CASES_THEN2 ASSUME_TAC SUBST1_TAC
    	(REWRITE_RULE[LESS_OR_EQ]t)) THENL[
     IMP_RES_TAC LESS_MONO_DIV;
     REWRITE_TAC[LESS_EQ_REFL]]);;

let Less_MULT_lemma = PROVE(
    "!r m p. 0 < p ==> (r < m) ==> (r < (p * m))",
    let lem1 = MATCH_MP LESS_LESS_EQ_TRANS 
    	(CONJ (SPEC "m:num" LESS_SUC_REFL)
    	      (SPECL["SUC m"; "p*(SUC m)"] LESS_EQ_ADD)) in
    GEN_TAC THEN REPEAT INDUCT_TAC THEN REWRITE_TAC[NOT_LESS_0]
    THEN DISCH_TAC THEN REWRITE_TAC[LESS_THM]
    THEN DISCH_THEN (DISJ_CASES_THEN2 SUBST1_TAC ASSUME_TAC)
    THEN PURE_ONCE_REWRITE_TAC[MULT]
    THEN PURE_ONCE_REWRITE_TAC[ADD_SYM] THENL[
      ACCEPT_TAC lem1;
      ACCEPT_TAC (MATCH_MP LESS_TRANS (CONJ (ASSUME "r < m") lem1))]);;

let Less_MULT_ADD_lemma = PROVE(
  "!m n r r'. 0 < m /\ 0 < n /\ r < m /\ r' < n ==> ((r' * m) + r) < (n * m)",
    REPEAT STRIP_TAC
    THEN CHOOSE_THEN STRIP_ASSUME_TAC (MATCH_MP Less_lemma (ASSUME "r < m"))
    THEN CHOOSE_THEN STRIP_ASSUME_TAC (MATCH_MP Less_lemma (ASSUME "r' < n"))
    THEN ASM_REWRITE_TAC[]
    THEN PURE_ONCE_REWRITE_TAC[RIGHT_ADD_DISTRIB]
    THEN PURE_ONCE_REWRITE_TAC[ADD_SYM]
    THEN PURE_ONCE_REWRITE_TAC[LESS_MONO_ADD_EQ]
    THEN SUBST1_TAC (SYM (ASSUME"m = r + p"))
    THEN IMP_RES_TAC Less_MULT_lemma);;

let DIV_DIV_DIV_MULT = prove_thm(`DIV_DIV_DIV_MULT`,
    "!m n. (0 < m) /\ (0 < n)  ==> !x. ((x DIV m) DIV n = x  DIV (m * n))",
    CONV_TAC (ONCE_DEPTH_CONV RIGHT_IMP_FORALL_CONV) THEN REPEAT STRIP_TAC
    THEN REPEAT_TCL CHOOSE_THEN (CONJUNCTS_THEN2 SUBST1_TAC ASSUME_TAC)
    	(SPEC "x:num" (MATCH_MP DA (ASSUME "0 < m")))
    THEN REPEAT_TCL CHOOSE_THEN (CONJUNCTS_THEN2 SUBST1_TAC ASSUME_TAC)
    	(SPEC "q:num" (MATCH_MP DA (ASSUME "0 < n")))
    THEN IMP_RES_THEN (\t.REWRITE_TAC[t]) DIV_MULT
    THEN IMP_RES_THEN (\t.REWRITE_TAC[t]) DIV_MULT
    THEN PURE_ONCE_REWRITE_TAC[RIGHT_ADD_DISTRIB]
    THEN PURE_ONCE_REWRITE_TAC[GSYM MULT_ASSOC]
    THEN PURE_ONCE_REWRITE_TAC[GSYM ADD_ASSOC]
    THEN ASSUME_TAC (MATCH_MP NOT_MULT_LESS_0
    	(CONJ (ASSUME "0 < n") (ASSUME "0 < m")))
    THEN CONV_TAC ((RAND_CONV o RAND_CONV) (REWR_CONV MULT_SYM))
    THEN CONV_TAC SYM_CONV THEN PURE_ONCE_REWRITE_TAC[ADD_INV_0_EQ]
    THEN FIRST_ASSUM (\t.REWRITE_TAC[MATCH_MP ADD_DIV_ADD_DIV t])
    THEN PURE_ONCE_REWRITE_TAC[ADD_INV_0_EQ]
    THEN MATCH_MP_TAC LESS_DIV_EQ_ZERO
    THEN IMP_RES_TAC Less_MULT_ADD_lemma);;

close_theory();;