CAS Best Practices

Indeed Symbolics.jl avoids this by having extendable typed symbolics, so @variables x::Complex is something you can do today (and we just need to add nice rules to handle it correctly). And then of course, every quaternion, octonian, etc. package then just works inside of the system, you just have to add rules. Someone has already started to do a bunch of non-commutative algebras in quantum optics with Symbolics+MTK:

https://david-pl.github.io/Qumulants.jl/dev/tutorial/

This is one of the major differences of Symbolics: it’s starting from the position that real numbers, rationals, etc. are just important special cases but instead the real problem is about symbolic arithmetic of typed multiple dispatching values. So from month 1 there’s examples of non-commutative algebras on non-standard numbers being used in the ecosystem, which is exactly what we want to see.

That’s mixing up implementation and interface. A generic interface does not have to choose a single representation, it just needs to be clean, concise, and have a way to change representations. I think many of the CAS’s of the old made a very fundamental mistake of trying to be a full language instead of embedding within a host with generic dispatching mechanisms and adopting all of its standard semantics. REDUCE is probably the closest there, but it has the classic Lisp probably of not having a complete standard library, and so it builds out its own linear algebra routines, its own extended arithmetic, etc.

Of course, the most clear example of this of how to do this is probably DifferentialEquations.jl where one representation gives a few hundred different solvers with the ability to automatically swap arithmetic at will, and those representations are handled by the type system. So you can use Arb in DifferentialEquations.jl, you can use MPFR BigFloats, etc. all because of compiler JIT specializations it’s both high performance yet not feature limited.

The idea of that whole ecosystem is to not even attempt to top-down the feature set, and instead just define strong dispatchable interfaces with common solver sets and allow the whole community to then couple with it. The architecture is described in:

https://www.sciencedirect.com/science/article/abs/pii/S0965997818310251

That should then make clear the design decisions and directions of JuliaSymbolics. Clean interfaces, specializing performance with pure Julia parts where we know unique features can improve it (one of the biggest reasons seems to be the implicit parallelism and now E-graphs in MetaTheory), adding wrappers to both help complete the feature set and make it easier to benchmark pure Julia replacements, using the work of the community to not reinvent the wheel (use number types from other packages, use linear algebra from other packages, etc.), and writing clear documentation about how it all comes together.

I’d invite people to start looking at details. You’ll see that in this implementation style:

How much future welfare of the CAS to be is going to be resting on decisions of this nature?

There is zero cost because there is no preference on a number type. Quaternions.jl can be replaced with some new representation and generics in symbolics can carry over with little to no work. It’s built purposefully generic to allow these kinds of transitions. Action, interface, and representation do not have to be coupled.

12 Likes