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

Desired functionalities before registration #1

Open
6 of 27 tasks
serenity4 opened this issue Apr 21, 2022 · 29 comments
Open
6 of 27 tasks

Desired functionalities before registration #1

serenity4 opened this issue Apr 21, 2022 · 29 comments

Comments

@serenity4
Copy link
Contributor

serenity4 commented Apr 21, 2022

Before we register this package, we should define minimal functionality that may be helpful to others.

Here is a list (kept up to date) of the different features that we are targetting:

  • Define empty functions for common operators in geometric algebra, meant to be extended by implementations:
    • geometric product
    • inner product
    • outer product
    • scalar product
    • commutator product
    • hodge star
    • reversion operator
    • norm
    • left and right contractions
    • grade projection
    • dual operator
  • Define non-unicode functions for all the operators above (e.g. inner, outer, commutator, ...).
  • Define core interface functions that may be useful in context of geometric algebra, declaring functions that are not already declared in Base or LinearAlgebra. They can then be used when validating implementations. These functions include:
    • dim: Dimension of the real space that the AbstractMultivector is embedded within.
    • grades: Grades of the nonzero k-vector components of an AbstractMultivector.
    • Base.zero: Return the additive identity.
    • Base.iszero: Return whether an AbstractMultivector is the additive identity.
    • Base.one: Return the multiplicative identity.
    • Base.isone: Return whether an AbstractMultivector is the multiplicative identity.
    • Base.:(-): Return negation of AbstractMultivectors.
    • Base.:(==): Return whether two AbstractMultivectors are equal.
    • Base.isapprox: Return whether two AbstractMultivectors are approximately equal.
    • Base.getindex(M, k): Return the k-vector component of the AbstractMultivector M.
  • Document all functions, describing their behavior and semantics.
  • Define a test harness for implementations to use, based on the functions defined in this package. This testing utility would validate that implementations possess correct behavior with regard to these functions, by validating most algebraic identities.
  • README documentation describing the intended role of this package, stating our goals for a somewhat official geometric algebra library and describing our decision to let one (or more) implementations come to maturity before committing to any of them in this package.
@eschnett
Copy link

The dot product \cdot is already exported by LinearAlgebra. We should extend that function instead of defining a new one.

@eschnett
Copy link

We should also define (or extend) a few helper functions such as ndims, size etc.

We might also want to define indexing to get at individual components of a multivector. We could keep this optional, but could then still define a standard for how to index multivectors.

  • Should multivectors be an AbstractArray? (Probably not.)
  • Should they implement the iterator interface? (Probably yes.)

@serenity4
Copy link
Contributor Author

serenity4 commented Apr 21, 2022

The dot product \cdot is already exported by LinearAlgebra. We should extend that function instead of defining a new one.

Indeed, and it also exports the cross product \times (which we could take as the commutator product). I see that those are aliases to dot and cross respectively though, and are not functions. It would have been better if those were not aliases but functions that dispatch to dot and cross. We might prefer to define proper functions instead of aliases for all operators, otherwise the names are misleading. About conflicts with LinearAlgebra, I don't know if one would try to use it along GeometricAlgebra; I'd rather think that GeometricAlgebra would have LinearAlgebra as a backend. And otherwise dealing with imports manually would not be as bad as having aliases be misleading. What do you think?

We should also define (or extend) a few helper functions such as ndims, size etc.

We might also want to define indexing to get at individual components of a multivector. We could keep this optional, but could then still define a standard for how to index multivectors.

* Should multivectors be an `AbstractArray`? (Probably not.)

* Should they implement the iterator interface? (Probably yes.)

Good point about these helper functions. We can define the functions that are not defined in Base (so, things other than ndims and size, maybe grade for example) for implementations to extend.

I also agree that multivectors should not necessarily be AbstractArray.

About iteration, although I think they should implement the iterator interface I think there are multiple iteration orders for vectors (other than (dually) single-graded) and multivectors in general, so it would be hard to write tests against that. Indexing would be easier to handle, e.g. we can provide functions for indexing from a linear index into a structured index and vice-versa (a bit similar to CartesianIndex but along grades which have a non-uniform length)

@eschnett
Copy link

I often have code that uses both linear algebra and higher level representations. I would try to stay away from conflicts. This would also make it more difficult for people to rewrite existing low-level functions to using higher level representations (geometric algebra). LinearAlgebra is a very basic package, it's difficult to stay out of its way.

We could choose a new name, e.g. times, and make this an alias (or a function calling) cross.

I would use the iterator interface mostly for functions such as map, i.e. to apply element-wise operations. Maybe I really want the broadcasting interface instead.

@serenity4
Copy link
Contributor Author

serenity4 commented Apr 21, 2022

I often have code that uses both linear algebra and higher level representations. I would try to stay away from conflicts. This would also make it more difficult for people to rewrite existing low-level functions to using higher level representations (geometric algebra). LinearAlgebra is a very basic package, it's difficult to stay out of its way.
We could choose a new name, e.g. times, and make this an alias (or a function calling) cross.

I see, I agree that it would be best to not have two different versions of the same unicode operators. But my concern is that we'd force implementations to extend dot and cross instead of more appropriate functions. dot is most likely ok but the cross product actually has a different meaning than the commutator product (for one, it produces a vector, instead of a bivector). Also, in general I think that extending aliases is confusing because we think we're extending a function while in reality we're extending the aliased one.

Then, we can of course have our own aliases, but my concern is about what functions we're fundamentally extending. The dot product and cross product are quite specific to linear algebra. If \times and \cdot were functions, there wouldn't be any issue, but we can't change that in LinearAlgebra.

On the user side, a way to solve this conflict would be to define your own function \times or \cdot which calls either the one from LinearAlgebra or from GeometricAlgebra. Something like

×(x, y) = LinearAlgebra.:×(x, y)
×(x::GeometricAlgebraType, y::GeometricAlgebraType) = GeometricAlgebra.:×(x, y)

or, to show that it's two fundamentally different things:

×(x, y) = LinearAlgebra.cross(x, y)
×(x::GeometricAlgebraType, y::GeometricAlgebraType) = GeometricAlgebra.commutator(x, y)

and same for \cdot. It's not ideal, but I think that avoiding confusion about semantics would be preferable. For the time being, if an implementation wishes to use the same \times as LinearAlgebra, nothing prevents it from doing so with something like

