Zulip Chat Archive
Stream: general
Topic: tidy bug
Patrick Massot (Oct 02 2018 at 20:01):
Can someone try
import tactic.tidy example (X Y : Type) (f : X → Y) (h : ∀ y : Y, ∃ x : X, f(x) = y) : (∃ g : Y → X, f ∘ g = id) := begin cases classical.axiom_of_choice h with g H, tidy, end
Patrick Massot (Oct 02 2018 at 20:02):
Here it says no goals
after tidy
but red-squiggle example
with type mismatch at application g a term a has type Y_1 but is expected to have type Y types contain aliased name(s): Y remark: the tactic `dedup` can be used to rename aliases
Bryan Gin-ge Chen (Oct 02 2018 at 20:05):
Here it says
no goals
aftertidy
but red-squiggleexample
withtype mismatch at application g a term a has type Y_1 but is expected to have type Y types contain aliased name(s): Y remark: the tactic `dedup` can be used to rename aliases
I get the same.
Patrick Massot (Oct 02 2018 at 20:07):
Let's wait for @Scott Morrison to wake up, or finish lunch, or whatever it's time to do in Australia
Bryan Gin-ge Chen (Oct 02 2018 at 20:08):
Here's the trace:
/- `tidy` says -/ dsimp at *, fsplit, work_on_goal 0 { intros a }, work_on_goal 1 { ext1, dsimp at *, solve_by_elim }
Patrick Massot (Oct 02 2018 at 20:08):
I'm working on that demo file we discussed earlier, trying to see what general purpose automation can do what. The problem with magic is it's somewhat unpredictable. It seems finish
is pretty powerful in those example, but I'd like to understand when tidy
or tauto
actually also work (or even work better)
Patrick Massot (Oct 02 2018 at 20:10):
Good idea Bryan!
Bryan Gin-ge Chen (Oct 02 2018 at 20:10):
Not sure if I misunderstand the meaning of the trace, but throwing it in as a proof fails at the first dsimp
Patrick Massot (Oct 02 2018 at 20:10):
It's very strange to follow, it seems hopeless and then solve_by_elim
pretends to get rid of all meta-vars and do the job
Patrick Massot (Oct 02 2018 at 20:11):
here I get exactly the same result as with tidy itself
Patrick Massot (Oct 02 2018 at 20:11):
google says Scott may be sleeping
Bryan Gin-ge Chen (Oct 02 2018 at 20:12):
I see this:
import tactic.tidy example (X Y : Type) (f : X → Y) (h : ∀ y : Y, ∃ x : X, f(x) = y) : (∃ g : Y → X, f ∘ g = id) := begin dsimp at *, -- squiggly line under dsimp /- Tactic State X Y : Type, f : X → Y, h : ∀ (y : Y), ∃ (x : X), f x = y ⊢ ∃ (g : Y → X), f ∘ g = id scratch.lean:14:0: error dsimplify tactic failed to simplify state: ⊢ ∀ (X Y : Type) (f : X → Y), (∀ (y : Y), ∃ (x : X), f x = y) → (∃ (g : Y → X), f ∘ g = id) -/ fsplit, work_on_goal 0 { intros a }, work_on_goal 1 { ext1, dsimp at *, solve_by_elim } end
Patrick Massot (Oct 02 2018 at 20:13):
you erased too much
Patrick Massot (Oct 02 2018 at 20:13):
the choice idea is required
Bryan Gin-ge Chen (Oct 02 2018 at 20:13):
Oops!
Bryan Gin-ge Chen (Oct 02 2018 at 20:26):
Yes, now I see the same.
Nothing seems strange with the intermediate tactic states. Is there a way to use the discharger
option for solve_by_elim
to make it spit out what it's doing at each stage?
Patrick Massot (Oct 02 2018 at 20:29):
How is it possible that none of our general purpose weapon can kill
example (X Y : Type) (f : X → Y) (g : Y → X) (h : f ∘ g = id ) (y : Y) : f (g y) = y
Kenny Lau (Oct 02 2018 at 20:30):
I don't use weapons :P
example (X Y : Type) (f : X → Y) (g : Y → X) (h : f ∘ g = id ) (y : Y) : f (g y) = y := congr_fun h y
Patrick Massot (Oct 02 2018 at 20:31):
Kenny, this is exactly what I did at https://github.com/PatrickMassot/lean-scratchpad/blob/master/src/demo.lean#L60 but I'm trying to rewrite this file using automation, for comparison
Patrick Massot (Oct 02 2018 at 20:32):
I guess this is again because tactic writers don't like function equalities, especially with compositions
Bryan Gin-ge Chen (Oct 02 2018 at 20:32):
Replacing solve_by_elim
with apply_assumption
gives the same strange behavior.
Rob Lewis (Oct 02 2018 at 20:32):
Higher order reasoning is hard!
Patrick Massot (Oct 02 2018 at 20:33):
finish
and its friends could try to turn each function equality assumption into a forall
Patrick Massot (Oct 02 2018 at 20:34):
example (X Y : Type) (f : X → Y) (g : Y → X) (h : ∀ z, (f ∘ g) z = id z) (y : Y): f (g y) = y := by finish
does work
Patrick Massot (Oct 02 2018 at 20:35):
Of course rewriting h
like this is the most un-mathematical thing you could see
Kenny Lau (Oct 02 2018 at 20:35):
finish
and its friends
Patrick Massot (Oct 02 2018 at 20:39):
its friends are tauto
and tidy
Bryan Gin-ge Chen (Oct 02 2018 at 20:43):
Could it be that there's something strange happening with work_on_goal
? The following works:
import tactic.tidy example (X Y : Type) (f : X → Y) (h : ∀ y : Y, ∃ x : X, f(x) = y) : (∃ g : Y → X, f ∘ g = id) := begin cases classical.axiom_of_choice h with g H, dsimp at *, fsplit, { exact g }, { ext1, dsimp at *, apply_assumption } end
Bryan Gin-ge Chen (Oct 02 2018 at 20:44):
Compare this, which gives the same no goals
+ weird error as the initial tidy
call:
import tactic.tidy example (X Y : Type) (f : X → Y) (h : ∀ y : Y, ∃ x : X, f(x) = y) : (∃ g : Y → X, f ∘ g = id) := begin cases classical.axiom_of_choice h with g H, dsimp at *, fsplit, --{ exact g }, work_on_goal 1 { ext1, dsimp at *, apply_assumption } end
Patrick Massot (Oct 02 2018 at 20:46):
interesting
Patrick Massot (Oct 02 2018 at 20:48):
Even better:
example (X Y : Type) (f : X → Y) (h : ∀ y : Y, ∃ x : X, f(x) = y) : (∃ g : Y → X, f ∘ g = id) := begin cases classical.axiom_of_choice h with g H, dsimp at *, fsplit, { exact g }, work_on_goal 0 { ext1, dsimp at *, apply_assumption } end
works!
Patrick Massot (Oct 02 2018 at 20:50):
but actually this is getting far away from what tidy suggested
Bryan Gin-ge Chen (Oct 02 2018 at 20:53):
Here's work_on_goal
. If I had to guess, there's something wrong in here, possibly in handling what happens if a goal gets solved.
Bryan Gin-ge Chen (Oct 02 2018 at 21:29):
I think the problem is that when apply_assumption
kills off a goal, it does not return properly to work_on_goal
. Then lean thinks it has finished, but in reality there are more goals that work_on_goal
just temporarily deleted. There are no issues when exact g
finishes a goal inside work_on_goal
, so there's something going on with this particular interaction.
Bryan Gin-ge Chen (Oct 02 2018 at 21:31):
apply_assumption
is here, but it's too monad-y for me to make sense of at the moment.
Simon Hudon (Oct 02 2018 at 21:42):
What problem are you looking for?
Bryan Gin-ge Chen (Oct 02 2018 at 22:07):
Patrick started this thread with an example where tidy
leaves the tactic state with no goals
but there is a strange error.
I'm proposing that the root cause of this is due to apply_assumption
not returning properly to work_on_goal
.
Scott Morrison (Oct 02 2018 at 22:08):
Thanks for these bug reports. I probably won't have a chance to work on it until the weekend.
Kenny Lau (Oct 02 2018 at 22:36):
import tactic.interactive example (X Y : Type) (f : X → Y) (g : Y → X) (h : ∀ z, (f ∘ g) z = id z) (y : Y): f (g y) = y := by tauto
Kenny Lau (Oct 02 2018 at 22:36):
@Patrick Massot
Patrick Massot (Oct 03 2018 at 07:14):
Thanks Kenny, but this is the version I don't want, because h
is stated un-mathematically
Yaël Dillies (Aug 15 2022 at 08:22):
Looks like tidy
used the same variable name twice:
import logic.relation
variables {α β γ δ ε κ : Type*}
example (r : α → β → Prop) (f₁ : α → γ) (g₁ : β → δ) (f₂ : γ → ε) (g₂ : δ → κ) :
relation.map (relation.map r f₁ g₁) f₂ g₂ = relation.map r (f₂ ∘ f₁) (g₂ ∘ g₁) :=
by tidy
/-
type mismatch at application
r ᾰ_h_h_left_w
term
ᾰ_h_h_left_w
has type
α_1
but is expected to have type
α
types contain aliased name(s): α
remark: the tactic `dedup` can be used to rename aliases
-/
Bhavik Mehta (Aug 16 2022 at 15:21):
Is this a bug in tidy
or in one of the things tidy
uses? If I remember correctly, tidy
doesn't have the ability to choose variable names whatsoever, just to call other tactics
Kevin Buzzard (Aug 16 2022 at 21:28):
example (r : α → β → Prop) (f₁ : α → γ) (g₁ : β → δ) (f₂ : γ → ε) (g₂ : δ → κ) :
relation.map (relation.map r f₁ g₁) f₂ g₂ = relation.map r (f₂ ∘ f₁) (g₂ ∘ g₁) :=
begin
ext1,
ext1,
simp at *,
fsplit,
work_on_goal 1
{ intros ᾰ,
cases ᾰ,
cases ᾰ_h, cases ᾰ_h_h, cases ᾰ_h_h_right, cases ᾰ_h_h_left, cases ᾰ_h_h_left_h,
induction ᾰ_h_h_right_right, induction ᾰ_h_h_right_left, cases ᾰ_h_h_left_h_h,
cases ᾰ_h_h_left_h_h_right, induction ᾰ_h_h_left_h_h_right_right,
induction ᾰ_h_h_left_h_h_right_left,
fsplit,
work_on_goal 2
{ dsimp at *,
fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 1
{ assumption },
simp at * } } },
intros ᾰ, cases ᾰ, cases ᾰ_h, cases ᾰ_h_h, cases ᾰ_h_h_right,
induction ᾰ_h_h_right_right, induction ᾰ_h_h_right_left,
dsimp at *, fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 1 {
fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 1
{ assumption },
fsplit,
work_on_goal 1
{ refl },
refl } } },
simp at *, } },
end
/-
type mismatch at application
r ᾰ_h_h_left_w
term
ᾰ_h_h_left_w
has type
α_1
but is expected to have type
α
types contain aliased name(s): α
remark: the tactic `dedup` can be used to rename aliases
-/
(error at first line of example statement)
Kevin Buzzard (Aug 16 2022 at 21:46):
import logic.relation
variables {α β γ δ ε κ : Type*}
example (r : α → β → Prop) (f₁ : α → γ) (g₁ : β → δ) (f₂ : γ → ε) (g₂ : δ → κ) :
relation.map (relation.map r f₁ g₁) f₂ g₂ = relation.map r (f₂ ∘ f₁) (g₂ ∘ g₁) :=
begin
ext1,
ext1,
simp at *,
fsplit,
work_on_goal 1
{ rintros ⟨ᾰ_w, ᾰ_h_w, ⟨ᾰ_h_h_left_w, ᾰ_h_h_left_h_w, ᾰ_h_h_left_h_h_left, rfl, rfl⟩,
rfl, rfl⟩,
refine ⟨_, _⟩,
work_on_goal 2
{ dsimp at *, -- this line breaks it; comment out to fix proof
fsplit,
work_on_goal 2 {
fsplit,
work_on_goal 1
{ assumption },
simp at * } } },
rintro ⟨ᾰ_w, ᾰ_h_w, ᾰ_h_h_left, rfl, rfl⟩,
dsimp at *,
refine ⟨_, _, ⟨_, _, ᾰ_h_h_left, rfl, rfl⟩, rfl, rfl⟩,
end
/-
type mismatch at application
r ᾰ_h_h_left_w
term
ᾰ_h_h_left_w
has type
α_1
but is expected to have type
α
types contain aliased name(s): α
remark: the tactic `dedup` can be used to rename aliases
-/
Kevin Buzzard (Aug 16 2022 at 21:46):
tidy
is running dsimp
on a goal with metavariables and on some hypotheses all at the same time
Kevin Buzzard (Aug 16 2022 at 21:58):
This is as compact as I can get it:
import logic.relation
variables {α β γ δ ε κ : Type*}
example (r : α → β → Prop) (f₁ : α → γ) (g₁ : β → δ) (f₂ : γ → ε) (g₂ : δ → κ) :
relation.map (relation.map r f₁ g₁) f₂ g₂ = relation.map r (f₂ ∘ f₁) (g₂ ∘ g₁) :=
begin
ext1,
ext1,
simp only [eq_iff_iff],
refine ⟨_, _⟩,
{ rintros ⟨_, _, ⟨_, _, foo, rfl, rfl⟩, rfl, rfl⟩,
refine ⟨_, _⟩,
swap, -- new first goal now depends on metavariable in new second goal
{ dsimp at *, -- this line breaks it; comment out to fix proof
exact ⟨_, foo, by simp⟩, } },
{ rintro ⟨_, _, bar, rfl, rfl⟩,
exact ⟨_, _, ⟨_, _, bar, rfl, rfl⟩, rfl, rfl⟩, },
end
/-
type mismatch at application
r ᾰ_h_h_left_w
term
ᾰ_h_h_left_w
has type
α_1
but is expected to have type
α
types contain aliased name(s): α
remark: the tactic `dedup` can be used to rename aliases
-/
Last updated: Dec 20 2023 at 11:08 UTC