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

Support for abstract vector spaces. #1781

Closed
wants to merge 74 commits into from

Conversation

capn-freako
Copy link
Contributor

@capn-freako capn-freako commented Jun 17, 2022

This PR introduces Algebra.Linear.VectorSpace, an abstract vector space.

The purpose of this new type is to provide the familiar metaphor/interface of "vector/matrix" that people are used to using in their client code, without locking the back-end implementation into arrays (more generally, n-tuples).
In this way, we hope to decouple the capture of design intent from design implementation, for architectures based on the concepts of linear algebra, such as machine learning networks.

commit d298d8b7b3f11c62b244db05970e8ba454baa9be
Author: David Banas <capn.freako@gmail.com>
Date:   Sat May 28 09:22:06 2022 -0700

    Final commit to `vector-space-foldr` branch.

    The experiment w/ right folds worked beautifully and will be merged back
    into `vector-space`.

    - Reverted `Data.List.Properties`, as I no longer need all the left fold
    accoutrements.

commit 8845ac79817c39423edb20ba87b0e75a8d0265c2
Author: David Banas <capn.freako@gmail.com>
Date:   Sat May 28 08:20:58 2022 -0700

    Clean-up pass.

commit d3b3256e88152d7d9820a99be2a584ae0135ad21
Author: David Banas <capn.freako@gmail.com>
Date:   Sat May 28 07:35:29 2022 -0700

    Cleanup of `VectorSpace.Properties`.

commit 06e69efbcce0c2a7fcd32936d0b2bb1fdff5f348
Author: David Banas <capn.freako@gmail.com>
Date:   Sat May 28 07:13:50 2022 -0700

    First successful compilation of `T-oS<=>v-dot`.
@capn-freako
Copy link
Contributor Author

Anyone know why the Ubuntu build / test-stdlib (pull_reuest) test failed?

@guilhermehas
Copy link
Contributor

