Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 341fd51

Browse files
committed
fix(tactic/ring): bugfix
1 parent 2e2d89b commit 341fd51

File tree

1 file changed

+62
-72
lines changed

1 file changed

+62
-72
lines changed

tactic/ring.lean

Lines changed: 62 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ namespace tactic
1919
namespace ring
2020

2121
meta structure cache :=
22-
--(m : expr_map ℕ)
2322
(α : expr)
2423
(univ : level)
2524
(comm_semiring_inst : expr)
@@ -50,6 +49,41 @@ match expr.to_int e with
5049
end
5150
end
5251

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+
5387
theorem const_add_horner {α} [comm_semiring α] (k a x n b b') (h : k + b = b') :
5488
k + @horner α _ a x n b = horner a x n b' :=
5589
by simp [h.symm, horner]
@@ -68,10 +102,10 @@ theorem horner_add_horner_gt {α} [comm_semiring α] (a₁ x n₁ b₁ a₂ n₂
68102
@horner α _ a₁ x n₁ b₁ + horner a₂ x n₂ b₂ = horner (horner a₁ x k a₂) x n₂ b' :=
69103
by simp [h₂.symm, h₁.symm, horner, pow_add, mul_add, mul_comm, mul_left_comm]
70104

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]
75109

76110
meta def eval_add (c : cache) : expr → expr → tactic (expr × expr)
77111
| e₁ e₂ := do d₁ ← destruct e₁, d₂ ← destruct e₂,
@@ -93,33 +127,32 @@ match d₁, d₂ with
93127
return (c.cs_app ``horner [a, x, n, b'],
94128
c.cs_app ``horner_add_const [a, x, n, b, e₂, b', h])
95129
| 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
98131
(b', h) ← eval_add b₁ e₂,
99132
return (c.cs_app ``horner [a₁, x₁, en₁, b'],
100133
c.cs_app ``horner_add_const [a₁, x₁, en₁, b₁, e₂, b', h])
101-
| ordering.gt, _ := do
134+
else if x₁ ≠ x₂ then do
102135
(b', h) ← eval_add e₁ b₂,
103136
return (c.cs_app ``horner [a₂, x₂, en₂, b'],
104137
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
106139
k ← expr.of_nat c.α (n₂ - n₁),
107140
(_, h₁) ← mk_app ``has_add.add [en₁, k] >>= norm_num,
108141
(b', h₂) ← eval_add b₁ b₂,
109142
return (c.cs_app ``horner [c.cs_app ``horner [a₂, x₁, k, a₁], x₁, en₁, b'],
110143
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
112145
k ← expr.of_nat c.α (n₁ - n₂),
113146
(_, h₁) ← mk_app ``has_add.add [en₂, k] >>= norm_num,
114147
(b', h₂) ← eval_add b₁ b₂,
115148
return (c.cs_app ``horner [c.cs_app ``horner [a₁, x₁, k, a₂], x₁, en₂, b'],
116149
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
118151
(a', h₁) ← eval_add a₁ a₂,
119152
(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₃])
123156
end
124157

125158
theorem horner_neg {α} [comm_ring α] (a x n b a' b')
@@ -159,32 +192,6 @@ do d ← destruct e, match d with
159192
c.cs_app ``horner_const_mul [k, a, x, n, b, a', b', h₁, h₂])
160193
end
161194

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-
188195
theorem horner_mul_horner_zero {α} [comm_semiring α] (a₁ x n₁ b₁ a₂ n₂ aa t)
189196
(h₁ : @horner α _ a₁ x n₁ b₁ * a₂ = aa)
190197
(h₂ : horner aa x n₂ 0 = t) :
@@ -221,18 +228,17 @@ match d₁, d₂ with
221228
(e', p₂) ← eval_mul e₂ e₁,
222229
p ← mk_eq_trans p₁ p₂, return (e', p)
223230
| 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
226232
(a', h₁) ← eval_mul a₁ e₂,
227233
(b', h₂) ← eval_mul b₁ e₂,
228234
return (c.cs_app ``horner [a', x₁, en₁, b'],
229235
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
231237
(a', h₁) ← eval_mul e₁ a₂,
232238
(b', h₂) ← eval_mul e₁ b₂,
233239
return (c.cs_app ``horner [a', x₂, en₂, b'],
234240
c.cs_app ``horner_const_mul [e₁, a₂, x₂, en₂, b₂, a', b', h₁, h₂])
235-
| ordering.eq := do
241+
else do
236242
(aa, h₁) ← eval_mul e₁ a₂,
237243
α0 ← expr.of_nat c.α 0,
238244
(haa, h₂) ← eval_horner c aa x₁ en₂ α0,
@@ -245,7 +251,6 @@ match d₁, d₂ with
245251
(t, H) ← eval_add c haa (c.cs_app ``horner [ab, x₁, en₁, bb]),
246252
return (t, c.cs_app ``horner_mul_horner
247253
[a₁, x₁, en₁, b₁, a₂, en₂, b₂, aa, haa, ab, bb, t, h₁, h₂, h₃, h₄, H])
248-
end
249254
end
250255

251256
theorem horner_pow {α} [comm_semiring α] (a x n m n' a')
@@ -342,39 +347,24 @@ meta def eval (c : cache) : expr → tactic (expr × expr)
342347
| none := eval_atom c e
343348
end
344349

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-
366350
end ring
367351

368352
namespace interactive
369353
open interactive interactive.types
354+
open tactic.ring
370355

371356
/-- 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
378368

379369
end interactive
380370
end tactic

0 commit comments

Comments
 (0)