using LinearAlgebra
import LinearAlgebra: ×
using GeometricAlgebra

GeometricAlgebra.:×(x::MyType, y::MyType) = ×(x, y)
×(x::MyType, y::MyType) = ...

which I think can be a good temporary solution. We can revisit that once we have an official implementation in this package.

I would use the iterator interface mostly for functions such as map, i.e. to apply element-wise operations. Maybe I really want the broadcasting interface instead.

That makes sense for vectors, but for multivectors there are no well-defined elements. Making a distinction would likely require setting up abstract type hierarchies, and I don't think that's a good idea right now. I think it's best to let implementations define it for their own types for the time being, and not deal with it in this package.

@ktchu
Copy link
Contributor

ktchu commented Apr 27, 2022

I agree with the original proposal, and all of the comments sound reasonable.

I have a couple of thoughts regarding definition of operators, types, etc. in the interface definition.

  • I think it might be useful to separate different geometric algebra issues into different GitHub issues so that work on each issue can progress independently.

  • Extending Operators from LinearAlgebra. I think there may be an option here that could address several of our concerns regarding semantics and operator aliases. It involves a combination of several of the previous comments.

    • Define an AbstractMultivector type (just a single entry point for the abstract type hierarchy).

    • Import the alias from LinearAlgebra and export it from GeometricAlgebra. For instance: \times.

    • Define an exported function that we want the alias to point to with our desired name. For instance: commutator()

    • Import the aliased method to LinearAlgebra, but don't export it. Define a non-exported version of the method that takes AbstractMultivector arguments and dispatches it to our exported function. Document the function to indicate its purposes. For instance:

      # `cross()` is a non-public method that exists solely to connect the `\times` alias to the `commutator()` function.
      cross(x::AbstractMultivector, y::AbstractMultivector) = commutator(x,y)
      
  • Abstract Type Hierarchy. I agree that we don't want to impose a complex type hierarchy on developers of GeometricAlgebra implementations. That said, I think it wouldn't be unreasonable to include the following two abstract types in the general interface because they are so fundamental to geometric algebra and likely to be included in most implementations.

    • abstract type AbstractMultivector end
    • abstract type AbstractBlade <: AbstractMultivector end
  • Core GeometricAlgebra Interface

    Here is a list of functions (binary operations excluded) that I think could be a reasonable start for an interface for the AbstractMultivector type.

    • dim: dimension of the real space that the AbstractMultivector is embedded within. Not present in Base.
    • grades: grades of the nonzero k-vector components of an AbstractMultivector. Not present in Base.
    • norm: norm of the AbstractMultivector. Extends LinearAlgebra.norm
    • dual: dual of the AbstractMultivector. Not present in Base.
    • reverse: Return the revserse of a AbstractMultivector. Extends Base.reverse
    • zero: Return the additive identity. Extends Base.zero
    • iszero: Return whether an AbstractMultivector is the additive identity. Extends Base.iszero
    • one: Return the additive identity. Extends Base.one
    • isone: Return whether an AbstractMultivector is the multiplicative identity. Extends Base.isone
    • :(-): Return negation of AbstractMultivectors. Extends Base.:(-)
    • :(==): Return whether two AbstractMultivectors are equal. Extends Base.:(==)
    • isapprox: Return whether two AbstractMultivectors are equal. Extends Base.isapprox
    • getindex(M, k): Return the k-vector component of the AbstractMultivector M. Extends Base.getindex

    Here is a list of functions (binary operations excluded) that I think could be a reasonable start for an interface for the AbstractBlad type.

    • grade: grade of the AbstractBlade. Not present in Base.
    • volume: signed volume of the AbstractBlade. Not present in Base.
    • inv: mulitplicative inverse of the AbstractBlade. Extends Base.inv(), which makes expressions like B^-1 possible.

@serenity4
Copy link
Contributor Author

serenity4 commented May 1, 2022

This sounds great. Regarding extending operators from LinearAlgebra, I am still a bit put off by having

julia> using GeometricAlgebra

julia> 
dot (generic function with 42 methods)

julia> ×
cross (generic function with 1 method)

while the fundamental operators are much more than the standard dot and cross products, but if that's only me I can get behind the suggestion by @ktchu.

Otherwise, I find reasonable the suggestions for the type hierarchy and the core operations defined for them. As a minor comment, I would believe that inv, dual, reverse, single-argument - and maybe (less sure about those) ==, isapprox are operators in themselves (though not always binary) in that they are required for performing core operations.

@ktchu
Copy link
Contributor

ktchu commented May 2, 2022

@serenity4 I agree that the aliases are off-putting. Two thoughts on how to address that issue.

  1. (short-term) Include a docstring for our exported version of the \cdot and \times operators so that they at least show up in the help for \cdot and \times.

  2. (long-term) After the general GeometricAlgebra.jl becomes more mature and if it has reasonably wide adoption, I don't think it would be unreasonable to propose to the maintainers of the LinearAlgebra package that we transition \cdot and \times to function calls instead of aliases to avoid the confusion that you pointed out in the REPL.

@ktchu
Copy link
Contributor

ktchu commented May 2, 2022

As a minor comment, I would believe that inv, dual, reverse, single-argument - and maybe (less sure about those) ==, isapprox are operators in themselves (though not always binary) in that they are required for performing core operations.

Agreed that these could be considered operators. Clarification question about terminology: are we using the term "operator" for both the long-form function name and the unicode operator function names? Or is there a different way that we are distinguishing operators from "interface functions"?

@serenity4
Copy link
Contributor Author

After the general GeometricAlgebra.jl becomes more mature and if it has reasonably wide adoption, I don't think it would be unreasonable to propose to the maintainers of the LinearAlgebra package that we transition \cdot and \times to function calls instead of aliases to avoid the confusion that you pointed out in the REPL.

Unfortunately LinearAlgebra is in the standard library, so I am afraid that option is not available.

are we using the term "operator" for both the long-form function name and the unicode operator function names? Or is there a different way that we are distinguishing operators from "interface functions"?

I would personally think of operators as "functions that perform core logic essential in the geometric algebra framework", as opposed to interface functions that are here to provide additional metadata/utilities/integration with other interfaces. In that sense, I wouldn't differentiate between the unicode name and the standard name, even if the unicode symbol is (most of the time) an infix operator. Though it's more of a personal terminology, I think the term is otherwise rather blurry as it may have slightly different meanings in different contexts (in mathematics vs programming for example).

