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):

https://github.com/leanprover-community/mathlib/blob/b7649bcd2d4db889ae2651637e2c8969c89f4c1f/src/data/polynomial/eval.lean#L479-L485

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