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
[Merged by Bors] - feat(linear_algebra/affine_space): affine spaces #2816
Conversation
Define (very minimally) affine spaces (as an abbreviation for add_torsor in the case where the group is a vector space), affine subspaces, the affine span of a set of points and affine maps.
Co-authored-by: Rob Lewis <Rob.y.lewis@gmail.com>
@jsm28 In the future, feel free to remove the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good. I left some comments.
Co-authored-by: Johan Commelin <johan@commelin.net>
Co-authored-by: Johan Commelin <johan@commelin.net>
Co-authored-by: Johan Commelin <johan@commelin.net>
Co-authored-by: Scott Morrison <scott@tqft.net>
Just noting that everything in this file works if you reduce the hypotheses to
as long as you change It seems there's no harm at all in generalising? |
Changed to use |
Aims to fix "invalid object declaration, environment already has an object named 'set.has_coe'" from linting generated all.lean.
(direction : submodule k V) | ||
(nonempty : carrier.nonempty) | ||
(add : ∀ (p : P) (v : V), p ∈ carrier → v ∈ direction → v +ᵥ p ∈ carrier) | ||
(sub : ∀ (p1 p2 : P), p1 ∈ carrier → p2 ∈ carrier → p1 -ᵥ p2 ∈ direction) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is an alternative approach. I'm not sure which one is better but I think that we should discuss the pros and cons of each approach.
- Define
affine_subspace
using the following axioms:
structure affine_subspace (k : Type*) (V : Type*) (P : Type*) [ring k] [add_comm_group V]
[module k V] [affine_space k V P] :=
(carrier : set P)
(add_mem' : ∀ p₁ p₂ p₃ ∈ carrier, (p₂ -ᵥ p₁) +ᵥ p₃ ∈ carrier)
(smul_mem' : ∀ (c : k) (p₁ p₂ ∈ carrier), c • (p₂ -ᵥ p₁) +ᵥ p₁ ∈ carrier)
These axioms are equivalent to yours with two differences:
- I don't include
direction
in the data (though it can be reconstructed). - I don't require the carrier to be nonempty.
The main "pro" of this approach is that the affine subspaces defined this way form a complete lattice. In particular, the intersection of two affine subspaces is always an affine subspace, you can define affine_span s = Inf {t : affine_subspace k V P | s ⊆ (t : set P)}
and have a galois_connection
between set P
and affine_subspace k V P
.
As for direction
, there are a few different possibilities:
- define
direction' : with_bot (submodule k V)
to bebot
for the empty affine space or the set ofp1 -ᵥ p2
otherwise. - define
direction s [nonempty (s : set P)] : submodule k V
; - define
direction s : submodule k V
to be the zero submodule for the empty affine space, otherwise as in 1.
Of course, you can add two of these definitions and prove that they agree (look at polynomial.degree
vs polynomial.nat_degree
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does sounds pretty nice!
@jsm28, you're definitely allowed to include "sounds good, but I don't feel up to attempting this now" in your answer. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that may be my shorter answer, then.
As a longer answer, I suspect there might be use for both types eventually, but the one not requiring nonempty
(i.e. sets of points containing all affine combinations) might best be called something other than affine_subspace
. That one gives the abstract benefit of the lattice structure, but results in various other complications, and I'm less sure of having practical uses for it (but it may be hard to tell what complications arise with each approach without a lot more implemented that builds on affine subspaces).
Anything involving dimensions is likely to be more complicated with empty subspaces, because an empty space should have dimension -1, but dimensions are also naturally expected to be a nat, or a cardinal in the infinite-dimensional case, and to be the same as the dimension of the submodule
that is the direction
; dimension 0 is naturally equivalent to having a single point, so if you special-case empty subspaces as also having dimension 0 to keep the types convenient you lose that equivalence. Two subspaces should be parallel iff their directions are equal, but with empty subspaces that doesn't work if the direction has type submodule
which would make empty spaces parallel to those with a single point. Without empty subspaces, two subspaces are equal iff they have nonempty intersection and the same direction. With empty subspaces, it's no longer the case that any subspace has an affine frame, and a subspace of dimension n only necessarily has a barycentric frame of n+1 points if your definition allows dimension -1 (and various definitions around barycentric coordinates would probably need special-casing for empty subspaces). Empty subspaces can't be converted to affine spaces on a subtype of points, whereas nonempty ones can.
As a general implementation principle, I hope that most definitions and proofs around affine subspaces and spans can do their main work through the corresponding definitions and results for submodules and spans in modules, rather than needing to repeat any logic that's already present in the module case.
I do know that for geometry I'll want types that build on top of nonempty subspaces by requiring them to have a given dimension, so that e.g. types line k V P
or plane k V P
can be defined to affine_subspace_n_dim k V P 1
or affine_subspace_n_dim k V P 2
or similar (and whenever a 0-dimensional subspace arises, it will probably be more convenient to convert it back to a point of type P
).
I don't right now have any working code outside of this PR that builds on affine subspaces. (I do have code building on affine maps, at a fairly trivial level - constructing an affine_map
from an isometry of Euclidean spaces.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be clear:
- This was a suggestion, i.e. I won't insist at least until I'll need this for some good reason (most probably I won't have a reason to use this part of
mathlib
in the next several months); if I'll have a good reason, I'll come again and will be ready to do the refactor. - I do not suggest proving facts about the "bad" empty subspace when it's not convenient. Just add
[nonempty (s : set P)]
or(hs : (s : set P).nonempty)
to anydef
/lemma
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, shall we get this merged? @urkud @semorrison
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks 🎉
bors merge
Define (very minimally) affine spaces (as an abbreviation for add_torsor in the case where the group is a vector space), affine subspaces, the affine span of a set of points and affine maps.
Pull request successfully merged into master. Build succeeded: |
When definitions of affine spaces and subspaces were added in #2816, there was some discussion of whether an affine subspace should be allowed to be empty. After further consideration of what lemmas need to be added to fill out the interface for affine subspaces, I've concluded that it does indeed make sense to allow empty affine subspaces, with `nonempty` hypotheses then added for those results that need them, to avoid artificial `nonempty` hypotheses for other results on affine spans and intersections of affine subspaces that don't depend on any way on affine subspaces being nonempty and can be more cleanly stated if they can be empty. Thus, change the definition to allow affine subspaces to be empty and remove the bundled `direction`. The new definition of `direction` (as the `vector_span` of the points in the subspace, i.e. the `submodule.span` of the `vsub_set` of the points) is the zero submodule for both empty affine subspaces and for those consisting of a single point (and it's proved that in the nonempty case it contains exactly the pairwise subtractions of points in the affine subspace). This doesn't generally add new lemmas beyond those used in reproving existing results (including what were previously the `add` and `sub` axioms for affine subspaces) with the new definitions. It also doesn't add the complete lattice structure for affine subspaces, just helps enable adding it later.
…3219) When definitions of affine spaces and subspaces were added in #2816, there was some discussion of whether an affine subspace should be allowed to be empty. After further consideration of what lemmas need to be added to fill out the interface for affine subspaces, I've concluded that it does indeed make sense to allow empty affine subspaces, with `nonempty` hypotheses then added for those results that need them, to avoid artificial `nonempty` hypotheses for other results on affine spans and intersections of affine subspaces that don't depend on any way on affine subspaces being nonempty and can be more cleanly stated if they can be empty. Thus, change the definition to allow affine subspaces to be empty and remove the bundled `direction`. The new definition of `direction` (as the `vector_span` of the points in the subspace, i.e. the `submodule.span` of the `vsub_set` of the points) is the zero submodule for both empty affine subspaces and for those consisting of a single point (and it's proved that in the nonempty case it contains exactly the pairwise subtractions of points in the affine subspace). This doesn't generally add new lemmas beyond those used in reproving existing results (including what were previously the `add` and `sub` axioms for affine subspaces) with the new definitions. It also doesn't add the complete lattice structure for affine subspaces, just helps enable adding it later.
…y#2816) Define (very minimally) affine spaces (as an abbreviation for add_torsor in the case where the group is a vector space), affine subspaces, the affine span of a set of points and affine maps.
…eanprover-community#3219) When definitions of affine spaces and subspaces were added in leanprover-community#2816, there was some discussion of whether an affine subspace should be allowed to be empty. After further consideration of what lemmas need to be added to fill out the interface for affine subspaces, I've concluded that it does indeed make sense to allow empty affine subspaces, with `nonempty` hypotheses then added for those results that need them, to avoid artificial `nonempty` hypotheses for other results on affine spans and intersections of affine subspaces that don't depend on any way on affine subspaces being nonempty and can be more cleanly stated if they can be empty. Thus, change the definition to allow affine subspaces to be empty and remove the bundled `direction`. The new definition of `direction` (as the `vector_span` of the points in the subspace, i.e. the `submodule.span` of the `vsub_set` of the points) is the zero submodule for both empty affine subspaces and for those consisting of a single point (and it's proved that in the nonempty case it contains exactly the pairwise subtractions of points in the affine subspace). This doesn't generally add new lemmas beyond those used in reproving existing results (including what were previously the `add` and `sub` axioms for affine subspaces) with the new definitions. It also doesn't add the complete lattice structure for affine subspaces, just helps enable adding it later.
Define (very minimally) affine spaces (as an abbreviation for
add_torsor in the case where the group is a vector space), affine
subspaces, the affine span of a set of points and affine maps.