Zulip Chat Archive
Stream: mathlib4
Topic: compiling behaviour within one file
Ralf Stephan (Jul 19 2024 at 11:20):
Thanks to incremental compile and the progress display bar, and simple manipulation of the code, one can identify quickly which lines in a file take most of the compile time. In one case I find this line
https://github.com/leanprover-community/mathlib4/blob/476f5f1808912a5922e3e3e756a0e44f55b9f1da/Mathlib/RingTheory/PowerSeries/Basic.lean#L666
convert MvPowerSeries.coeff_prod _ _ _
stopping the progress bar for 10 seconds. Is this believable? I didn't think convert
would be a complex tactic.
Ralf Stephan (Jul 19 2024 at 11:22):
Is there (another) tool assigning percentage of compile time in a file to single lines?
Michael Rothgang (Jul 19 2024 at 11:34):
Lean has two built-in profilers: this page describes the "old" one, which gives line-based information. trace.profiler
is the new one (which creates collapsible traces; I'm not sure if/where documentation for that one is).
Michael Rothgang (Jul 19 2024 at 11:34):
Wow, 10 seconds for a convert is really slow: that means something in the file needs to be fixed.
Kevin Buzzard (Jul 19 2024 at 13:53):
10 seconds for a convert is absolutely normal, it means that, somewhere in the goal and somewhere in what you are trying to convert it to, there were two terms which (a) looked different (b) turned out to be equal by rfl
and (c) to prove that they were equal by rfl
involved unfolding and unfolding and unfolding until each term was gigantic. The take home is that convert
should not be being used here and one wants instead to use convert ... using ...
or other tactics which won't embark upon the massive unfold.
Ralf Stephan (Jul 19 2024 at 13:58):
Thanks. I'll try that. :working_on_it:
Kevin Buzzard (Jul 19 2024 at 14:03):
In fact, if you write set_option trace.profiler true in
before the theorem's docstring and then unfold the trace by clicking on or near the triangles, it turns out that the problem is
[] [6.725668] ❌ (Multiset.map (fun x ↦ ∏ x_1 ∈ s, (MvPowerSeries.coeff R (Finsupp.single () (x x_1))) (f x_1))
(s.finsuppAntidiag
d).val).sum =?= (Multiset.map (fun l ↦ ∏ i ∈ s, (MvPowerSeries.coeff R (l i)) (f i))
(s.finsuppAntidiag (Finsupp.single () d)).val).sum ▶
Lean takes 6.7 seconds on my computer to fail to prove that two things are equal by rfl
.
Changing line 666 to erw [MvPowerSeries.coeff_prod]
makes the proof instant, because Lean does not get induced into doing a "heavy rfl
", which is the phenomenon you're running into (a rfl
which succeeds or fails but takes an age to do so because of an explosion in the size of terms). I'm on a train so don't fancy making a PR but please feel free to make one yourself!
Kevin Buzzard (Jul 19 2024 at 14:09):
The reason that just a straight rw
fails is that if you try
rw [MvPowerSeries.coeff_prod f (single () d) s]
then you get the error
tactic 'rewrite' failed, did not find instance of the pattern in the target expression
(MvPowerSeries.coeff R (single () d)) (∏ j ∈ s, f j)
...
⊢ (MvPowerSeries.coeff R (single () d)) (∏ j ∈ s, f j) = ...
which looks counterintuitive, but if you then start looking in the innards of what's going on, you find that the MvPowerSeries.coeff
in the lemma you're trying to use is (when written out in full)
@DFunLike.coe (MvPowerSeries Unit R →ₗ[R] R) (MvPowerSeries Unit R) (fun x ↦ R) LinearMap.instFunLike
(MvPowerSeries.coeff R (single () d)) : MvPowerSeries Unit R → R
whereas the MvPowerSeries.coeff
in the goal is
@DFunLike.coe (R⟦X⟧ →ₗ[R] R) R⟦X⟧ (fun x ↦ R) LinearMap.instFunLike (MvPowerSeries.coeff R (single () d)) : R⟦X⟧ → R
so there is some slight difference here, caused by the fact that
def PowerSeries (R : Type*) :=
MvPowerSeries Unit R
is not an abbrev
. Perhaps this is the root cause of the issue. erw
is a tactic which tries harder to unify, so sees through this non-reducible definition and works successfully.
Kevin Buzzard (Jul 19 2024 at 14:20):
If you change line 54 of the file from a def
to
abbrev PowerSeries (R : Type*) :=
MvPowerSeries Unit R
then two proofs break because they have rfl
s in them which aren't needed any more because the goal is already closed (so they can just be deleted), and you can change the bad convert
line to just a plain old rw
because now rw
can see through the problem which was making it break before when the definition of PowerSeries
was more irreducible. I would regard this as a good change. It would be interesting to see what else breaks in mathlib after this change -- you can do this by making the change I suggest on a branch, fixing the rfl
errors in that same file, and then pushing the branch to github and opening a WIP PR and seeing what CI thinks of it. Once you've got mathlib compiling again (a green tick in CI), you can type !bench
in your PR and you'll get a profile of how much faster or slower mathlib is compiling. Sorry I am not able to do this myself, I have ropey internet for the next hour or so.
Matthew Ballard (Jul 19 2024 at 14:20):
I would think we would want MvPowerSeries
API to apply directly to the single variable case
Kevin Buzzard (Jul 19 2024 at 14:21):
That's your way of saying "I agree that abbrev
is worth pursuing" right?
Matthew Ballard (Jul 19 2024 at 14:23):
But it depends on if we spend tons of time searching for things applying to \sigma := Unit
Kevin Buzzard (Jul 19 2024 at 14:24):
So the benchmarking is going to be interesting because you're saying that right now we don't know which way it will go.
Matthew Ballard (Jul 19 2024 at 14:24):
Then it should be a structure probably
Matthew Ballard (Jul 19 2024 at 14:25):
Yeah, depends on the performance impact on the field
Ralf Stephan (Jul 19 2024 at 14:44):
The first variant with erw
is #14910. Since, with abbrev
, the fixes in RingTheory/LaurentSeries.lean
will require me some time to get a grip on the subject, you may either help at #14913, or merge #14910. I may be half a math, but I'm definitely no polymath.
Matthew Ballard (Jul 19 2024 at 15:40):
This exposes a rather nasty diamond
import Mathlib
open Polynomial
variable {F : Type*} [Field F] (f : F[X])
example : (f : RatFunc F) = (f : LaurentSeries F) := by with_unfolding_all rfl -- fails
Matthew Ballard (Jul 19 2024 at 15:44):
Fails on current master
Riccardo Brasca (Jul 19 2024 at 16:02):
I think the problem comes from docs#RatFunc.coeAlgHom
Riccardo Brasca (Jul 19 2024 at 16:03):
Let me see if I can do something
Riccardo Brasca (Jul 19 2024 at 16:14):
Well, thinking more about it I don't think we can make it defeq: on the RHS everything is clear, the coercion is defined coefficientwise. But on the LHS something nontrivial is happening, a polynomial is viewed as a rational function (and this is trivial), but then to prove that a rational function "is" a power series one has to prove something.
Riccardo Brasca (Jul 19 2024 at 16:15):
Maybe docs#RatFunc.coe_coe should be simp
?
Riccardo Brasca (Jul 19 2024 at 16:18):
Unless we decide that the coercion from polynomials to power series is "going through RatFunc
"
Riccardo Brasca (Jul 19 2024 at 16:31):
Can we define a morphism out of the fraction ring that has good defeq properties wrt the base ring? If we can then it should be fixable. But I have to go now
Matthew Ballard (Jul 19 2024 at 16:49):
TIL: irreducible_def
involves an opaque
Riccardo Brasca (Jul 19 2024 at 17:06):
Currently I don't think they're defeq in any sense
Damiano Testa (Jul 19 2024 at 17:07):
Certainly, most weakenings of Field
to something less restrictive will not just prevent DefEq
but even PropEq
.
Damiano Testa (Jul 19 2024 at 17:08):
RatFunc F
does not contain F
if F
has non-zero nilpotent elements, right?
Matthew Ballard (Jul 19 2024 at 17:10):
I am just trying to get it to unfold until really break
Matthew Ballard (Jul 19 2024 at 17:20):
No defeq + coercions makes this really fiddly
Riccardo Brasca (Jul 19 2024 at 17:21):
(deleted)
Riccardo Brasca (Jul 19 2024 at 17:21):
/-- The coercion `RatFunc F → LaurentSeries F` as bundled alg hom. -/
def coeAlgHom (F : Type u) [Field F] : RatFunc F →ₐ[F[X]] LaurentSeries F :=
liftAlgHom (Algebra.ofId _ _) <|
nonZeroDivisors_le_comap_nonZeroDivisors_of_injective _ <|
Polynomial.algebraMap_hahnSeries_injective _
example (F : Type*) [Field F] (p : F[X]) : coeAlgHom F p = Algebra.ofId F[X] (LaurentSeries F) p := by
rfl --fails
This seems already a problem
Matthew Ballard (Jul 19 2024 at 17:23):
Some of that is docs#RatFunc.liftOn and docs#RatFunc.mk both use irreducible_def
's
Kyle Miller (Jul 19 2024 at 17:25):
When I debug convert
lines, I usually do convert ... using 0
and increment 0
a step at a time until something bad happens.
Then there are also configuration options you can use with convert (config := { ... }) ... using ...
; here's the documentation
For example, you can do (config := { closePost := false })
to make it not try to apply rfl
when closing sub-goals once nothing else applies. You can also do with_reducible convert ...
to make it apply rfl
only at reducible transparency. It already tries rfl
before descending into a term at reducible transparency (controlled by closePre
and preTransparency
).
Matthew Ballard (Jul 19 2024 at 17:37):
Something benchmark-able is queued up for bot
Matthew Ballard (Jul 19 2024 at 17:39):
I don't understand how the abbrev
alters the instance ordering.
Matthew Ballard (Jul 19 2024 at 18:35):
Benchmarking seems happy
Riccardo Brasca (Jul 19 2024 at 20:31):
Which branch are you talking about?
Ralf Stephan (Jul 19 2024 at 20:32):
Ralf Stephan (Jul 23 2024 at 07:33):
Matthew Ballard said:
This exposes a rather nasty diamond
By chance, I found something about it in an interview with @Yakov Pechersky :
With rational functions, I find it particularly interesting, because we have a diamond.
From polynomials, you can go to rational functions, and then to Laurent series.
Or you can go from polynomials to power series, and then to Laurent series.
https://leanprover-community.github.io/blog/posts/backstage-with-pechersky/
Last updated: May 02 2025 at 03:31 UTC