@Jollywatt
Copy link

Jollywatt commented Sep 2, 2022

Hello all,

I'm enthusiastic to get this project rolling, but would like to get some clarity on how to start.
I have a working implementation of multivector types over at https://github.com/Jollywatt/GeometricAlgebra.jl. My current understanding is that the next steps for me should be:

  1. Rename to something like Multivectors.jl or even EuclideanMultivectors.jl or DenseMultivectors.jl depending on how specialised I want my package to be. (At the moment, it works with any metric signature, and supports SparseArrays, but it may be better to pick something specific and do it well instead of trying to do everything.)
  2. Restructure code to use JuliaGeometricAlgebra/GeometricAlgebra.jl and extend its methods.
  3. Once the implementation reaches near-maturity, transfer ownership of the project to this organisation.

Some things I'm unsure about:

  • I want to avoid making an opinionated package, but my implementation will inevitably have design decisions that other users might dislike. How do I be courteous to other possible implementations? Should I avoid a snatching up Multivectors.jl from the package namespace for myself, or should I claim it and avoid unwieldy names like BasicMultivectors.jl? I know that the end user would rather do using Multivectors than something weird-sounding.
  • How does transferring ownership to JuliaGeometricAlgebra work?
  • Is there anything else I should be aware of or be careful to get right?

Edit:
The package https://github.com/digitaldomain/Multivectors.jl already exists. From glimpsing the source, my implementation differs in that:

  • there is no distinction between covariant and contravariant vectors
  • geometric multiplication of blades is done at run-time, not compile time
  • $k$-vectors and multivectors are just wrappers for component arrays, rather than collections of Blades, or KVectors.
  • multivectors are displayed in a way which tries to mirror how basic Vectors are displayed in the REPL, rather than with a succinct mathematical notation (e.g., ⟨0.65⟩₀ + ⟨10.0e₁₃,10.0e₂₃⟩₂)
  • most things are slower
  • generally, my package is aimed at pedagogy, rather than research

@Jollywatt
Copy link

Meta-question: where is the best place to consult this group for opinions and feedback regarding my own implementation package? Should we have a wiki?

@serenity4
Copy link
Contributor Author

I am personally busy with other projects at the moment, though happy to discuss directions for the project. Any efforts are appreciated to develop this package if it can be useful to you or others.

Your understanding seems correct. I would say that the transfer of ownership is optional, depending on whether you want to have the package be part of the organization or not. It is usually good practice to increase the confidence in projects (notably by potentially having more than a single maintainer), when you believe the package is in a decent state to be considered seriously for development and upkeep. Transfer of ownership is achieved by using the option "Transfer" in the repo settings. I guess that GitHub would then put some sort of automatic redirection in place for older versions.

For the naming, it seems somewhat analogous to automatic differentiation in Julia: there will be several implementations of the same thing. Instead of a descriptive name (as you suggested i.e. EuclideanMultivectors.jl, DenseMultivectors.jl or other), but that can't describe the core functionality as well as GeometricAlgebra.jl, I would suggest to use something a bit detached from the functionality (e.g. for AD this was Zygote.jl, Enzyme.jl, Diffractor.jl, ...). That is, only if you intend to register the package in the General registry, otherwise you can name it GeometricAlgebra.jl as that's completely fine.

I am not so sure right now that there will be one main package to elicit to take the place of a canonical GeometricAlgebra.jl; it would be nice if there was, but probably there will always be several approaches to implementing GA that will have different uses for different contexts. At some point I think we could rename this GeometricAlgebra.jl to GeometricAlgebraBase.jl. The name GeometricAlgebra.jl would be sort-of implicitly "forbidden" (just like I don't think there is any AutomaticDifferentiation.jl).

Regarding your meta-question, I think https://github.com/orgs/JuliaGeometricAlgebra/discussions can be a good place (can you create new discussions?), otherwise feel free to create a geometric-algebra stream on Zulip (could be more discoverable by other people).

@eschnett and @ktchu feel free to chime in if you have any thoughts on the matter.

@ktchu
Copy link
Contributor

ktchu commented Sep 6, 2022

@Jollywatt Great to meet you! Thanks for restarting the conversation on the JuliaGeometricAlgebra/GeometricAlgebra.jl package. I think we've all gotten a bit busy over the summer.

I agree with @serenity4's comments. In case it's helpful, I'll add one other idea to the mix.

  • Local Registries Using local registries (https://github.com/GunnarFarneback/LocalRegistry.jl) might be a good interim way to release the different implementations of GeometricAlgebra.jl. That's the current approach that @wgvozdjak and I have taken for our implementation. As the types, interfaces, and tests defined by JuliaGeometricAlgebra/GeometricAlgebra.jl mature, the current plan is to have our implementation "derive" off of the JuliaGeometricAlgebra package to ensure compatibility.

    The local registry approach also helps to address some of your other concerns.

    • avoids the need to introduce unwieldy names for package users
    • allows you to release your Multivectors.jl package even though the package name is already taken in the General registry

Eventually, we may need to sort out how to use packages with the same name from different registries, but I think this is a low probability event in the near-term.

@chrisjldoran
Copy link

Hi everyone. I wanted to extend a discussion to this thread that I've started with @Jollywatt. I have been working on GA in Julia for a few years now, and together with a collaborator we have a new, optimised library ready to release. https://github.com/MonumoLtd/GeometricAlgebra.jl. This has some commercial support from a company I am working with.

I talked about the library at ICACGA last year, originally intending to call it SimpleGA. (I am also due to talk on this at JuliaCon this summer.) But using acronyms in package names is not encouraged and seeing that GeometricAlgebra is not taken we decided to use that name. Then I came across @Jollywatt's work and this thread. So I wanted to see what people think about registering this name, given your plans. My thoughts are:

  • The library we have developed is low level and optimised. I want to use it as the basis for graphics work where I am going next (and I'll be encouraging people to join this effort at JuliaCon).
  • The library is also very simple. It just implements the geometric product, projection and a few other operations. The intention is that this will be good for teaching as people can build there own work on top of this.
  • The philosophy of 'geometric product first' is important, I believe, and consistent with Hestenes' development of Geometric Algebra. Once you have the geometric product you can build the exterior product and other things.
  • So, basically, I'm making a pitch that this library can start to form the basis as an entry point for the subject, while not taking the fun out of things by implementing everything you could possibly want.
  • But, I appreciate everyone has their own views on the 'right' way to develop a GA package and the ambition to keep GeometricAlgebra as more of a portal to the subject is an interesting one. Though I'm not sure how that would work in practice.

Anyway, let me know what you think. Personally I would like to use the GeometricAlgebra package name and talk about this at JuliaCon. I think there is plenty of scope to grow applications on top of this library while keeping the core simple. And obviously I am keen to work with as many people as possible to develop this.

@serenity4
Copy link
Contributor Author

Hi,

It's nice to see commercial uses of GA!

The main issue I have with registering a package under the name GeometricAlgebra.jl is as I described in my previous comment:

I am not so sure right now that there will be one main package to elicit to take the place of a canonical GeometricAlgebra.jl; it would be nice if there was, but probably there will always be several approaches to implementing GA that will have different uses for different contexts.

For example, with a package which allows low-level access to geometric algebra constructs and restrictions to retain performance, then it is a nice package to build things from, but not really something that one would like to advertise as the "way" to do geometric algebra. This would be appropriate for developers, which may appreciate the use of GA for implementing core numerical algorithms, but not for general users that simply want to play around with GA and use it for non-performance critical code.

On the other hand, a high-level package will most likely have its own drawbacks, specifically in terms of performance which is often suboptimal with generic GA implementations. Very good performance can definitely be achieved, but if hand-written implementations of specialized algorithms perform even 1.5x faster than the GA implementation, libraries implementing performance-critical algorithms may outright discard the idea of using GA (or, at least, that makes the idea of dedicating time to even learn about GA less appealing, particularly in a community that cares that much about peformance). A good metric IMHO is to see how linear algebraic operations perform compared to existing libraries. If one can get the same performance as optimized linear algebra routines, then GA may have a much larger impact and could argue for its adoption in core packages.

I personally believe that it is not possible to get optimal performance without resorting to an approach which integrates compile-time simplifications and having direct control over the generated instructions, which prompted me to work on a SymbolicGA.jl package. But that has drawbacks too; notably, a lack of dynamism which is less suited to playing around in the REPL for example, as well as potentially increased compile times especially as the dimensions of algebras increase.

That is why I would recommend to use another package name, as no matter what is chosen as the "canonical" GA implementation it will address a different set of trade-offs that may or may not be suited for a given audience. And if a GeometricAlgebra package is put forward, that would surely shadow other implementations and might be the only impression most people will get about GA, which again might be aligned with their expectations or might not.

The issue is similar with the automatic differentiation ecosystem in Julia, but AD is such a focus and so widely known as a concept that people tend to know about which packages they should use or not (or at least there are Discourse threads for that). But there, whether to use Zygote, Enzyme or ForwardDiff for example is completely context-dependent, and each has its drawbacks (be it for performance - again, use-case dependent, e.g. backward or forward differentiation - or support for advanced programming constructs).

As mentioned in the discussion, there is always the option of using a local registry if you really want to use the name GeometricAlgebra. For example, you could register the package on the General registry with another name, making it accessible and allowing collaboration, and have a local registry where that package is registered under the name GeometricAlgebra such that you can use one name or the other in your projects. Not ideal, but a fair option.

By the way, I don't think it is necessarily bad to have acronyms in package names, just that if we can avoid it then it's better. It's typically not great if these acronyms are about very specific things that 99.99% of people won't know about (worse if it is not even easy to figure out from the package description or even via Google). A short repo description with an expanded acronym would be a fairly easy way to improve readability. I wouldn't expand NURBS in a package name for example, and the Julia package NURBS.jl has the fairly explanatory description NURBS.jl - Non Uniform Rational Basis-Splines for Julia which IMO clarifies it nicely.

(I am also presenting at JuliaCon about SymbolicGA.jl, and I'd be happy to share ideas over GA implementations anytime. Feel free to reach out!)

@chrisjldoran
Copy link

Thanks. I get all these points and will think on them. I do have some immediate thoughts though:

  • I moved to Julia from Haskell because of its promise of high-level programming and near-metal performance, and by and large it has delivered on that lofty goal. I see GA as a great example of this. A good library can deliver great performance, while keeping the interface high level. This is what we have set out to achieve, and I think we have something good for low dimensional algebras (up to around G(4,4)). So I'd argue that this is the starting point where people should come in.

(A recent win was stripping out all Vectors from some code and swapping in GA elements allowed my algorithm to immediately run on the GPU, which is pretty cool.)

  • For much larger spaces I think it is less clear that GA offers a compute advantage. It is great for theoretical work and understanding concepts in linear algebra, but the challenges of working with e.g. large matrices are computer science challenges, not mathematical ones. Recently I was playing around in 28D getting a bivector representation of the Lie Algebra E4 working (all done on Maple!). This all worked fine, but if you imagine trying to store a full rotor in that space you would get a nasty shock. As a practical tool rotors are useless in large spaces without specific ways of handling them.

  • It seems inevitable that someone will register GeometricAlegbra at some point. We cannot police this, and I'd much rather the initial experience was a decent one. I have a colleague who nearly gave up on GA because their first experience was with a Julia library that performed terribly. (I'll tell you which one over a pint at JuliaCon!).

  • Where I'd like this to get to is taking ownership of the name and establishing a Committee to agree what goes in it. I'll raise this at GAME2023 next month (I'm speaking there too, if you are able to make it). I hope I have a reputation for being fair and open with GA (and with life). Certainly the moment someone else produces a faster library than the current one I will want to swap that into the repo. The package site and docs can then advertise other packages and approaches while ensuring that the first experience is a decent one.

  • This way we could focus efforts on standardising an API, rather than specific notation (which will never happen). The big driver for this (for me) will be constructing a GA front end for graphics, building on GLAbstraction. I think this is enterprise that will appeal to a decent team and could a real gamechanger.

Let me know what you think, particularly around committee ownership of GeometricAlgebra.

Chris

@serenity4
Copy link
Contributor Author

It seems inevitable that someone will register GeometricAlgebra at some point.

Indeed, this is why we thought that this JuliaGeometricAlgebra/GeometricAlgebra.jl package could be a decent placeholder for a GeometricAlgebra.jl package. We started thinking about designing it as an API package that would provide functions (and possibly abstract types) for implementations to extent, but never finished it and so it remained unregistered.

For me personally, the reason for stopping work on fleshing out this initial API came from the fact that in the implementation I am working on, no API is required beyond a unique macro. My use case with GA is not even to have types which represent GA elements, but rather define geometric operations using GA as a meta-language which can integrate seemlessly with arbitrary container types, e.g. tuples, standard vectors but also GPU-specific types. The only use I have of GA at this stage is as a language in which to code algorithms to make them simpler, easier to understand and more composable. All in a GPU-compatible way (using graphics APIs, which are more restrictive than compute APIs) and with maximum performance. As for my own motivations, I am developing a set of libraries for graphics programming (we do seem to have overlapping interests!) using the Vulkan/SPIR-V route. I aim to use algorithms written in GA language in Julia that are compatible with compilation into SPIR-V code (yes, I am really putting a lot of effort to avoid having to use GLSL/HLSL for coding shaders), which is currently coming together quite well.

I can propose to have a GeometricAlgebra.jl package that acts as a suite providing access to different implementations over a unified interface, similarly to DifferentialEquations.jl. I would certainly prefer to have a package that uses implementations as dependencies rather than focusing on one specific implementation with its particular API. At this stage I am convinced that whatever API will be developed will be significantly tied to the implementation that uses it, notably because of the level of abstraction at which GA resides. For example, whether or not to include arbitrary multivectors as valid elements is not a trivial matter depending on the implementation.

I do not have any issue with promoting specific implementations (and I do encourage it, for GA has a very good potential in the realm of numerical computing), and agree that leaving the name GeometricAlgebra.jl free is not great for the risk of having someone else registering it. The issue I would have is promoting any specific project as the main path for developing geometric algebra in Julia, unless it shows exceptionally good trade-offs for most uses. Notably with respect to:

  • Maintainable and clean code (no or little code repetition, well-documented).
  • Performance (optimal or near optimal with known caveats, if any).
  • Clean and intuitive high-level API (doesn't have to opt in to any specific notation, but having implementations for commonly used GA operators would be a plus).

And as mentioned previously, different trade-offs will be more or less important to different people. Near-optimal performance with GA implementations requires careful thought, and designing an intuitive high-level API is not an easy task either.

We can definitely have a think about how to select such a canonical implementation (and in pragmatic terms, as perfect does not exist). I do not think based on all the GA packages I know of that we'd have any suitable candidates ready right now, but we can work towards developing a few approaches that would have potential in this regard. Reserving a GeometricAlgebra.jl package in the name of an open organization and a common effort can be done separately from selecting an implementation. Waiting a bit more before performing such a selection would be wiser IMHO.

Regarding the management of any GeometricAlgebra.jl, as long as it happens inside a well-defined organisation where at least two active members have admin rights, I don't think there will be any problem of reputation or trust. I can add you to the JuliaGeometricAlgebra organization if you want.

A few more comments on performance:

  • I agree with your point on high-dimensional spaces, probably most people will want to use e.g. 3D GA, PGA and CGA, and perhaps a few other low-dimensional spaces.
  • Julia is really fast and numerical algorithms have been so optimized that even fast code can seem slow, even if compared to other languages it remains blazing fast. Any implementation of GA that is to be adopted as a cornerstone will be scrutinized for performance by the community, and I recommend to stay very critical about it if you decide to advertise any GA library as a foundational element.
  • If the library is meant in context of a specific project or effort, then good enough performance is probably sufficient, as bottlenecks may not appear there in this particular context. Advertising for general use to the wider community is a completely different game.

@ktchu
Copy link
Contributor

ktchu commented Mar 30, 2023

First, it's great to meet you, @chrisjldoran! Congratulations on the upcoming release of your GeometricAlgebra package! Thank you for sharing your thoughts and ideas for reasonable approaches for managing GeometricAlgebra package in the general registry.

@serenity4 Good to hear from you again. Like you, I have been busy with other work, which has unfortunately contributed to the lag in our discussion.

I generally agree with @serenity4 regarding the challenges and trade-offs with a single GeometricAlgebra package in the General Julia package registry. Personally, I think the local registry approach is a good one to help reduce clutter in the General registry (though the marketing, adoption, and confusion drawbacks are not to be discounted). For your reference, I have included some notes I collected on setting up a local registry at the end of this comment (it was easier to set up than I expected)

@serenity4 It sounds like approach we were originally thinking of for General/GeometricAlgebra might be (1) difficult to reach consensus on, (2) perhaps not as viable as originally believed (because each implementation has different goals, assumptions, etc.), and (3) is a heavier effort than I think we might reasonably have time to maintain.

As an alternate proposal, what do people think of implementing General/GeometricAlgebra as a "portal package" (as @chrisjldoran suggested)? I'm envisioning something lightweight similar to the following.

  • The GitHub repository for the project includes a README with (1) an explanation of the purpose, meaning, and general organization of the "portal package", (2) links to individually managed GeometricAlgebra implementations (i.e., GitHub repositories and local registries) and (3) instructions for how to install packages from local registries (it's pretty straightforward).

  • The package itself only includes a "dummy" GeometricAlgebra module with a docstring containing (1) a brief description and motivation why General/GeometricAlgebra is a portal package and (2) a reference to the README of the GitHub repository for more details.

Local Registry: Registry Maintainers

  • Create a registry.

    • Set up a remote Git repository (e.g., on GitHub).
    • Create the registry. This following command will create a registry directory ~/.julia/registries/ with the specified name, set it up as a Git repository, and set the remote for the Git repository.
      julia> using LocalRegistry
      julia> create_registry(...)
      
    • Push the registry to the remote repository for the registry.
      $ cd ~/.julia/registries/<registry_name>
      $ git push -u origin HEAD
      
  • Add a writable registry to the Julia installation.

    julia> ]
    pkg> registry add <registry_git_url>
    

    To avoid SSH key compatibility issues, use Julia >= 1.7 and set the JULIA_PKG_USE_CLI_GIT environment variable to true.

Local Registry: Package Maintainers

Setup

  • Add a writable registry to the Julia installation (see above).

Register a new package

  • Register a package.
    • Use LocalRegistry to register the package.
      julia> using LocalRegistry
      julia> register(package, ...)
      

Release a new version of the package

julia> using LocalRegistry
julia> register(package_name)

Local Registry: Package Users

  • Add a writable registry to the Julia installation (see above).
  • Add package
    julia> ]
    pkg> add <package from local registry>
    

@serenity4
Copy link
Contributor Author

Thanks for the suggestion @ktchu, a portal package makes a lot of sense to me. It would be great to take the opportunity of having such a portal to host documentation:

  • About the different implementations and the characteristics of each (expanding on simple links to other implementations).
  • About geometric algebra in general, and introduce the topic (hopefully in an unopinionated manner) for people unfamiliar with it. This could make documenting individual implementations easier, as they could link to that portal repo and assume basic familiarity with GA (at least, not have to explain everything from scratch). Might not be trivial to align on what a "good" introduction should be like, but I am quite open if that means users get a clear idea about what GA is about.

I think to get started (and register something) having at least a clear README and links to implementations would be enough, though.

I see two main challenges with local registries for wider adoption (so far, I believe we all used local registries for specific projects, which is different than asking for other packages in the General registry to use them):

  • Any dependent of a NewRegistry/GeometricAlgebra.jl package would require NewRegistry for itself and all downstream packages, as otherwise the name GeometricAlgebra.jl will not be resolved (fortunately, we won't have the wrong package installed, as I think package UUIDs would have to match).
  • I believe local registries would require further tooling for managing new releases to be viable for collaboration. As presented above, the way to register a new version of a package is to do so using LocalRegistry.register, but that requires manual intervention from a person; better would be to have the registry in question have a bot, just like JuliaRegistrator for the General registry. That would be up to individual registries to do, but I think it's pretty essential to invite collaborators.

I believe these caveats are enough to justify having implementations in the General registry for those whose purpose is to be adopted and built upon by the Julia community. I see local registries as good solutions for specific projects, but maybe not so great to require for developers and users in general - at least not until secondary registries emerge and we don't require a new registry simply for installing a single geometric algebra package (e.g., having a "Graphics" registry with a collection of related packages might be useful, though fragmentation may become a problem). Having both a version in General and in local registries also seem fine to me, though personally I find having to use another name than GeometricAlgebra.jl for my packages acceptable and easiest.

@chrisjldoran
Copy link

Thanks everyone. I've been thinking about this a lot over the last few days, and here is what I intend to do. I know it goes against the advice above, but I hope you agree that the reasoning is sound. You also have my word that I'll reverse this if it clearly causes problems in the community.

First off, I think we all want the same thing. As @serenity4 said, we want a GA library that serves as a initial introduction to the subject and is:

  • Maintainable and clean code (no or little code repetition, well-documented).
  • Performance (optimal or near optimal with known caveats, if any).
  • Clean and intuitive high-level API (doesn't have to opt in to any specific notation, but having implementations for commonly used GA operators would be a plus).

This didn't exist last summer, which is precisely why I set out to build it. I also have the luxury currently of having 2 experienced Julia software engineers on tap to help get the code to a professional standard. So I'd like to release this as GeometricAlgebra, and expect the library to be criticised when it fails to meet @serenity4's goals.

I'm sure you don't need a lecture on the advantages of having an MVP that keen be used, tested and criticised over trying to design the perfect piece of software by committee!

Under the hood the GeometricAlgebra library has a range of different implementations, all of which can be used simultaneously. I see no issue introducing additional ones and handling all of the complications of multiple algebras with submodules, namespace management and multiple dispatch. This combination in Julia is actually quite awesome and makes everything just work.

Over time I expect to see a lot more work on the larger algebras, and ideally a symbolic package too. These can all be active so that, eg if you do some work in a symbolic package but then want to drop into a implementation for speed that is easy to do. (I can see that the conversion utility between algebras could become a focus of work, but there are no conceptual issues here).

So I do think we can shoot for having everything we want in one place, with the main thought having to go into conversions between algebras. We'd want to avoid unnecessary duplication, so performance will be the main criteria if forced to chose. But I'm always happy to swap out code for something faster, and Julia has great benchmarking tools to settle any debates.

Beyond that my library is 'agenda-free'. Multivectors are created from basis vectors, and you can chose the name these however you like. Multiplication is *, and everything else works as expected. The only piece of personal agenda that underlies this package is that it is 'geometric product' first. If you want to just do exterior algebra you can make it work, but there are better alternatives out there. That is the one smallish hill I will take a stand on!

Beyond the core package, the site will also advertise other implementations and extensions, as well as hopefully building up a good set of examples. The ultimate test is that this library is used to enable interesting projects, and not to be admired as a GA implementation.

In terms of timeline I'm proposing:

  • Registering the package + cooling off period.
  • 'Soft' launch at GAME2023. There will be a strong GA contingent there with interest in graphics, though maybe not that much interest on the Julia angle. I hope to make a few converts with this library.
  • A period where we push / criticise / break things and build up a list of what could / should be added.
  • 'Full' launch at JuliaCon, together with an open invitation to the community to get involved and hopefully create a committee to oversee improvements. If enough of us are at JuliaCon then that will be a great opportunity to thrash out any issues.

My measure of success with this endeavour is that in 12 months time there is a self-sustaining group of people improving the package, and I know that when I type 'using GeometricAlgebra' in my own projects it will just work!

As I said, if it turns out that these ambitions are unachievable then I'll reverse out and we'll go a different route. But for now I do think a good solution is in reach and we should at least try to build it!

@ktchu
Copy link
Contributor

ktchu commented Mar 30, 2023

@serenity4 @chrisjldoran. I think this has been a productive discussion about pathways forward for General/GeometricAlgebra. While there will always be points of disagreement, I think we are all working in good faith to find a structure that works well for the community (including future users and developers).

@chrisjldoran. I agree with your measures of success for this package (and any package in general) and appreciate you explicitly expressing your willingness to revert changes that cause difficulties to the community. I also agree that Julia's language structure should make it possible to, in principle and over time, converge several implementations under the same hood. And, MVP over perfect software by committee is definitely something I'm a supporter of.

Regarding registration of the General/GeometricAlgebra package, I have a couple of thoughts in the area of "promoting a community spirit".

  • @chrisjldoran. What do you think of having the GitHub repository for the package that you register be the one from this organization – JuliaGeometricAlgebra/GeometricAlgebra.jl? I see two main benefits from this: (1) it explicitly demonstrates a "blessing" from the current community that your package is a reasonable starting point for the General registry package and (2) potentially adds a couple of additional developers/maintainers from the current community.

  • In the spirit of data-driven decision making, I think it would be good to monitor usage, developer activity, and other relevant (and easily obtainable) metrics for all of the GA packages. In my opinion, these should form the foundation for decisions about whether we, as a community, want to change the package registered with the General registry.

  • @chrisjldoran. What is your thinking on how contributions to your package would be managed? and what license are you planning to use for the package?

@serenity4
Copy link
Contributor Author

Under the hood the GeometricAlgebra library has a range of different implementations, all of which can be used simultaneously. I see no issue introducing additional ones and handling all of the complications of multiple algebras with submodules, namespace management and multiple dispatch. This combination in Julia is actually quite awesome and makes everything just work.

Just to be clear, when talking about implementations previously I was talking about implementations of the geometric algebra framework, not specific geometric algebras. Ideally, such a framework would allow any kind of geometric algebras. Including only the most used ones is a reasonable choice, yet remains a trade-off. The term "implementation" was used to refer how GA rules are defined and enforced in the code, not to refer to specific algebras.

My measure of success with this endeavour is that in 12 months time there is a self-sustaining group of people improving the package, and I know that when I type 'using GeometricAlgebra' in my own projects it will just work!

Unfortunately, it won't be as simple as that. I believe we all agree that different implementations will choose different trade-offs. You may have your own goals, but imposing trade-offs is not the way to go. And changing a set of trade-offs for another would typically require rewrites from scratch. SymbolicGA.jl is my second iteration of a 2-year long development process (in and out), the first of which being https://github.com/serenity4/GeometricAlgebra.jl, and it may not be the last.

I can cite several trade-offs that the implementation you propose makes (please correct me if I am wrong on any of those points):

  • Disallowing mixing even and odd grade elements (as mentioned in the package docs: you cannot combine even and odd elements in any of the optimised algebras). You give good reasons as to why this can be reasonable, but this remains a trade-off in favor of performance that is required by a specific library design. Why would we not want to combine elements if the algebraic rules allow it?
  • Basing the library on the geometric product. This sacrifices performance whenever grade projections are desired (i.e. not requiring the full result of the geometric product). Such grade projections are needed for the outer product, but also for the inner product, and we do have uses for those in GA, it is not only for purely exterior algebras. I could give a few benchmarks for operations that are useful in GA that would be forced to remain largely suboptimal by design because they involve grade projections.
  • Limiting which algebras can be used based what has been implemented. This makes it impossible for users to experiment with new algebras beyond those that will have been contributed to the repo.
  • Having all algebras hardcoded in the package. I can see how it may be easier for initial development, but designing algebras separately makes it very complex to refine together. It also means that the package may grow quite large in size (introducing lots of types and methods), preventing a lightweight design with increased load times, beyond maintenance considerations.

Note that those are not "negative" points in any way; they are trade-offs. But personally, these trade-offs are not those I am after, and that is the reason I would not join the development of this specific project. That does not mean at all that I would not enjoy sharing ideas over ways to implement geometric algebra in Julia, however!

I understand that you want to launch an effort and include other people in the development of a geometric algebra framework. I simply believe there is no rush to advertise a General/GeometricAlgebra.jl package. Why sacrifice this central name for a first prototype? If you expect mainstream adoption of the library, know that if (or rather when) a large redesign is needed, that will be hugely breaking, and I would rather avoid rough transitions for users if it could be avoided by simply having different packages for smoother transitions.

I believe it is perfectly possible to lead such a development effort using another package name. I am trying to avoid suffering from consequences of a choice we will have made early on. This is why I hope that you will accept choosing another name (SimpleGA.jl for example, or anything else that you like), and leave all the rest (the project, the ambitions...) unchanged. We can let the discussion cool down for a while before any decision is made. Again, we are not in a rush.

@chrisjldoran
Copy link

Thanks guys, a bunch of interesting questions. I do hope I get to meet you both soon. In no particular order, first @ktchu

  • Choice of repo. For now this is simply a pragmatic one. Monumo are happy to support this development in the hope of some minor PR / kudos, so I'm happy to go with them. We are using the repo in internal development too. It is a public repo so anyone can contribute. All companies have a finite concentration span, so I expect this will migrate to the home you suggest when they lost interest.
  • License is MIT, which I believe is the most permissive. Happy to be corrected on this and change it. There is no question of Monumo wanting to own any IP here.
  • Monitoring contributions. Yeah, this may be tricky at first. I really want to get to a committee to do this, but it will take a while to sort out. What I'll try and do is set down some basic 'API rules' to stick to.
    And @serenity4
  • Disallowing mixing even and odd grade elements. This is such a useful optimisation that it would be a waste to not use it. The need hardly ever arises in practice, and on the odd occasions it does there is a simple solution - move up a dimension. Note that this is not a restriction on the more conventional algebras, G(4,4) and G(32,32).
  • Basing the library on the geometric product. Well, it is a GeometricAlgebra library! Your comment on using projection information to optimise performance is correct. For the small algebras it does not look like it is worth the effort, but for the large ones this is worth doing. The main function that does implement this is 'dot', which is fast precisely because we know the result is a scalar. There is definitely scope for optimising the 'project( A * B , n)' construct, which we can look at. Nothing in the current design choices precludes this. (It was a key part of my Haskell code, and improved the performance from 'dismal' to 'borderline acceptable')
  • Limiting which algebras can be used based what has been implemented. Currently the biggest is G(32,32), which is pretty big. Pretty much everything can be built from that. We can go bigger if people want. But everyone has the code and can add their own algebras too. If they are interesting we can add them back in.
  • Having all algebras hardcoded in the package. There is clearly going to have to be some cap on the included algebras to prevent bloat, so we need some real drive from the community to add more. I don't see many more being required. The only 2 on my list are G(8,0) and G(64,0). Do you see any obvious holes?
  • Why sacrifice this central name for a first prototype? This is not the first prototype! This is already about version 3, and I'm already building packages on it. I've also been writing GA libraries for 30 years in various languages. But my main reason for doing this now is the upcoming conferences, and my belief in release and iterate.

@serenity4
Copy link
Contributor Author

I agree with your points @chrisjldoran, I was just highlighting that those are trade-offs based on assumptions you made that work for you. I tend to have a more ambitious and perhaps idealistic goal; for one, most of these trade-offs are not required when going through the symbolic route. From what I see, you have a very pragmatic take on how to approach these trade-offs, and I respect that (even more so when backed by your experience using GA for concrete projects).

In the end, you are free to do as you wish, and I only hope that we will not come to regret using that silver bullet with using that GeometricAlgebra.jl name if you go for it. Regardless, you do seem to have a good drive, and I'd be more than happy to see GA flourish in the Julia ecosystem.

I won't be able to make it to GAME2023, but I am looking forward to meeting those of you who will attend JuliaCon :)

@Jollywatt
Copy link

Just agreeing with @serenity4's points here. My own emphasis is to prioritize the newcomers' experience in order to encourage adoption.

Imagine a new user wanting to try out Julia and GA. They quickly find "GeometricAlgebra.jl", and will then expect to be able to:

  • play around with arbitrary algebras
  • construct arbitrary multivectors
  • use other well-established products they've read a bit about, such as $\wedge$ and $\times$

Then, once the user is a bit more serious, they might look to more specific packages like "FastGA.jl", "PGA.jl" or "SymbolicGA.jl" depending on their needs.

If the newcomer is faced with e.g., having to move everything from $\mathbb{R}^3$ to the STA using a peculiar isomorphism in order to "apply a rotor to a 3D vector", they might come away thinking GA is more complicated than it is.1 Putting it on the user to implement $\wedge$ could have a similar effect.

I'm optimistic and believe that a performant GA implementation that is "complete" in the above sense is just around the corner.2 MonumoLtd/@chrisjldoran's package is deliberately a "partial" implementation. Hence my plea to leave the privileged name "GeometricAlgebra.jl" reserved for the time being and to choose a descriptive name for General.

Footnotes

  1. One idea for how to fix this for https://github.com/MonumoLtd/GeometricAlgebra.jl could be to implement e.g., an GA30.Mixed type which simply wraps GA31.Even and overrides mv_to_text to display it as an element of Cl(3). You'd have to implement this separately for every algebra though.

  2. It's encouraging that, based on some simple benchmarks, my own https://github.com/Jollywatt/GeometricAlgebra.jl seems to be around 1.5x slower than @chrisjldoran's for things like 3D multivector products and sums, while the former is a "complete" implementation.

@serenity4
Copy link
Contributor Author

I see that the package is already pending registration: JuliaRegistries/General#80669

@chrisjldoran
Copy link

Thanks everyone. We'll see how it goes, and I expect you to keep challenging me to meet our ambitions. A couple of small points:

  • @Jollywatt "having to move everything from to the STA using a peculiar isomorphism in order to "apply a rotor to a 3D vector". I think you misunderstood. You can multiply even and odd elements quite happily. To apply a rotor R to a vector a in any algebra you write " R * a * R' ". The result is an odd multivector. Preventing this would be a crime against GA. The only thing you cannot do is ADD an even to an odd. I've never seen a good use for this, and preventing it reduces memory by 1/2, and boosts performance by between 2x and 4x. This is all explained in the docs. People I've shown this trick to at conferences have always liked it.
  • "use other well-established products they've read a bit about, such as wedge and X." This is definitely up for debate. Adding times(A,B) as a product for example is one line of code to add to one file. The reason to not do it is a lack of consistency with notation. For GA purists X is half the commutator product (see Hestenes and Sobczyk, equation 1.55). But most people typing 'a X b' in 3D would expect the cross product (a vector) not a bivector. If you have a clean proposal for resolving this dilemma then we can implement it. But it has been an irritating bit of notation for over 50 years and so far no-one has a good answer. (For a period we used a BOLD X for the vector cross product to distinguish it from the commutator product, but it wasn't a good choice.)
  • The outer product. Potentially more useful, though there are still some issues. The big problem is that the outer product's definition usually assumes that the input multivectors are homogeneous (all the same grade). It isn't as general as the geometric product. It is easy for someone to implement their own version using the geometric product and projection onto grade and that leaves people to use their own notation. Some people in the community are doing very strange things with notation, duality, etc. so for now I thought it best to let people implement their own. But if there is a proposal that a good number can agree on it is easy enough to add (and optimise).

@ktchu
Copy link
Contributor

ktchu commented Mar 31, 2023

@chrisjldoran. I was under the impression that your proposal was still under discussion (i.e., a decision was not yet made), so I am surprised and disappointed to see that the pending registration of Monumo Ltd's implementation with the General registry.

While I respect your expertise and status in the field of Geometric Algebra and appreciate your software engineering/delivery philosophy, your goals as stated can be achieved using a local registry for now while we, as a community, decide on the path we would like to take to move forward:

But my main reason for doing this now is the upcoming conferences, and my belief in release and iterate.

While using a local registry is perhaps slightly more inconvenient for developers who would like to contribute, it is relatively low overhead for most seasoned developers (and, in my opinion, a worthwhile skill for less experienced developers to acquire).

From the perspective of "marketing" Monumo's package to the wider community at a conference (especially for a 'soft' launch to a slightly tangential community), I would expect that having the package in the General registry vs a local registry should not make or break interest from people who are serious about Geometric Algebra (though it may be a bigger activation barrier for people mostly interested in graphics ... but, in my opinion, that should not be the target audience for a Geometric Algebra package registered in the General registry).

To summarize, I disapprove of the currently active registration of Monumo Ltd's GeometricAlgebra package because our community discussion has not yet concluded (i.e., no decision has been explicitly made and multiple viable options are still on the table). To be clear, I am not necessarily opposed to the technical aspects of the Monumo package (though there are several identified by @serenity4 and @Jollywatt that raise concerns for me). In my opinion, respecting an in-progress community discussion (and the concomitant inconveniences of the slight delay) outweighs the benefits of a fast move to market.

I respectfully request that Monumo withdraw its registration of their GeometricAlgebra package for inclusion in the General registry. Thank you for your consideration.

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

No branches or pull requests

5 participants