Zulip Chat Archive
Stream: lean4
Topic: get_elem_tactic timeout from similar hyps
James Gallicchio (Feb 11 2025 at 23:37):
I have an unusual proof where I accumulate facts about getElem
on a few vectors. But then, when I try to state another fact with more getElem
s, I end up timing out get_elem_tactic
because trivial
tries to unify hypotheses that will fail to unify.
image.png
I will try to make a minimal reproduction tomorrow.
James Gallicchio (Feb 11 2025 at 23:40):
The statement that triggers this timeout is
-- then, b/c c7 and c11 are adjacent, either c7_3 = c3_3 or c11_2 = c3_2
have : (tc.kclique.get 7)[3] = (tc.kclique.get 3)[3] ∨
(tc.kclique.get 11)[2] = (tc.kclique.get 3)[2] := sorry
where the context is
n s : ℕ
tc : TwoCubes (n + 3) s
c3_3 : (tc.kclique.get 3)[3] ≠ 0
c3_2 : (tc.kclique.get 3)[2] ≠ 0
c7_0 : (tc.kclique.get 7)[0] = 0
c7_1 : (tc.kclique.get 7)[1] = 1
c7_2 : (tc.kclique.get 7)[2] = (tc.kclique.get 3)[2]
c11_0 : (tc.kclique.get 11)[0] = 0
c11_1 : (tc.kclique.get 11)[1] = 1
c11_3 : (tc.kclique.get 11)[3] = (tc.kclique.get 3)[3]
⊢ ...
James Gallicchio (Feb 11 2025 at 23:42):
tc.kclique.get : BitVec (n+5) -> Vector (Fin _) (n+5)
, so there are interesting casts happening for all of those numerals, which I suspect may be contributing to how slow it is.
James Gallicchio (Feb 11 2025 at 23:50):
actually, found a quick repro! this takes 3 seconds to elaborate on my machine :sweat_smile:
set_option trace.profiler true in
example (f : BitVec (n+5) -> Vector (Fin (s+2)) (n+5)) : False :=
have : (f 7)[0] = 0 := sorry
have : (f 7)[1] ≠ 0 := sorry
have : (f 7)[2] = (f 3)[2] := sorry
have : (f 11)[0] = 0 := sorry
have : (f 11)[1] ≠ 0 := sorry
have : (f 11)[2] = (f 3)[2] := sorry
have : (f 7)[3] = (f 3)[3] ∨
(f 11)[2] = (f 3)[2] := sorry
sorry
Jovan Gerbscheid (Feb 12 2025 at 14:58):
The reason is that Lean tries to figure out what the numbers 7
and 11
are modulo 2 ^ (n + 5)
, by unfolding them. To stop lean from doing this, you can write something like seal BitVec.ofNat
before the definition.
Jovan Gerbscheid (Feb 12 2025 at 15:26):
This unification takes exponential time as you increase the 5
:
set_option trace.profiler true in
example : (1 : BitVec (n + 5)) = (0 : BitVec (n + 5)) := rfl
James Gallicchio (Feb 12 2025 at 16:56):
seal BitVec.ofNat
improves the elaboration time by about 50%, but it is still quite slow (2s to compile 10 lines on a new machine). How can I further debug this?
James Gallicchio (Feb 12 2025 at 16:57):
(note that adding explicit proof terms to each getElem completely sidesteps the slow elaboration, since it is triggered by getElem's proof obligation machinery)
Jovan Gerbscheid (Feb 12 2025 at 17:00):
The example you posted is only 0.2 seconds on the lean web when using seal BitVec.ofNat
James Gallicchio (Feb 12 2025 at 18:28):
oh dear, the difference seems to be whether mathlib is imported
James Gallicchio (Feb 12 2025 at 18:37):
not sealed | sealed | |
---|---|---|
mathlib | 2.46 | 0.68 |
core | 1.89 | 0.10 |
James Gallicchio (Feb 12 2025 at 18:38):
so I guess the .5 seconds is just the overhead of mathlib bigness, and the other 1.8 seconds is avoided by sealing
James Gallicchio (Feb 12 2025 at 18:45):
wait. Importing all of mathlib is significantly faster than a minimized import set. huh? this takes 2.4 seconds on lean web:
import Mathlib.Algebra.Order.Group.Defs
import Mathlib.Data.Fintype.Card
seal BitVec.ofNat
set_option trace.profiler true in
example (f : BitVec (n+5) -> Vector (Fin (s+2)) (n+5)) : False :=
have : (f 7)[0] = 0 := sorry
have : (f 7)[1] ≠ 0 := sorry
have : (f 7)[2] = (f 3)[2] := sorry
have : (f 11)[0] = 0 := sorry
have : (f 11)[1] ≠ 0 := sorry
have : (f 11)[2] = (f 3)[2] := sorry
have : (f 7)[3] = (f 3)[3] ∨
(f 11)[2] = (f 3)[2] := sorry
sorry
probably could be minimized more but I have to run now
Damiano Testa (Feb 12 2025 at 18:57):
Synthesizing instances could benefit from shortcuts available in all of mathlib that are not available in a reduced environment, so maybe this is not too surprising. I would say that increasing imports is not necessarily a guarantee of slow-downs/speed-ups.
Damiano Testa (Feb 12 2025 at 18:59):
After all, elaboration is dependent on the order of the imports.
James Gallicchio (Feb 13 2025 at 17:20):
@Parth Shastri pointed out that lt_add_iff_pos_left
can apply whenever 0 is on the LHS (regardless of the RHS), which significantly slows down the get_elem_tactic
's simp search:
example : 0 < n + 1 := by
repeat rw [Nat.lt_add_left_iff_pos]
removing simp from this lemma, sealing BitVec.ofNat, and importing more of Mathlib all help speed up the example significantly. thanks y'all!
Last updated: May 02 2025 at 03:31 UTC