Zulip Chat Archive
Stream: general
Topic: An example of why formalization is useful
Riccardo Brasca (Mar 31 2022 at 14:53):
I really like what is going on with #12777. @Sebastian Monnet proved that if E
,F
and K
are fields such that finite_dimensional F E
, then fintype (E →ₐ[F] K)
. We already have docs#field.alg_hom.fintype, that is exactly the same statement with the additional assumption is_separable F E
.
The interesting part of the PR is that, with the new theorem, the linter will automatically flag all the theorem that can be generalized (for free!), removing the separability assumption. I think in normal math this is very difficult to achieve, if I generalize a 50 years old paper that assumes p ≠ 2
to all primes, there is no way I can manually check and maybe generalize all the papers that use the old one.
Riccardo Brasca (Mar 31 2022 at 14:54):
OK, of course right after I write this, Lean decided that something is wrong and didn't accept the new result, but still, the story is in principle interesting...
Damiano Testa (Mar 31 2022 at 15:01):
I completely agree with you! Automated reduction of assumptions is great!
In a similar vein, I was very impressed with I changed the definition of ideal to use comm_semiring
instead of comm_ring
and then noticing that essentially the only proofs that failed were the ones that explicitly involved using -
!
Sebastien Gouezel (Mar 31 2022 at 15:08):
This happened to me a lot with the Bochner integral refactor, in which I removed a second_countable_topology
assumption. Then I had to go through a bunch of linting steps, where the linter complained that I had useless assumptions in a bunch of files that do not directly depend on integration theory (notably many results in complex analysis).
Scott Morrison (Mar 31 2022 at 21:52):
Whatever happened to the optional linter (I think written by @Alex J. Best?) that tried to determine if a type class assumption was too strong (not just unnecessary)? It was far too slow to put into the automatic linting step, but it would be lovely to have it run once a day and put the output somewhere easily accessible.
Scott Morrison (Mar 31 2022 at 22:01):
ah, I found some messages with Alex, and what you're meant to be able to do is (in mathlib):
leanpkg add https://github.com/alexjbest/lean-generalisation
then add import generalisation_linter
in a file, and then run #lint
as normally.
Right now this fails with cannot find revision lean-3.42.0 in repository _target/deps/lean-generalisation
at the leanpkg add
step.
Scott Morrison (Mar 31 2022 at 22:01):
Alex's talk about the generalisation linter is at https://www.youtube.com/watch?v=pudd4F749tE.
Eric Rodriguez (Mar 31 2022 at 23:48):
i tried bumping at https://github.com/ericrbg/lean-generalisation
, and trying to run it overnight on my laptop on mathlib. will report back what it finds!
Scott Morrison (Apr 01 2022 at 01:38):
I ran it just up to import algebra.group.basic
. There are essentially four classes of suggestions:
- broken ones that include
no_meet_fake_name
in the output - suggestions that might well be okay, but I'm not interested in:
#check @comp_mul_right /- _inst_1: semigroup ↝ has_mul is_associative -/
- some that are "obviously silly": `#check @group.to_monoid /- _inst_1: group ↝ monoid -/
- and some good ones!
The first three classes are pretty easy to filter out. To ignore a superset of the second class, we can just filter out everything that suggests replacing one typeclass with multiple typeclasses. (They may well be valid, but I probably less valuable.) The third class would require a filter that declines suggestions that weaken a typeclass if the declaration is in the namespace.
The remaining suggestions up to algebra.group.basic
I've implemented as #13092; we'll see what CI says.
Scott Morrison (Apr 01 2022 at 02:54):
Okay, this is kind of fun. :-) Many of the suggestions up to (an arbitrarily chosen target) algebra.ring.pi
are in #13094, #13095, #13096, #13097, #13098, #13099.
Eric Rodriguez (Apr 01 2022 at 07:40):
meanwhile, the version running on mk_all
still hasn't finished... mypoor macbook :)
Eric Rodriguez (Apr 01 2022 at 07:47):
worryingly, it also throws some errors of the form:
WARNING types not equal
<def algebraic_geometry.Scheme.open_cover.finite_subcover : Π {X : algebraic_geometry.Scheme},
X.open_cover →
Π [H : compact_space ↥(X.to_LocallyRingedSpace.to_SheafedSpace.to_PresheafedSpace.carrier)], X.open_cover := λ
{X : algebraic_geometry.Scheme} (𝒰 : X.open_cover)
[H : compact_space ↥(X.to_LocallyRingedSpace.to_SheafedSpace.to_PresheafedSpace.carrier)],
let t : finset ↥(X.to_LocallyRingedSpace.to_SheafedSpace.to_PresheafedSpace.carrier) := _.some
in {J := ↥t,
obj := λ (x : ↥t), 𝒰.obj (𝒰.f x.val),
map := λ (x : ↥t), 𝒰.map (𝒰.f x.val),
f := λ (x : ↥(X.to_LocallyRingedSpace.to_SheafedSpace.to_PresheafedSpace.carrier)), Exists.some _,
covers := _,
is_open := _}>
WARNING types not equal
<def algebraic_geometry.PresheafedSpace.is_open_immersion.to_SheafedSpace_hom : Π {C : Type u}
[_inst_1 : category_theory.category C] [_inst_2 : category_theory.limits.has_products C]
{X : algebraic_geometry.PresheafedSpace C} (Y : algebraic_geometry.SheafedSpace C) (f : X ⟶ Y.to_PresheafedSpace)
[H : algebraic_geometry.PresheafedSpace.is_open_immersion f],
algebraic_geometry.PresheafedSpace.is_open_immersion.to_SheafedSpace Y f ⟶ Y := λ {C : Type u}
[_inst_1 : category_theory.category C] [_inst_2 : category_theory.limits.has_products C]
{X : algebraic_geometry.PresheafedSpace C} (Y : algebraic_geometry.SheafedSpace C) (f : X ⟶ Y.to_PresheafedSpace)
[H : algebraic_geometry.PresheafedSpace.is_open_immersion f], f>
not sure how this happens
Yaël Dillies (Apr 01 2022 at 09:25):
Just noting that we have branch#generalising_typeclasses
Oliver Nash (Apr 01 2022 at 09:26):
Thanks @Yaël Dillies Is anyone brave enough to merge master into a branch 2752 commits behind?
Yaël Dillies (Apr 01 2022 at 09:27):
I already did but then let the branch rot again :upside_down:
Scott Morrison (Apr 01 2022 at 10:57):
Ah, nice, after following the generalisation linters hints for a while, I realised it was going to be possible to generalise module
to work over a non_assoc_semiring
. This is now in #13111.
Scott Morrison (Apr 01 2022 at 10:57):
I wonder if we can bring lie_module
back into the fold. :-)
Eric Wieser (Apr 01 2022 at 11:21):
I think I decided not to make that generalization at the time because it didn't actually have any obvious instances
Eric Wieser (Apr 01 2022 at 11:22):
In particular, a non associative ring can't be a module over itself, because mul_smul
is just associativity
Eric Wieser (Apr 01 2022 at 11:22):
In fact, I think mul_smul
implies the action behaves as if the ring were associative
Eric Rodriguez (Apr 01 2022 at 11:23):
are you saying this is the same as docs#monoid.exponent in that any module ends up automatically implying associativity?
Yaël Dillies (Apr 01 2022 at 11:25):
I will update generalising_typeclasses
once you are done with all this, Scott.
Eric Wieser (Apr 01 2022 at 11:34):
It's not quite as strong as implying associativity
Eric Wieser (Apr 01 2022 at 11:34):
Just that the action factors via an embedding into something associative
Eric Wieser (Apr 01 2022 at 11:35):
((a * b) * c) • x = (a * (b * c)) • x
is implied by the module axioms
Eric Rodriguez (Apr 01 2022 at 11:41):
not sure how quotients work in non-assoc rings, but can you make a module of R into its "associtivisation"?
Reid Barton (Apr 01 2022 at 11:59):
This example or a related one was discussed here some time ago
Reid Barton (Apr 01 2022 at 12:00):
Scott Morrison (Apr 01 2022 at 12:21):
Yeah, okay, I think I won't bother with that PR. :-)
Scott Morrison (Apr 01 2022 at 12:22):
I guess it is actually non_unital_ring
that we may want modules for, for C^*-algebra purposes...?
Eric Rodriguez (Apr 01 2022 at 12:29):
i still don't know why we didn't call those rng
s... we're going to need 4k screens to fit Lean text soon
Yaël Dillies (Apr 01 2022 at 12:30):
random_number_generator
?
Eric Rodriguez (Apr 01 2022 at 12:33):
ring
without the i
dentity
Eric Rodriguez (Apr 01 2022 at 12:34):
if you mean it'd get confused with that, it seems to already be called docs#rand_g
Scott Morrison (Apr 01 2022 at 12:34):
and rig
for semiring
(ring without n
egative), and presumably rg
s for the silliest ones?
Yaël Dillies (Apr 01 2022 at 12:36):
A name without vowels is likely to be read as an abbreviation.
Eric Rodriguez (Apr 01 2022 at 12:39):
Moritz Doll (Apr 01 2022 at 12:51):
Is it possible to run the generalization linter alone? #lint
dies on many files on my machine.
Eric Rodriguez (Apr 01 2022 at 12:52):
just type generalization_linter
Eric Rodriguez (Apr 01 2022 at 12:52):
after #lint
Eric Rodriguez (Apr 01 2022 at 12:52):
but it's really expensive it's still running on my laptop since ~yday 10GMT
Moritz Doll (Apr 01 2022 at 12:55):
thanks, unfortunately it still times out..
Riccardo Brasca (Apr 01 2022 at 13:14):
Is it possible to run it from the command line?
Riccardo Brasca (Apr 01 2022 at 13:14):
And not in VS Code
Floris van Doorn (Apr 01 2022 at 13:41):
You need to type #lint only generalization_linter
if you don't want to do the default tests.
Eric Rodriguez (Apr 01 2022 at 13:42):
oh dear, my poor CPU cycles are probably re-running simp-nf...
Eric Rodriguez (Apr 02 2022 at 09:03):
still running, albeit single-threaded so hopefully it's nearly done... how long did it take to run the first time?
Scott Morrison (Apr 02 2022 at 09:10):
I'm not sure it's ever been run on the entire library! :-)
Eric Rodriguez (Apr 05 2022 at 09:49):
OK, I've tried now twice and it just outputs errors and never any suggestions :/ maybe this is a memory issue though, so I guess these results are going to have to wait.
https://gist.github.com/ericrbg/e78cd06e2930763a07fd2f22c14a67d0
Riccardo Brasca (Apr 05 2022 at 09:58):
If someone is ready to explain me how to do it I have some cpu time (and memory) to spare
Eric Rodriguez (Apr 05 2022 at 10:28):
- Take a
mathlib
clone with cache leanpkg add https://github.com/ericrbg/lean-generalisation
mk_all.sh
to get anall.lean
- Make a file that imports
all
andgeneralisation_linter
, and under all that put#lint only generalisation_linter
lean --make
that file into some output file
If this works as I think it should, piping from that file should give you the output. It's likely worth trying step 4 with logic.basic
instead of all
first to check things are working as they should
Riccardo Brasca (Apr 05 2022 at 10:38):
import all
import generalisation_linter
#lint only generalisation_linter
and lean --make src/test_linter.lean > res
gives
/- Checking 0 declarations (plus 0 automatically generated ones) in the current file with 1 linters -/
/- All linting checks passed! -/
:rolling_eyes:
Floris van Doorn (Apr 05 2022 at 10:39):
You'll want #lint_mathlib only generalisation_linter
or #lint_all only generalisation_linter
Eric Rodriguez (Apr 05 2022 at 10:39):
oopsies, yes, wrong lint command!
Riccardo Brasca (Apr 05 2022 at 10:40):
Ah yes, with logic.basic
it does something
Riccardo Brasca (Apr 05 2022 at 10:45):
For future reference: one has to redirect stderr to obtain a file with the result
Riccardo Brasca (Apr 05 2022 at 10:55):
It is of course still working, but the first output is
WARNING types not equal
<def category_theory.nat_trans.right_derived : Π {C : Type u} [_inst_1 : category_theory.category C] {D : Type u_1}
[_inst_2 : category_theory.category D] [_inst_3 : category_theory.abelian C]
[_inst_4 : category_theory.has_injective_resolutions C] [_inst_5 : category_theory.abelian D] {F G : C ⥤ D}
[_inst_6 : F.additive] [_inst_7 : G.additive], (F ⟶ G) → Π (n : ℕ), F.right_derived n ⟶ G.right_derived n := λ
{C : Type u} [_inst_1 : category_theory.category C] {D : Type u_1} [_inst_2 : category_theory.category D]
[_inst_3 : category_theory.abelian C] [_inst_4 : category_theory.has_injective_resolutions C]
[_inst_5 : category_theory.abelian D] {F G : C ⥤ D} [_inst_6 : F.additive] [_inst_7 : G.additive] (α : F ⟶ G)
(n : ℕ),
category_theory.whisker_left (category_theory.injective_resolutions C)
(category_theory.whisker_right (category_theory.nat_trans.map_homotopy_category α (complex_shape.up ℕ))
(homotopy_category.homology_functor D (complex_shape.up ℕ) n))>
WARNING types not equal
<def category_theory.exp_terminal_iso_self : Π {C : Type u} [_inst_1 : category_theory.category C] {X : C}
[_inst_2 : category_theory.limits.has_finite_products C] [_inst_4 : category_theory.exponentiable (⊤_ C)],
(category_theory.exp (⊤_ C)).obj X ≅ X := λ {C : Type u} [_inst_1 : category_theory.category C] {X : C}
[_inst_2 : category_theory.limits.has_finite_products C] [_inst_4 : category_theory.exponentiable (⊤_ C)],
category_theory.yoneda.ext ((category_theory.exp (⊤_ C)).obj X) X
(λ (Y : C) (f : Y ⟶ (category_theory.exp (⊤_ C)).obj X),
(category_theory.limits.prod.left_unitor Y).inv ≫ category_theory.cartesian_closed.uncurry f)
(λ (Y : C) (f : Y ⟶ X),
category_theory.cartesian_closed.curry ((category_theory.limits.prod.left_unitor Y).hom ≫ f))
category_theory.exp_terminal_iso_self._proof_9
category_theory.exp_terminal_iso_self._proof_10
category_theory.exp_terminal_iso_self._proof_11>
WARNING types not equal
<def category_theory.injective.exact.desc : Π {C : Type u} [_inst_1 : category_theory.category C]
[_inst_2 : category_theory.limits.has_zero_morphisms C] [_inst_3 : category_theory.limits.has_images Cᵒᵖ]
[_inst_4 : category_theory.limits.has_equalizers Cᵒᵖ] {J Q R S : C} [_inst_5 : category_theory.injective J]
(h : R ⟶ J) (f : Q ⟶ R) (g : R ⟶ S) [_inst_6 : category_theory.exact g.op f.op], f ≫ h = 0 → (S ⟶ J) := λ
{C : Type u} [_inst_1 : category_theory.category C] [_inst_2 : category_theory.limits.has_zero_morphisms C]
[_inst_3 : category_theory.limits.has_images Cᵒᵖ] [_inst_4 : category_theory.limits.has_equalizers Cᵒᵖ]
{J Q R S : C} [_inst_5 : category_theory.injective J] (h : R ⟶ J) (f : Q ⟶ R) (g : R ⟶ S)
[_inst_6 : category_theory.exact g.op f.op] (w : f ≫ h = 0), (category_theory.exact.lift h.op g.op f.op _).unop>
that looks Eric's
Riccardo Brasca (Apr 08 2022 at 11:59):
Voilà. The interesting output starts at line 605.
Eric Rodriguez (Apr 08 2022 at 14:03):
this is amazing! I already see some nice generalisations here...
Eric Rodriguez (Apr 08 2022 at 16:28):
this also reveals things that other linters should catch; for example, docs#algebra.id.smul_eq_mul was purportedly about the smul
from algebra.id
, but it is about has_mul.to_has_scalar
. (This linter catches it as we can generalise this lemma to has_mulR
, even though that makes no sense for algebra
)
Eric Wieser (Apr 08 2022 at 16:33):
Some of those lemmas I just left behind for easy unification
Eric Wieser (Apr 08 2022 at 16:33):
docs#smul_eq_mul is the same as docs#algebra.id.smul_eq_mul
Eric Wieser (Apr 08 2022 at 16:34):
I didn't measure the effects of that, but note that the simp_nf linter doesn't seem to reject the dumplication
Eric Wieser (Apr 08 2022 at 16:35):
Similarly for docs#algebra.mul_smul_comm vs docs#mul_smul_comm
Eric Rodriguez (Apr 08 2022 at 16:35):
Oh, because Lean doesn't have to dig as far for the has_mul
? That makes some sense
Eric Wieser (Apr 08 2022 at 16:35):
Maybe, who knows
Eric Wieser (Apr 08 2022 at 16:36):
I only wanted to light and put back out again so many fires at once in some PRs related to those, and leaving behind the less general lemmas was a nice way to avoid the fire growing
Eric Rodriguez (Apr 08 2022 at 16:37):
also interesteing that it gets some wrong in some weird ways (l632 of above):
#check @no_zero_smul_divisors.iff_algebra_map_injective
/- _inst_2: ring ↝ euclidean_domain no_zero_divisors
_inst_3: is_domain ↝ no_zero_divisors nontrivial
-/
Eric Wieser (Apr 08 2022 at 16:39):
is_domain
could in theory be replaced by those two typeclasses everywhere
Eric Wieser (Apr 08 2022 at 16:39):
It exists to make the spelling shorter
Eric Rodriguez (Apr 08 2022 at 16:39):
I meant more the ring ↝ euclidean_domain
Eric Rodriguez (Apr 08 2022 at 18:33):
first from this new full dataset: #13252
Yaël Dillies (Apr 09 2022 at 21:01):
@Eric Rodriguez, as it turns out I caught in #13268 the same generalization as the linter in #13260 :sweat_smile:
Yaël Dillies (Apr 09 2022 at 21:04):
Too bad I'm not running on a very powerful machine.
Eric Rodriguez (Apr 09 2022 at 21:05):
Riccardo Brasca said:
Voilà. The interesting output starts at line 605.
if you want to PR results from it, here's some of the outputs. I'm working on PRing some of this stuff as a side-hobby
Yaël Dillies (Apr 09 2022 at 21:07):
Yeah I read it but this was on my mind's queue after the "Rename nat.neg_one_pow_of_even
" task :laughing:
Scott Morrison (Apr 09 2022 at 23:53):
I did a little editorial clean-up of @Riccardo Brasca's output, trying to remove the "garbage".
https://gist.github.com/semorrison/bdf8e3a5e4e6da34071f94821cec805c
Scott Morrison (Apr 09 2022 at 23:53):
In particular I simply removed everything that replaces a single type class with multiple ones, as these appear to often incorrect or in any case low priority.
Yaël Dillies (Apr 10 2022 at 07:46):
Do we want the separated_space ↝ t2_space
? I remember some discussion about this.
Scott Morrison (Apr 11 2022 at 11:50):
I did the suggestions for data/polynomials/*
in #13342.
Yaël Dillies (Apr 13 2022 at 12:16):
And me some of the suggestions (which I once again found independently :sweat_smile:) for order.bounded_order
in #13419.
Eric Rodriguez (Apr 13 2022 at 12:17):
The API for
with_top
and the API forwith_top
somehow...
;b
Yaël Dillies (Apr 13 2022 at 12:18):
Whooops
Yaël Dillies (Apr 14 2022 at 10:55):
#13443 for number_theory.
Last updated: Dec 20 2023 at 11:08 UTC