@@ -19,7 +19,6 @@ namespace tactic
19
19
namespace ring
20
20
21
21
meta structure cache :=
22
- -- (m : expr_map ℕ)
23
22
(α : expr)
24
23
(univ : level)
25
24
(comm_semiring_inst : expr)
@@ -50,6 +49,41 @@ match expr.to_int e with
50
49
end
51
50
end
52
51
52
+ meta def normal_form_to_string : expr → string
53
+ | e := match destruct e with
54
+ | some (destruct_ty.const n) := to_string n
55
+ | some (destruct_ty.xadd a x _ n b) :=
56
+ " (" ++ normal_form_to_string a ++ " ) * (" ++ to_string x ++ " )^"
57
+ ++ to_string n ++ " + " ++ normal_form_to_string b
58
+ | none := to_string e
59
+ end
60
+
61
+ theorem zero_horner {α} [comm_semiring α] (x n b) :
62
+ @horner α _ 0 x n b = b :=
63
+ by simp [horner]
64
+
65
+ theorem horner_horner {α} [comm_semiring α] (a₁ x n₁ n₂ b n')
66
+ (h : n₁ + n₂ = n') :
67
+ @horner α _ (horner a₁ x n₁ 0 ) x n₂ b = horner a₁ x n' b :=
68
+ by simp [h.symm, horner, pow_add, mul_assoc]
69
+
70
+ meta def eval_horner (c : cache) (a x n b : expr) : tactic (expr × expr) :=
71
+ do d ← destruct a, match d with
72
+ | destruct_ty.const 0 :=
73
+ return (b, c.cs_app ``zero_horner [x, n, b])
74
+ | destruct_ty.const _ := do
75
+ let e := c.cs_app ``horner [a, x, n, b],
76
+ p ← mk_eq_refl e, return (e, p)
77
+ | destruct_ty.xadd a₁ x₁ n₁ _ b₁ :=
78
+ if x₁ = x ∧ b₁.to_nat = some 0 then do
79
+ (n', h) ← mk_app ``has_mul .mul [n₁, n] >>= norm_num,
80
+ return (c.cs_app ``horner [a₁, x, n', b],
81
+ c.cs_app ``horner_horner [a₁, x, n₁, n, b, n', h])
82
+ else do
83
+ let e := c.cs_app ``horner [a, x, n, b],
84
+ p ← mk_eq_refl e, return (e, p)
85
+ end
86
+
53
87
theorem const_add_horner {α} [comm_semiring α] (k a x n b b') (h : k + b = b') :
54
88
k + @horner α _ a x n b = horner a x n b' :=
55
89
by simp [h.symm, horner]
@@ -68,10 +102,10 @@ theorem horner_add_horner_gt {α} [comm_semiring α] (a₁ x n₁ b₁ a₂ n₂
68
102
@horner α _ a₁ x n₁ b₁ + horner a₂ x n₂ b₂ = horner (horner a₁ x k a₂) x n₂ b' :=
69
103
by simp [h₂.symm, h₁.symm, horner, pow_add, mul_add, mul_comm, mul_left_comm]
70
104
71
- theorem horner_add_horner_eq {α} [comm_semiring α] (a₁ x n b₁ a₂ b₂ a' b')
72
- (h₁ : a₁ + a₂ = a') (h₂ : b₁ + b₂ = b') :
73
- @horner α _ a₁ x n b₁ + horner a₂ x n b₂ = horner a' x n b' :=
74
- by simp [h₂.symm, h₁.symm, horner, mul_add, mul_comm]
105
+ theorem horner_add_horner_eq {α} [comm_semiring α] (a₁ x n b₁ a₂ b₂ a' b' t )
106
+ (h₁ : a₁ + a₂ = a') (h₂ : b₁ + b₂ = b') (h₃ : horner a' x n b' = t) :
107
+ @horner α _ a₁ x n b₁ + horner a₂ x n b₂ = t :=
108
+ by simp [h₃.symm, h ₂.symm, h₁.symm, horner, mul_add, mul_comm]
75
109
76
110
meta def eval_add (c : cache) : expr → expr → tactic (expr × expr)
77
111
| e₁ e₂ := do d₁ ← destruct e₁, d₂ ← destruct e₂,
@@ -93,33 +127,32 @@ match d₁, d₂ with
93
127
return (c.cs_app ``horner [a, x, n, b'],
94
128
c.cs_app ``horner_add_const [a, x, n, b, e₂, b', h])
95
129
| destruct_ty.xadd a₁ x₁ en₁ n₁ b₁, destruct_ty.xadd a₂ x₂ en₂ n₂ b₂ :=
96
- match cmp x₁ x₂, cmp n₁ n₂ with
97
- | ordering.lt, _ := do
130
+ if expr.lex_lt x₁ x₂ then do
98
131
(b', h) ← eval_add b₁ e₂,
99
132
return (c.cs_app ``horner [a₁, x₁, en₁, b'],
100
133
c.cs_app ``horner_add_const [a₁, x₁, en₁, b₁, e₂, b', h])
101
- | ordering.gt, _ := do
134
+ else if x₁ ≠ x₂ then do
102
135
(b', h) ← eval_add e₁ b₂,
103
136
return (c.cs_app ``horner [a₂, x₂, en₂, b'],
104
137
c.cs_app ``const_add_horner [e₁, a₂, x₂, en₂, b₂, b', h])
105
- | ordering.eq, ordering.lt := do
138
+ else if n₁ < n₂ then do
106
139
k ← expr.of_nat c.α (n₂ - n₁),
107
140
(_, h₁) ← mk_app ``has_add .add [en₁, k] >>= norm_num,
108
141
(b', h₂) ← eval_add b₁ b₂,
109
142
return (c.cs_app ``horner [c.cs_app ``horner [a₂, x₁, k, a₁], x₁, en₁, b'],
110
143
c.cs_app ``horner_add_horner_lt [a₁, x₁, en₁, b₁, a₂, en₂, b₂, k, b', h₁, h₂])
111
- | ordering.eq, ordering.gt := do
144
+ else if n₁ ≠ n₂ then do
112
145
k ← expr.of_nat c.α (n₁ - n₂),
113
146
(_, h₁) ← mk_app ``has_add .add [en₂, k] >>= norm_num,
114
147
(b', h₂) ← eval_add b₁ b₂,
115
148
return (c.cs_app ``horner [c.cs_app ``horner [a₁, x₁, k, a₂], x₁, en₂, b'],
116
149
c.cs_app ``horner_add_horner_gt [a₁, x₁, en₁, b₁, a₂, en₂, b₂, k, b', h₁, h₂])
117
- | ordering.eq, ordering.eq := do
150
+ else do
118
151
(a', h₁) ← eval_add a₁ a₂,
119
152
(b', h₂) ← eval_add b₁ b₂,
120
- return (c.cs_app ``horner [a', x₁, en₁, b'] ,
121
- c.cs_app ``horner_add_horner_eq [a₁, x₁, en₁, b₁, a₂, b₂, a', b', h₁, h₂])
122
- end
153
+ (t, h₃) ← eval_horner c a' x₁ en₁ b',
154
+ return (t, c.cs_app ``horner_add_horner_eq
155
+ [a₁, x₁, en₁, b₁, a₂, b₂, a', b', t, h₁, h₂, h₃])
123
156
end
124
157
125
158
theorem horner_neg {α} [comm_ring α] (a x n b a' b')
@@ -159,32 +192,6 @@ do d ← destruct e, match d with
159
192
c.cs_app ``horner_const_mul [k, a, x, n, b, a', b', h₁, h₂])
160
193
end
161
194
162
- theorem zero_horner {α} [comm_semiring α] (x n b) :
163
- @horner α _ 0 x n b = b :=
164
- by simp [horner]
165
-
166
- theorem horner_horner {α} [comm_semiring α] (a₁ x n₁ n₂ b n')
167
- (h : n₁ + n₂ = n') :
168
- @horner α _ (horner a₁ x n₁ 0 ) x n₂ b = horner a₁ x n' b :=
169
- by simp [h.symm, horner, pow_add, mul_assoc]
170
-
171
- meta def eval_horner (c : cache) (a x n b : expr) : tactic (expr × expr) :=
172
- do d ← destruct a, match d with
173
- | destruct_ty.const 0 :=
174
- return (b, c.cs_app ``zero_horner [x, n, b])
175
- | destruct_ty.const _ := do
176
- let e := c.cs_app ``zero_horner [a, x, n, b],
177
- p ← mk_eq_refl e, return (e, p)
178
- | destruct_ty.xadd a₁ x₁ n₁ _ b₁ :=
179
- if x₁ = x ∧ b₁.to_nat = some 0 then do
180
- (n', h) ← mk_app ``has_mul .mul [n₁, n] >>= norm_num,
181
- return (c.cs_app ``horner [a₁, x, n', b],
182
- c.cs_app ``horner_horner [a₁, x, n₁, n, b, n', h])
183
- else do
184
- let e := c.cs_app ``horner [a, x, n, b],
185
- p ← mk_eq_refl e, return (e, p)
186
- end
187
-
188
195
theorem horner_mul_horner_zero {α} [comm_semiring α] (a₁ x n₁ b₁ a₂ n₂ aa t)
189
196
(h₁ : @horner α _ a₁ x n₁ b₁ * a₂ = aa)
190
197
(h₂ : horner aa x n₂ 0 = t) :
@@ -221,18 +228,17 @@ match d₁, d₂ with
221
228
(e', p₂) ← eval_mul e₂ e₁,
222
229
p ← mk_eq_trans p₁ p₂, return (e', p)
223
230
| destruct_ty.xadd a₁ x₁ en₁ n₁ b₁, destruct_ty.xadd a₂ x₂ en₂ n₂ b₂ :=
224
- match cmp x₁ x₂ with
225
- | ordering.lt := do
231
+ if expr.lex_lt x₁ x₂ then do
226
232
(a', h₁) ← eval_mul a₁ e₂,
227
233
(b', h₂) ← eval_mul b₁ e₂,
228
234
return (c.cs_app ``horner [a', x₁, en₁, b'],
229
235
c.cs_app ``horner_mul_const [a₁, x₁, en₁, b₁, e₂, a', b', h₁, h₂])
230
- | ordering.gt := do
236
+ else if x₁ ≠ x₂ then do
231
237
(a', h₁) ← eval_mul e₁ a₂,
232
238
(b', h₂) ← eval_mul e₁ b₂,
233
239
return (c.cs_app ``horner [a', x₂, en₂, b'],
234
240
c.cs_app ``horner_const_mul [e₁, a₂, x₂, en₂, b₂, a', b', h₁, h₂])
235
- | ordering.eq := do
241
+ else do
236
242
(aa, h₁) ← eval_mul e₁ a₂,
237
243
α0 ← expr.of_nat c.α 0 ,
238
244
(haa, h₂) ← eval_horner c aa x₁ en₂ α0 ,
@@ -245,7 +251,6 @@ match d₁, d₂ with
245
251
(t, H) ← eval_add c haa (c.cs_app ``horner [ab, x₁, en₁, bb]),
246
252
return (t, c.cs_app ``horner_mul_horner
247
253
[a₁, x₁, en₁, b₁, a₂, en₂, b₂, aa, haa, ab, bb, t, h₁, h₂, h₃, h₄, H])
248
- end
249
254
end
250
255
251
256
theorem horner_pow {α} [comm_semiring α] (a x n m n' a')
@@ -342,39 +347,24 @@ meta def eval (c : cache) : expr → tactic (expr × expr)
342
347
| none := eval_atom c e
343
348
end
344
349
345
- meta def derive1 : expr → tactic (expr × expr)
346
- | `(%%e₁ = %%e₂) := do
347
- c ← mk_cache e₁,
348
- (e₁', p₁) ← eval c e₁,
349
- (e₂', p₂) ← eval c e₂,
350
- is_def_eq e₁' e₂' <|> fail " normal forms not equal, possibly false" ,
351
- p ← mk_eq_symm p₂ >>= mk_eq_trans p₁,
352
- p ← mk_app ``eq_true_intro [p],
353
- return (expr.const `true [], p)
354
- | _ := fail " derive1 not applicable"
355
-
356
- meta def derive : expr → tactic (expr × expr) | e :=
357
- do (_, e', pr) ←
358
- ext_simplify_core () {} simp_lemmas.mk (λ _, failed) (λ _ _ _ _ _, failed)
359
- (λ _ _ _ _ e,
360
- do (new_e, pr) ← derive1 e,
361
- guard (¬ new_e =ₐ e),
362
- return ((), new_e, some pr, tt))
363
- `eq e,
364
- return (e', pr)
365
-
366
350
end ring
367
351
368
352
namespace interactive
369
353
open interactive interactive.types
354
+ open tactic.ring
370
355
371
356
/-- Tactic for solving equations in the language of rings. -/
372
- meta def ring (loc : parse location) : tactic unit :=
373
- do ns ← loc.get_locals,
374
- tt ← tactic.replace_at tactic.ring.derive ns loc.include_goal
375
- | fail " ring failed to simplify" ,
376
- when loc.include_goal $ try tactic.triv,
377
- when (¬ ns.empty) $ try tactic.contradiction
357
+ meta def ring : tactic unit :=
358
+ do `(%%e₁ = %%e₂) ← target,
359
+ c ← mk_cache e₁,
360
+ (e₁', p₁) ← eval c e₁,
361
+ (e₂', p₂) ← eval c e₂,
362
+ is_def_eq e₁' e₂' <|> fail
363
+ (" normal forms not equal, possibly false" ++
364
+ " \n LHS = " ++ normal_form_to_string e₁' ++
365
+ " \n RHS = " ++ normal_form_to_string e₂'),
366
+ p ← mk_eq_symm p₂ >>= mk_eq_trans p₁,
367
+ tactic.exact p
378
368
379
369
end interactive
380
370
end tactic
0 commit comments