Zulip Chat Archive
Stream: general
Topic: deterministic timeout + goal accomplished
Simon Andreys (Dec 01 2020 at 14:58):
I got a "goal accomplished" together with a "deterministic timeout". This appends right at the end of a proof, at the "refl" or "simp" line. I found out that this problem was already encountered one week ago :
https://leanprover.zulipchat.com/#narrow/stream/240192-Berkeley-Lean.20Seminar/topic/Project.20ideas/near/217690233
This error message is quite dreadful (you feel so close, but you are so far), and I think it deserves its own topic. In my case, I found a different proof that work, but I still don't understand why my first, more beautiful proof fails. The issue was also solved in the discussion linked above. What I gathered is that :
-the issue is not actually at the "refl" but happens before, some tactic is messing around, corrupting some goal in the background, and when the compiler checks what's the tactic did, it gets lost.
-In the case linked above, replacing a "have" by a "let" in an isomorphism in the proof solved the problem. The isomorphism had to be describe explicitly.
-In my case, I replaced a proof based on a associativity lemmas by a proof with multiple dsimp and some lower level lemmas. I have still no idea where the error comes from, and I am afraid it is just under the carpet, ready to appear again.
Simon Andreys (Dec 01 2020 at 15:01):
Since I have a functioning proof (for now), this topic aims at documenting the issue rather than solving my problem, but here is the faulty code anyway :
lemma compq_quotient_assoc (p: polynomial R) (q : polynomial R) (I:ideal $ polynomial R) :
(quotient_cast (le_of_eq (comp_ideal_assoc p q I))).comp ( (compq_quotient q (comp_ideal p I) ).comp (compq_quotient p I))=
compq_quotient (p.comp q) I :=
begin
dsimp [compq_quotient, quotient_cast],
repeat {rw quotient_map_assoc},
congr',
simp,
rw compq_assoc, --goal accomplished but deterministic timeout
end
and the correct proof :
lemma compq_quotient_assoc' (p: polynomial R) (q : polynomial R) (I:ideal $ polynomial R) :
(quotient_cast (le_of_eq (comp_ideal_assoc p q I))).comp ( (compq_quotient q (comp_ideal p I) ).comp (compq_quotient p I))=
compq_quotient (p.comp q) I :=
begin
apply ring_hom.ext, intro aclass,
cases ideal.quotient.mk_surjective aclass with a ha,
dsimp [quotient_cast, compq_quotient, comp_ideal, ideal.quotient_map, ideal.map],
rw ← ha,
repeat {rw ideal.quotient.lift_mk},
simp,
dsimp [compq],
rw comp_assoc, --works fine, but slow
end
Finally, the full context :
Simon Andreys (Dec 01 2020 at 15:11):
The faulty proof uses a lemma quotient_map_assoc on the composition of ideal.quotient_map, maybe a similar lemma already exists but the closest I could find was ideal.comp_quotient_map_eq_of_comp_eq
The lemma quotient_map_assoc does not return any error, but I fear that it's where the mess happens. It's a shame because it looks useful.
Kevin Buzzard (Dec 01 2020 at 15:27):
The problem with the timing-out proof is congr'
(if you put sorry
immediately after the congr'
you get the timeout).
Simon Andreys (Dec 01 2020 at 15:45):
Indeed, but there may still be a mess earlier. When I get rid of the congr' and I try to do a rw, I get a "motive is not type correct". With simp_rw, the goal accomplished+timeout is back :
begin
dsimp [compq_quotient, quotient_cast],
repeat {rw quotient_map_assoc},
simp,
simp_rw compq_assoc q p, -- rw gives a "motive is not type correct" error, so I use simp_rw
refl, --ga +timeout
end
Mario Carneiro (Dec 01 2020 at 16:20):
you need four backticks for the spoiler tag if you want to put code in it
Simon Andreys (Dec 01 2020 at 16:23):
@Mario Carneiro thanks, it's done.
Simon Andreys (Dec 01 2020 at 16:25):
There is no coloration though.
Mario Carneiro (Dec 01 2020 at 16:25):
you need ```lean
probably
Mario Carneiro (Dec 01 2020 at 16:26):
it's set as the default language in this zulip instance but I guess it doesn't work under spoiler tags
Simon Andreys (Dec 01 2020 at 16:32):
Indeed color is back !
Simon Andreys (Dec 01 2020 at 17:02):
I think I understand the problem a bit more, having tested different things. I think it lies in the argument (hIJ : I ≤ ideal.comap f J)
of ideal.quotient_map . In VSCode, this argument is hidden in the current goal during the proof (but I get to see it if I hover on it). I think the rw tactics fails because if it replaces an expression in the first argument of quotient_map but does not modify it in the second argument, the obtained expression makes no sense. I suppose simp_rw and congr' both have a faulty treatment of this second argument. This is why taking a representative with ideal.quotient.mk_surjective and proving things outside of the quotient works in the second proof.
Mario Carneiro (Dec 01 2020 at 17:10):
So far I've managed to reduce the bad congr'
proof to this:
example {R : Type} [comm_ring R] (p q : polynomial R) (I : ideal (polynomial R))
(h1 : I ≤ ideal.comap
((ring_hom.id (polynomial R)).comp ((compq q).comp (compq p)))
(comp_ideal (p.comp q) I))
(h2 : I ≤ ideal.comap (compq (p.comp q)) (comp_ideal (p.comp q) I)) :
(comp_ideal (p.comp q) I).quotient_map
((ring_hom.id (polynomial R)).comp ((compq q).comp (compq p))) h1 =
(comp_ideal (p.comp q) I).quotient_map (compq (p.comp q)) h2 :=
begin
have H_congr_lemma := λ {I : ideal (polynomial R)} (J : ideal (polynomial R))
(f f_1 : polynomial R →+* polynomial R) (e_3 : f = f_1)
(hIJ : I ≤ ideal.comap f J) (hIJ_1 : I ≤ ideal.comap f_1 J),
(λ (I J : ideal (polynomial R)) (f f_1 : polynomial R →+* polynomial R) (e_3 : f = f_1)
(hIJ : I ≤ ideal.comap f J),
@eq.drec (polynomial R →+* polynomial R) f
(λ (f_1 : polynomial R →+* polynomial R) (e_3 : f = f_1),
J.quotient_map f hIJ = J.quotient_map f_1
(@eq.rec (polynomial R →+* polynomial R) f
(λ (f : polynomial R →+* polynomial R), I ≤ ideal.comap f J)
hIJ f_1 e_3))
rfl f_1 e_3)
I J f f_1 e_3 hIJ,
have := @H_congr_lemma I (comp_ideal (p.comp q) I)
((ring_hom.id (polynomial R)).comp ((compq q).comp (compq p)))
(compq (p.comp q))
sorry
h1
h2,
exact this,
end
Mario Carneiro (Dec 01 2020 at 17:10):
The theorem statement is the state immediately before congr'
. AFAICT it typechecks, so rw is not to blame
Mario Carneiro (Dec 01 2020 at 17:12):
The H_congr_lemma
is the proof generated by congr'
. It also typechecks, but applying the proof (which is the final have
and exact this
) fails. I notice that the type of the have
is not literally the same as the goal, it produces something other than h2
on the rhs
Simon Andreys (Dec 01 2020 at 17:24):
Nice ! I should learn how to get these generated proofs. I did not mean to say that rw was to blame, I meant that it cannot be applied because of the second argument, and this is why I was cornered into using congr' in the first place.
Simon Andreys (Dec 01 2020 at 17:56):
I've written a lemma to replace the sorry, in your code, to be sure it was not interfering. The second have
produces
(comp_ideal (p.comp q) I).quotient_map ((ring_hom.id (polynomial R)).comp ((compq q).comp (compq p))) h1 =
(comp_ideal (p.comp q) I).quotient_map (compq (p.comp q)) _
where _ is of type
(λ (f : polynomial R →+* polynomial R), I ≤ ideal.comap f (comp_ideal (p.comp q) I)) (compq (p.comp q))
Implementing the substitution (i.e. replacing f by (compq (p.comp q) ) in the expression) gives the type of h2. This type is equal to the type of h2, but not definitionally (edit : no, they are defeq) ! This problem, again. Does this mean there is some heq
issue in congr'
?
Mario Carneiro (Dec 01 2020 at 17:56):
are you sure it is not defeq? I tried the same thing and rfl
proves they are equal
Simon Andreys (Dec 01 2020 at 17:57):
Okay, they are defeq. Why is this not h2
then ?
Mario Carneiro (Dec 01 2020 at 17:58):
it is, I'm pretty sure
Mario Carneiro (Dec 01 2020 at 17:58):
but I also have evidence that lean is unfolding lots of things and I'm not sure why yet
Mario Carneiro (Dec 01 2020 at 17:58):
for example, the error goes away if you make ring_hom.id
an axiom
Mario Carneiro (Dec 01 2020 at 18:26):
More minimized:
import data.polynomial.eval
example {R : Type} [comm_ring R] (p q : polynomial R)
(P : (polynomial R → polynomial R) → Prop)
(h1 : P p.comp) (h2 : P q.comp) (e : p.comp = q.comp) :
(eq.rec h1 e : P q.comp) = h2 :=
by {change h2 = h2, exact rfl}
Mario Carneiro (Dec 01 2020 at 18:27):
the weird thing is that the change
works but the exact
doesn't, meaning that the elaborator and kernel disagree about the defeq
Simon Andreys (Dec 01 2020 at 18:48):
So it is indeed a problem of defeq on the type of h2 ? Very strange indeed.
Reid Barton (Dec 01 2020 at 18:49):
is anything irreducible
today?
Mario Carneiro (Dec 01 2020 at 18:49):
polynomial.comp
appears to be today's culprit
Mario Carneiro (Dec 01 2020 at 18:50):
it still doesn't make any sense to me that this would be unfolded though
Reid Barton (Dec 01 2020 at 18:50):
This looks similar to the other weirdness then
Mario Carneiro (Dec 01 2020 at 18:51):
amusingly, lean is totally fine with the proof proof_irrel _ _
Reid Barton (Dec 01 2020 at 18:51):
in that, putting everything else aside, :this: both sides of the equality are propositions
Mario Carneiro (Dec 01 2020 at 18:53):
actually eval₂
looks like a better candidate for irreducibility
Mario Carneiro (Dec 01 2020 at 18:53):
also finsupp.sum
Reid Barton (Dec 01 2020 at 18:53):
Reid Barton (Dec 01 2020 at 18:54):
or do you mean better than tensor_algebra
or whatever it was
Mario Carneiro (Dec 01 2020 at 18:54):
oh curious
Reid Barton (Dec 01 2020 at 18:56):
(For @Simon Andreys and others, I'm referring to https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/algebra.2Esemiring_to_ring.20breaks.20semimodule.20typeclass.20lookup/near/218215493)
Mario Carneiro (Dec 01 2020 at 18:58):
Uh oh:
import data.polynomial.eval
example {R : Type} [comm_ring R] (p q r : polynomial R)
(c : R →+* polynomial R)
(P : (polynomial R) → Prop)
(h1 : P (p.eval₂ c q)) (h2 : P (p.eval₂ c r))
(e : (p.eval₂ c q) = (p.eval₂ c r)) :
h2 = eq.rec h1 e := rfl -- timeout
irreducibility may not be good enough
Mario Carneiro (Dec 01 2020 at 19:06):
Aha, it's not eval2
that's the problem, it's fine if you use eval2
over another semiring. It's the polynomial R
semiring instance
Mario Carneiro (Dec 01 2020 at 19:09):
or at least, it's the combination of the two
Mario Carneiro (Dec 01 2020 at 19:16):
import data.polynomial.basic
@[irreducible] def polynomial.eval₂' {R S} [semiring R] [semiring S]
(f : R → S) (x : S) (p : polynomial R) : S :=
p.sum (λ _ a, f a * x)
example {R S : Type} [semiring R] [semiring S]
(f : R → polynomial S) (x : polynomial S) (p q : polynomial R)
(P : polynomial S → Prop)
(h1 : P (p.eval₂' f x)) (h2 : P (q.eval₂' f x))
(e : (p.eval₂' f x) = (q.eval₂' f x)) :
h2 = eq.rec h1 e := rfl
Replacing the definition of eval₂'
with sorry
makes it work, so clearly lean is reducing the irreducible
Simon Andreys (Dec 01 2020 at 22:13):
The issue is quite out of my scope, but what I gather is that the elaborator does reduce some expression while the compilator doesn't (or the other way around ?), and this problem was already raised before and is linked with the irreducible tag. It's reassuring in some way, since I kinda understand what may cause it (some Prop in the parameters of a function is wrongly typed by some tactic), and how to work around (unfold and dsimp, and use low level lemmas, as unpleasant it may be). Better even, the root problem may be solved at some point and the "high" level proof be efficient again.
Simon Andreys (Dec 03 2020 at 22:52):
I was overly optimistic when saying that I knew how to work around the problem : it resurfaced at the next lemma. I will use a less composite approach to construct the isomorphism I want.
Last updated: Dec 20 2023 at 11:08 UTC