Zulip Chat Archive
Stream: general
Topic: Undergraduate math list (algebras)
Patrick Massot (Oct 05 2021 at 14:58):
Oliver, the question is whether you can write a def that takes a lie algebra structure and outputs a non_unital_non_assoc_semiring
Eric Wieser (Oct 05 2021 at 15:01):
Patrick Massot said:
Oliver, the question is whether you can write a def that takes a lie algebra structure and outputs a
non_unital_non_assoc_semiring
Should we have bracketive
/unbracketive
to match multiplicative
/additive
? One translates between +
and *
, the other between lie brackets and *
.
Oliver Nash (Oct 05 2021 at 15:07):
Patrick Massot said:
Oliver, the question is whether you can write a def that takes a lie algebra structure and outputs a
non_unital_non_assoc_semiring
I see, well we can do this:
import algebra.lie.basic
variables (L : Type* ) [lie_ring L]
def lie_ring.to_non_unital_non_assoc_semiring : non_unital_non_assoc_semiring L :=
{ mul := has_bracket.bracket,
left_distrib := lie_add,
right_distrib := add_lie,
zero_mul := zero_lie,
mul_zero := lie_zero,
.. (by apply_instance : add_comm_group L), }
Oliver Nash (Oct 05 2021 at 15:09):
And if we had also assumed lie_algebra R L
(for a comm_ring R
) we could define the relevant is_scalar_tower
and smul_comm_class
classes.
Eric Wieser (Oct 05 2021 at 15:09):
Where does the has_scalar R L
instance come from?
Oliver Nash (Oct 05 2021 at 15:10):
From lie_algebra.to_module
Eric Wieser (Oct 05 2021 at 15:11):
Eric Wieser (Oct 05 2021 at 15:13):
Oh I was getting confused by lie_ring_module
which has a different sort of action, never mind
Oliver Nash (Oct 05 2021 at 15:13):
Oh, but actually you have a point, we need a has_scalar L L
.
Oliver Nash (Oct 05 2021 at 15:14):
Which I guess would come from lie_ring.to_non_unital_non_assoc_semiring
via has_mul.to_has_scalar
if we set things up right.
Patrick Massot (Oct 05 2021 at 15:26):
Oh wow, someone took the trouble to sort the conversations in different topics
Patrick Massot (Oct 05 2021 at 15:26):
What is the conclusion then? Do you have a fully working instance?
Oliver Nash (Oct 05 2021 at 15:27):
No but I could create one. It would be a type synonym and 3/4 associated instances on it. I can create and PR it if you would like but it is not very likely to be used.
Oliver Nash (Oct 05 2021 at 15:27):
I'd be more inclined to do it if we "fixed" our algbera
class.
Oliver Nash (Oct 05 2021 at 15:27):
Of course, very easy and won't do any harm.
Patrick Massot (Oct 05 2021 at 15:28):
I don't think it necessarily needs to be PRed, but clarifying this would be nice
Patrick Massot (Oct 05 2021 at 15:28):
What do you mean by fixing here?
Oliver Nash (Oct 05 2021 at 15:29):
Changing its definition so that it does not require the underlying "ring" to be unital and associative.
Oliver Nash (Oct 05 2021 at 15:29):
There was an old branch where Scott and I made a brief attempt to do this and more recently there is this: https://github.com/leanprover-community/mathlib/commit/dcbed292a23994dfddf70d8262a4defb3103e968#diff-7fa8b94b14c549770d3cddb5a015c4c6029e40e3cd5161d574d9b9f5e7cdff1bR54
Patrick Massot (Oct 05 2021 at 15:29):
Ok, that's a big refactor.
Oliver Nash (Oct 05 2021 at 15:30):
Yep
Oliver Nash (Oct 05 2021 at 15:30):
Patrick Massot said:
I don't think it necessarily needs to be PRed, but clarifying this would be nice
I'll paste a complete version here later today.
Oliver Nash (Oct 05 2021 at 16:07):
The following is not pretty but I think should illustrate how to do this:
import algebra.lie.basic
def lie_ring.to_has_mul (L : Type*) := L
def forward {L : Type*} : L → lie_ring.to_has_mul L := λ x, x
def back {L : Type*} : lie_ring.to_has_mul L → L := λ x, x
variables {R L : Type*} [comm_ring R] [lie_ring L] [lie_algebra R L]
instance : non_unital_non_assoc_semiring (lie_ring.to_has_mul L) :=
{ mul := λ x y, forward ⁅back x, back y⁆,
left_distrib := lie_add,
right_distrib := add_lie,
zero_mul := zero_lie,
mul_zero := lie_zero,
.. (by apply_instance : add_comm_group L), }
instance : module R (lie_ring.to_has_mul L) :=
@lie_algebra.to_module R L _ _ _
instance : is_scalar_tower R (lie_ring.to_has_mul L) (lie_ring.to_has_mul L) :=
{ smul_assoc := smul_lie, }
lemma lie_smul' (t : R) (x y : L) : t • ⁅x, y⁆ = ⁅x, t • y⁆ := by rw lie_smul
instance : smul_comm_class R (lie_ring.to_has_mul L) (lie_ring.to_has_mul L) :=
{ smul_comm := lie_smul' }
Oliver Nash (Oct 05 2021 at 16:56):
Tidied up :point_up: slightly. LMK if you want anything else.
Eric Wieser (Oct 05 2021 at 17:11):
with_mul
is probably a better name than to_has_mul
.
Patrick Massot (Oct 05 2021 at 17:53):
It still feels weird that we don't have a plain non_unital_non_associative_algebra R A
. People coming to mathlib and asking where are algebras will have a very hard time understanding the answer
Eric Wieser (Oct 05 2021 at 17:56):
If we do that we face the docs#domain problem, where either:
- Lots of lemmas get stated about
domain
that don't actually require all ofring
,nontrivial
, andno_zero_divisors
- No lemmas actually use
domain
, which means it's not really pedagogically useful
And to make matters worse, typeclass inference can't promote ring R
nontrivial R
no_zero_divisors R
into integral_domain
even though they mean the same thing
Eric Wieser (Oct 05 2021 at 18:12):
I think that last problem goes away in lean4
Eric Wieser (Oct 05 2021 at 18:12):
I guess we could just define it like docs#vector_space but not use it?
Eric Wieser (Oct 05 2021 at 18:13):
(i thought we did that for vector_space
too but I guess not)
Johan Commelin (Oct 05 2021 at 19:12):
Patrick Massot said:
It still feels weird that we don't have a plain
non_unital_non_associative_algebra R A
. People coming to mathlib and asking where are algebras will have a very hard time understanding the answer
Understanding the answer will be just as hard as understanding why we have group
and add_group
. And just as hard as why we can't use ∘
to denote multiplication in endomorphism rings.
Patrick Massot (Oct 05 2021 at 19:14):
I disagree, this is not the same order of magnitude.
Johan Commelin (Oct 05 2021 at 19:18):
Hmm, ok, I agree that such algebras could exist. Do you agree that Lie algebras wouldn't be instances?
Johan Commelin (Oct 05 2021 at 19:19):
I've never used such algebras, apart from Lie algebras.
Yury G. Kudryashov (Oct 05 2021 at 19:22):
@Patrick Massot Does the "module R A
+ is_scalar_tower R A A
+ smul_comm_class R A A
" definition work in this case?
Yury G. Kudryashov (Oct 05 2021 at 19:22):
If yes, then we can go with branch#redefine-algebra and use very weak typeclass assumptions in the definition.
Patrick Massot (Oct 05 2021 at 19:26):
Johan, did you intend to write "Lie algebras would be instances"?
Patrick Massot (Oct 05 2021 at 19:27):
I'm talking about https://en.wikipedia.org/wiki/Non-associative_algebra which does include Lie algebras and mathlib algebras as special cases
Patrick Massot (Oct 05 2021 at 19:27):
(although wikipedia insists the base ring is a field for some mysterious reason)
Johan Commelin (Oct 05 2021 at 19:28):
No. I meant "would not".
I think it is more useful that every associative algebra gives a Lie algebra, via the commutator bracket, then the fact that the Lie algebra can be viewed as a non-assoc multiplication.
Having both as instances would give two non-propeq multiplications on every assoc algebra.
Yury G. Kudryashov (Oct 05 2021 at 19:29):
But we can have a type tag that turns a Lie algebra into a (non-assoc) algebra.
Yury G. Kudryashov (Oct 05 2021 at 19:29):
Then we restate all facts in terms of Lie brackets.
Patrick Massot (Oct 05 2021 at 19:31):
Yury, yes I think this collection of type classes work
Yury G. Kudryashov (Oct 05 2021 at 19:31):
And it is equivalent to the standard definition in case of semiring A
.
Patrick Massot (Oct 05 2021 at 19:32):
Johan, we don't have to have instances of this, I only suggest that people who want to formalize stuff about algebras can find a way to express this without searching Zulip for this thread.
Yury G. Kudryashov (Oct 05 2021 at 19:33):
@Eric Wieser This :up: is another reason to remove algebra_map
from the definition of algebra
.
Patrick Massot (Oct 05 2021 at 19:33):
I certainly don't want our currently supported algebras to become harder to use because of this definition.
Patrick Massot (Oct 05 2021 at 19:34):
I think we can simply put the definition somewhere and not use it.
Johan Commelin (Oct 05 2021 at 19:39):
Ok, then I fully agree with you.
Yury G. Kudryashov (Oct 05 2021 at 19:44):
Earlier, I suggested the same retractor as a way to get rid of some TC diamonds.
Yury G. Kudryashov (Oct 05 2021 at 19:45):
We only lose some definitional equalities for algebra_map
, nothing more.
Yury G. Kudryashov (Oct 05 2021 at 19:46):
And we can reuse instances about scalar towers in definitions of algebras.
Yaël Dillies (Oct 05 2021 at 20:13):
Patrick Massot said:
Johan, we don't have to have instances of this, I only suggest that people who want to formalize stuff about algebras can find a way to express this without searching Zulip for this thread.
I think a better solution to this is to curate a note explaining how maths-speak translates to mathlib-speak. Typically, an explanation of how to declare a vector space or an algebra.
Eric Wieser (Nov 08 2021 at 15:14):
#10221 improves the docstring of algebra
a little, which somewhat helps here.
Kevin Buzzard (Nov 08 2021 at 15:55):
for vector spaces I think we came up with a really nice idea involving either notation or reducible defs, I can't remember, it was something Anne and I talked about months ago and then I never did anything about.
Kyle Miller (Nov 09 2021 at 22:13):
Would it be possible to make a command to do the canonical variables
incantation for you for various objects?
For example, maybe
declare algebra R A
declare vector_space K V
would do
variables [comm_semiring R] [semiring A] [algebra R A]
variables [field K] [add_comm_group V] [module K V]
I am imagining that this wouldn't be worked out automatically, but rather it would be hard-coded. Maybe another command def_declare
could create entries in its database, allowing these definitions to be put near relevant classes. Perhaps as a bonus it could add {A : Type*}
and so on if these variables aren't already present.
An unsophisticated implementation could be that declare
is a parameterized open_locale
, doing textual substitution of the arguments.
If this is possible, would it be a good idea? I like how it's not particularly magical (and you can verify its effects with #where
and such) and how it doesn't abuse the language (anything nonstandard is localized to the declare
line).
Rob Lewis (Nov 09 2021 at 22:20):
This is definitely doable (with docs#lean.parser.emit_code_here) and would make a nice little project! Working out which classes are needed from e.g. algebra R A
should be doable too, at least if all the types involved appear in the target type class.
Anne Baanen (Nov 09 2021 at 22:20):
I have a patch for Lean lying around somewhere that allows you to write [ring R] [[algebra R A]] [[module R M]]
, and adds all the missing typeclass dependencies, e.g. [ring R] [semiring A] [algebra R A] [add_comm_monoid M] [module R M]
. However, adding more locals broke the elaborator terribly and I couldn't figure out a good way to proceed.
Anne Baanen (Nov 09 2021 at 22:26):
https://github.com/leanprover-community/lean/commit/d17c9e0c67573a35b8319da15b816409e92c160e
Kyle Miller (Nov 09 2021 at 22:29):
@Anne Baanen Having [[...]]
notation for auto-inserting all missing dependencies in binders would be great, too, if that could work, though it doesn't solve vector_space
, I think. There could be an attribute for classes (abbreviation_class
?) that directs this feature to try to eliminate the class completely. For example
@[abbreviation_class]
def vector_space (K V : Type*) [field K] [add_comm_group V] [module K V]
could define how `[[vector_space K V]]
is replaced, though this might be confusing if you forget the double square brackets.
Anne Baanen (Nov 09 2021 at 22:30):
Also as you can see, where in mathlib we would know to use [add_comm_group M]
when R
is a ring, the fancy brackets only insert add_comm_monoid
.
Anne Baanen (Nov 09 2021 at 22:35):
Kyle Miller said:
Anne Baanen Having
[[...]]
notation for auto-inserting all missing dependencies in binders would be great, too, if that could work, though it doesn't solvevector_space
, I think. There could be an attribute for classes (abbreviation_class
?) that directs this feature to try to eliminate the class completely. For example@[abbreviation_class] def vector_space (K V : Type*) [field K] [add_comm_group V] [module K V]
could define how
`[[vector_space K V]]
is replaced, though this might be confusing if you forget the double square brackets.
Good idea to control the dependencies through an attribute. Maybe we could also setup something like:
class module (R M : Type*) [semiring R] [add_comm_monoid M] := ...
@[dependency (field K) (add_comm_group V)]
abbreviation vector_space (K V : Type*) [semiring K] [add_comm_monoid V] := module K V
-- Don't specialize the typeclass arguments themselves!
Eric Rodriguez (Nov 09 2021 at 22:36):
this would be super cool!
Yaël Dillies (Nov 09 2021 at 22:37):
I assume this is then meant for teaching and not mathlib?
Eric Rodriguez (Nov 09 2021 at 22:38):
I feel like it could be huge for mathlib if you could type more maths-friendly things far more often instead of the typeclass hell you see in things like the statement of FTC
Anne Baanen (Nov 09 2021 at 22:44):
Anne Baanen said:
I have a patch for Lean lying around somewhere that allows you to write
[ring R] [[algebra R A]] [[module R M]]
, and adds all the missing typeclass dependencies, e.g.[ring R] [semiring A] [algebra R A] [add_comm_monoid M] [module R M]
. However, adding more locals broke the elaborator terribly and I couldn't figure out a good way to proceed.
Looking at it again, the precise diagnosis involves lines 796-801 of definition_cmds.cpp
:
bool recover_from_errors = p.m_error_recovery;
elaborator elab(env, p.get_options(), resolve_decl_name(env, fn), metavar_context(), local_context(), recover_from_errors);
buffer<expr> new_params;
elaborate_params(elab, params, new_params);
elab.freeze_local_instances();
replace_params(params, new_params, fn, val);
In elaborate_params
I added the code to add dependencies for instance arguments, however replace_params
can't tell at which points new params were inserted, so it (correctly) trips an error. So a solution would probably start with passing a list of added/deleted indices to replace_params
.
Yaël Dillies (Nov 09 2021 at 22:48):
Eric Rodriguez said:
I feel like it could be huge for mathlib if you could type more maths-friendly things far more often instead of the typeclass hell you see in things like the statement of FTC
Yeah but also the modularity is crucial. During the convexity refacotr, I literally turned a single concrete type into around 15 shades of spaces.
Kyle Miller (Nov 09 2021 at 22:52):
In support of modularity, it can protect code from changes to the algebra hierarchy, since things about a vector_space
don't care too much about exactly which intermediate algebraic objects you also need to include. (And there are in fact theorems about vector spaces, I believe. :wink:)
Anne Baanen (Nov 09 2021 at 23:38):
Anne Baanen said:
So a solution would probably start with passing a list of added/deleted indices to
replace_params
.
This seems to work, almost! Now the only issue is that we detect the list of missing instances by checking which errors result from elaborating the implicit+deps binder, but the errors seem to bubble up to the surface too(?)
Anne Baanen (Nov 10 2021 at 00:22):
Now we ignore the "missing instance" errors. What do you all think, is this addition PR-worthy? https://github.com/leanprover-community/lean/compare/implicit-dep-binder
Eric Rodriguez (Nov 10 2021 at 00:27):
What do the lean4 people think of this in lean4? Not sure who to @
Last updated: Dec 20 2023 at 11:08 UTC