From Wikipedia (https://en.wikipedia.org/wiki/Vector_space), I think that Vector Space is defined over a Field and not from a Commutative Ring.

@MatthewDaggitt
Copy link
Contributor

Anyone know why the Ubuntu build / test-stdlib (pull_reuest) test failed?

Not your fault (#1804)

From Wikipedia (https://en.wikipedia.org/wiki/Vector_space), I think that Vector Space is defined over a Field and not from a Commutative Ring.

Thanks @Taneb and @guilhermehas for the heads up! I'd totally missed that. It's a good point. @capn-freako I think they're right that we should stick to the standard definition. May I ask where you go the current definition from?

@capn-freako
Copy link
Contributor Author

Thanks @Taneb and @guilhermehas for the heads up! I'd totally missed that. It's a good point. @capn-freako I think they're right that we should stick to the standard definition. May I ask where you go the current definition from?

Admittedly, I "cheated" when I didn't find Field available among the other standard algebraic definitions.
Shall I take a whack at defining Field and, then, redefining VectorSpace to use it, instead of CommutativeRing?
I think we'll need division eventually, anyway, when working most generally w/ vector spaces, even abstractly.

@JacquesCarette
Copy link
Contributor

You're likely to want to define R-module over a (commutative?) ring first. That's fully constructive. Vector Space over a Field is... hard.

@capn-freako
Copy link
Contributor Author

You're likely to want to define R-module over a (commutative?) ring first. That's fully constructive. Vector Space over a Field is... hard.

Thanks, Jacques! Have you been down that particular road before?

I like this concise summary of Field (from the Wikipedia page):

Even more summarized: a field is a commutative ring where 0 ≠ 1 and all nonzero elements are invertible.

@capn-freako
Copy link
Contributor Author

You're likely to want to define R-module over a (commutative?) ring first. That's fully constructive. Vector Space over a Field is... hard.

Oh, shoot! The new multiplicative inverse function must be partial, because 0# must be excluded from its domain.
Is that why you warned me thusly?

@capn-freako
Copy link
Contributor Author

Hey guys, a question about something in Algebra.Structures:
In IsRingWithoutOne, the additive inverse is defined thusly:

+-isAbelianGroup : IsAbelianGroup + 0# -_

while in IsNearring it is defined:

+-inverse   : Inverse 0# _⁻¹ +

What is the significance of this difference?

@MatthewDaggitt
Copy link
Contributor

Oh, shoot! The new multiplicative inverse function must be partial, because 0# must be excluded from its domain.
Is that why you warned me thusly?

Yes we haven't quite worked out how we want to handle the partiality. See #1175 for discussion.

@MatthewDaggitt
Copy link
Contributor

What is the significance of this difference?

It's an artefact of the order of inheritance. One inherits from IsQuasiring and the other from IsAbelianGroup. In general it's very difficult to come up with a consistent inheritance pattern and is an area of active research how to do it modularly (which we have definitely not achieved in the standard library!)

@JacquesCarette
Copy link
Contributor

Have you been down that particular road before?

Not this exact one, but close enough to know that this way lies much pain.

Oh, shoot! The new multiplicative inverse function must be partial, because 0# must be excluded from its domain.
Is that why you warned me thusly?

Yes!

Matthew also said:

In general it's very difficult to come up with a consistent inheritance pattern and is an area of active research how to do it modularly (which we have definitely not achieved in the standard library!)

In my mind, the most general solution requires explicit morphisms between definitions (not just embeddings induced by same-name-same-thing) and a proper notion of pullback/pushout. Agda actually has many of the needed features already, but "closing the gap" still requires quite a lot of work.

@MatthewDaggitt MatthewDaggitt added status: won't-merge Decided against merging the PR in. and removed status: being-worked-on labels Sep 17, 2022
@MatthewDaggitt
Copy link
Contributor

@capn-freako I'm going to close this PR as I think the current approach needs some rethinking and probably some addition scaffolding first. Feel free to open a new PR if you revisit it later on and think you've fixed the problems!

@capn-freako
Copy link
Contributor Author

Oh, snap! I was just putting the finishing touches on a next push, which I think addresses the concerns and is much more in line w/ the literature.
Any chance you could reopen this PR for one more round?

@MatthewDaggitt
Copy link
Contributor

Sure!

@capn-freako
Copy link
Contributor Author

Okay, guys, I think that last push is much more in line with the literature and addresses your previous concerns.
Please, take a look and let me know what you think.

Thanks!
-db

Copy link
Member

@Taneb Taneb left a comment

Choose a reason for hiding this comment

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

On the whole I'm really not happy with the approach taken here. We certainly shouldn't merge this before the imminent release of 2.0, and I don't think this approach will lead to something merits inclusion in the standard library.

I welcome @capn-freako to adapt this into a standalone library and continue developing it.

I suggest for the standard library that we work towards linear algebra in small, well-reasoned chunks building on what we've already implemented. I have in my head a rough roadmap for this (and other things!) that I've been working on for a good while.


field
isCommutativeRing : IsCommutativeRing + _*_ - 0# 1#
*-inverse : {x : A} → (p : x ≢ 0#) → (x * ((x ⁻¹) {p})) ≈ 1#
Copy link
Member

Choose a reason for hiding this comment

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

This mixes propositional equality (_≢_) with setoid equality (_≈_), which is a really bad idea. Consider Data.Rational.Unnormalised. This type has many representations of 0 which are propositionally distinct, e.g. mkℚᵘ (+ 0) 0 and mkℚᵘ (+ 0) 1, so instead it uses the equivalence relation _≃_ under which all of these representations of 0 are equivalent.

_/_ : (x y : A) → {y ≢ 0#} → A
(x / y) {p} = x * ((y ⁻¹) {p})

field
Copy link
Member

Choose a reason for hiding this comment

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

The definition of a field also needs a rule that 0 does not equal 1, or equivalently that every invertible element is nonzero

@@ -863,6 +865,21 @@ record IsCommutativeRing
; *-isCommutativeMonoid
)

record IsField
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that definitions of fields should go in Algebra.Structures and Algebra.Bundles, considering that they're not quite algebraic structures. I'm not sure where we should put this definition, but we already have Algebra.Apartness.{Bundles, Structures} containing one notion of a field.

record IsVectorSpace : Set (suc (ℓm ⊔ ℓr ⊔ m ⊔ r)) where

field
basis : IsBasis
Copy link
Member

Choose a reason for hiding this comment

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

I think there are vector spaces of interest for which it is very difficult for us to define a basis for, such as the space of functions from ℚ to ℚ.

vacc ss vs = foldr _+ᴹ_ 0ᴹ (zipWith (_*ₗ_) ss vs)

field
basisSet : List V
Copy link
Member

Choose a reason for hiding this comment

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

Having the basis set be a list means we can't define infinite-dimensional vector spaces, such as the space of polynomials over ℚ. An alternative might be to have an indexing set and a function from that set to the vector space, but then we need to decide whether we need to think about levels.

-_ : Op₁ Carrier
0# : Carrier
1# : Carrier
_⁻¹ : (x : Carrier) → {x ≢ 0#} → Carrier
Copy link
Member

Choose a reason for hiding this comment

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

I think that this operator might be very hard to use in practice. I don't see how the implicit x ≢ 0# parameter would ever be inferred.


-- An _Inner Product Space_ is a vector space augmented with a function
-- that takes two vectors and returns a scalar.
record IsInnerProductSpace (f : V → V → S) : Set (suc (ℓm ⊔ ℓr ⊔ m ⊔ r)) where
Copy link
Member

Choose a reason for hiding this comment

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

There really ought to be some laws here.

@MatthewDaggitt
Copy link
Contributor

Given @Taneb's feedback and the lack of reply I'm going to close this again for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition status: won't-merge Decided against merging the PR in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants