Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tactic/tidy): limit the amount of time spent on refl #3380

Closed
wants to merge 3 commits into from

Conversation

semorrison
Copy link
Collaborator

I have mixed feelings about refl in tidy.

On the one hand, including it near the top of default_tactics list (as it is now) saves about 60s in compiling mathlib.

On the other hand, it potentially makes tidy very slow, as it is willing to tackle "heavy rfl" problems, even when other tactics would be more advisable.

As a compromise, in this PR we run refl inside a try_for wrapper.
The time limit was chosen as a smallest value for which we get the full compilation time benefits
(in fact a slight overall improvement).

This PR also

  1. replaces the unique proof by tidy that fails if refl is removed entirely
  2. satisfies the linter on tactic/tidy.lean

@semorrison semorrison added the awaiting-review The author would like community review of the PR label Jul 13, 2020
@@ -67,7 +67,8 @@ def CommRing_yoneda : TopCommRing.{u} ⥤ (Top.{u}ᵒᵖ ⥤ CommRing.{u}) :=
{ obj := λ X, continuous_functions X R,
map := λ X Y f, continuous_functions.pullback f R },
map := λ R S φ,
{ app := λ X, continuous_functions.map X φ } }
{ app := λ X, continuous_functions.map X φ, },
map_comp' := by { intros X Y Z f g, ext V h, dsimp, refl, }, }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proof still works by tidy and could be omitted, but the whole declaration is up against the -T100000 limit, and now apparently slightly over, so I've put the map_comp proof in by hand.

It would be better to improve the simp lemmas so this refl isn't even needed, but not today.

@gebner
Copy link
Member

gebner commented Jul 13, 2020

I am very uneasy about this change.

In my experience it only needs one small and unrelated change to push the 49 to 51, and then some definitions in the category theory library will fail in a completely unclear way. Even worse, tidy is used extensively in auto params so the failure is even more mysterious.

What is the debugging story here? Is there a tracing option that gives some information about how tidy fails and what to do to make it work?

Ideally we'd also have an option to specify the refl timeout.

@semorrison
Copy link
Collaborator Author

The one (very weak) counter argument, is that you can actually remove refl entirely from the list of tidy tactics, and everything still compiles (just a bit slower).

I agree this is not a satisfactory answer to your objection!

@semorrison
Copy link
Collaborator Author

Nevertheless I think a reasonable solution may be to just remove refl. It will cost us a slight slow down, but apparently make tidy more useful.

@semorrison
Copy link
Collaborator Author

semorrison commented Jul 13, 2020

Let me #xy the problem:

import algebra.category.CommRing.basic
import data.polynomial

noncomputable theory

attribute [simp] polynomial.coeff_map

def CommRing.polynomial : CommRing ⥤ CommRing :=
{ obj := λ R, CommRing.of (polynomial R),
  map := λ R S f, ring_hom.of (polynomial.map f),
  map_comp' := λ R S T f g, by { ext, dsimp, simp, }, }

def CommRing.polynomial' : CommRing ⥤ CommRing :=
{ obj := λ R, CommRing.of (polynomial R),
  map := λ R S f, ring_hom.of (polynomial.map f),
  map_comp' := λ R S T f g, by { refl, }, } -- `refl` fails, but takes 12 seconds to do so!

This sort of slow failure of refl makes tidy completely unusable here. If we leave out refl from the list of tidy tactics it essentially reproduces the first proof, in a reasonable time.

@robertylewis
Copy link
Member

I know nothing about the category theory library, but when I hear "refl takes 12 seconds to fail," I have to assume there's an @[irreducible] annotation missing somewhere.

@semorrison
Copy link
Collaborator Author

In fact, this proof with a slow refl is just about polynomials. Let me extract it better...

@semorrison
Copy link
Collaborator Author

Here's the further minimised slow refl failure, no category theory involved:

import data.polynomial

noncomputable theory

example {R S T : Type} [comm_ring R] [comm_ring S] [comm_ring T]
  (f : R →+* S)
  (g : S →+* T) :
  ring_hom.of (polynomial.map (g.comp f)) =
    (ring_hom.of (polynomial.map g)).comp (ring_hom.of (polynomial.map f)) :=
begin
  refl, -- `refl` fails, but takes 6 seconds to do so!
end

@gebner
Copy link
Member

gebner commented Jul 13, 2020

Any one of the following works:

attribute [irreducible] polynomial.eval₂  --  1ms
attribute [irreducible] finsupp.sum       --  1ms
attribute [irreducible] finset.sum        --  1ms
attribute [irreducible] multiset.map      -- 25ms

@semorrison
Copy link
Collaborator Author

I experimented with attribute [irreducible] polynomial.eval₂, and can get things to work, but I there are six different files where I need to add local attribute [semireducible] polynomial.eval₂ to get existing proofs to work.

Does it seem reasonable to do this? That is, make something irreducible, adding local attributes to make existing proofs work, and defer the real work of fixing those proofs to use a proper API for later? Or is this adding more technical debt, and it would be better to only mark things as [irreducible] if we fix all subsequent proofs at the same time?

@semorrison
Copy link
Collaborator Author

(I guess that this was going to be the cheapest change to make, out of those four.)

@gebner
Copy link
Member

gebner commented Jul 13, 2020

Does it seem reasonable to do this? That is, make something irreducible, adding local attributes to make existing proofs work, and defer the real work of fixing those proofs to use a proper API for later? Or is this adding more technical debt, and it would be better to only mark things as [irreducible] if we fix all subsequent proofs at the same time?

If possible, I think we should try to add enough API that we don't need local attribute [semireducible]. In cast that fails, I'd try to use sections to only change the reducibility for a single lemma. Do you have a branch with the changes somewhere?

@semorrison
Copy link
Collaborator Author

eval2_irreducible

@gebner
Copy link
Member

gebner commented Jul 13, 2020

eval2_irreducible

Thanks! That doesn't look so bad. I think some parts can be easily replaced by unfold eval₂ (or by rw eval₂_def which would be a bit more future-proof).

I heard on Zulip that somebody wanted to do a big refactor of the polynomials. Maybe it would be best to do this as part of the refactor.

@semorrison
Copy link
Collaborator Author

That was me... :-) But it keeps getting postponed!

I will close this for now.

@semorrison semorrison closed this Jul 13, 2020
bors bot pushed a commit that referenced this pull request Jul 28, 2020
A while back @gebner identified that [an unfortunate timeout could be avoided](#3380 (comment)) by making `polynomial.eval2` irreducible.

This PR does that.

It's not perfect: on a few occasions I have to temporarily set it back to semireducible, because it looks like the proofs really do some heavy refling.

I'd like to make more things irreducible in the polynomial API, but not yet.



Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
Co-authored-by: jalex-stark <alexmaplegm@gmail.com>
Co-authored-by: kckennylau <kc_kennylau@yahoo.com.hk>
@semorrison semorrison removed the awaiting-review The author would like community review of the PR label Sep 11, 2020
@semorrison semorrison deleted the tidy_try_for branch October 19, 2021 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants