mjo/hurwitz.py: fix entry_algebra_gens() in HurwitzMatrixAlgebra
Just like we did for MatrixAlgebra, add a special case for the
octonions in entry_algebra_gens(). The OctonionAlgebra uses gens()
for the multiplicative generators, so we only get five of them.
mjo/matrix_algebra.py: support OctonionAlgebra in entry_algebra_gens()
We need a special case for algebras that have a basis(), since that's
really what we want, and "generators" is technically incorrect when
multiplication is involved.
mjo/matrix_algebra.py: special case for OctonionAlgebra
Eventually I will switch mjo.hurwitz to use Sage's (new)
OctonionAlgebra class. In preparation, add a special case to deal with
the fact that they have a vector() method but no to_vector().
Michael Orlitzky [Fri, 27 Mar 2026 18:07:17 +0000 (14:07 -0400)]
mjo/clan/normal_decomposition.py: another principal decomp test
There was a bug in the previous test, since we are using the Ishi
convention that gives us a lower-triangular normal decomposition: a
subclan is obtained by "deleting" the first idempotent rather than the
last. After fixing that, we add another test to show that this does
actually produce a subalgebra (the new test finds the bug).
Michael Orlitzky [Fri, 27 Mar 2026 15:25:26 +0000 (11:25 -0400)]
mjo/clan/normal_decomposition.py: add test for principal decomp
We get a principal decomposition of a non-unital clan if we "delete"
the r'th idempotent from the normal decomposition of a unital clan,
but this isn't obvious. Let's test it.
Michael Orlitzky [Fri, 27 Mar 2026 00:56:17 +0000 (20:56 -0400)]
mjo/clan/clan_element.py: add norm methods
For convenience, define norm() and norm_vinberg() in terms of the
corresponding inner product methods. This will usually involve a
sqrt(), and I have not thought very hard about how to handle that
intelligently.
mjo/clan/t_algebra_clan.py: speed up ComplexHermitianClan
To speed up ComplexHermitianClan, we use a quadratic field extension
for the entries of the ambient matrix space rather than (basically)
assuming QQ and QQbar. But before we can do that, we need to adjust
from_matrix() to reject mismatched entry algebras. We also need to
special case several real/complex field pairs, because the quadratic
extension procedure does not always give us something usable -- our
Hurwitz matrix algebras are finicky.
mjo/cone/decomposition.py: allow nonorthogonal nonlinea parts (WIP)
This is a work-in-progress that probably doesn't function and
definitely won't pass tests. I'm pushing the changes only because I
broke Sage on the machine I'm working on and need to sync.
Michael Orlitzky [Sun, 22 Feb 2026 17:44:48 +0000 (12:44 -0500)]
mjo/clan: eliminate UnitalClan
We can add Unital() in NormalDecomposition anyway, because following
Vinberg we assume that they have one. But even if they didn't, the
unit element would be a property of each individual clan.
Michael Orlitzky [Sun, 22 Feb 2026 17:32:43 +0000 (12:32 -0500)]
mjo/clan: more class hierarchy refactoring
Renamed MatrixAlgebra to TAlgebraClan, since in theory the up-hat and
down-hat work for any T-algebra. Separated that out along with the
NormalDecomposition class.
Rework the pointed_linspace_decomposition() as nonlineal_part(),
returning only the pointed component. The lineality space is easy to
obtain, even as a cone, though generally that will be overkill.
We drop _orthogonalize() for now, since it appears that Sage/PPL
will implicitly orthogonalize the cone's lines().
mjo/cone/decomposition.py: new pointed-linspace decomposition
Begin a new experiment with the pointed-linspace decomposition. We
know how to do this with orthogonal projections, but in Sage we must
work over the rationals (and arithmetic is much faster there anyway).
I sketched a quick proof of concept showing that this can be done, and
it's very likely that PPL does exactly the same thing when it
minimizes the generators in Cone().
But just in case, here's an implementation that definitely does what I
think it does.
Michael Orlitzky [Fri, 23 Jan 2026 16:50:23 +0000 (11:50 -0500)]
mjo/clan: complete the migration to three coordinates
Three coordinates are needed to identify a basis element in general:
(i,j) to identify the component, and then "k" for the basis within
the (i,j)th component.
This should allow us to define HnClan, which has 2d off-diagonal
components.
clan: eliminate the user basis stuff from the new clan module
I think we'll be able to get away with just using the "real" basis
elements as keys to the CFM. This makes it easy to reconstruct the
"user" coordinates from CFM elements.
These functions are useful outside of Euclidean Jordan algebras.
It's looking in particular like the _all2list() gimmick may be
a useful general construct for algebras with a user basis.
Michael Orlitzky [Tue, 11 Nov 2025 23:46:20 +0000 (18:46 -0500)]
mjo/cone/decomposition.py: add tests, fix the edges of the edges
A miscellaneous selection:
* The vertex numbering was off because pivots() renumbers them.
* Updated the docs to fix some incorrect claims.
* Added lots of new tests.
* Special case for irreducible cones to return K itself.
* Use subspace_with_basis() instead of span() to preserve
our user basis.
Tests now pass, and the documentation is converging upon the truth.
Using exponentiation was allowing us to skip the domain/codomain check
for operator composition when their dimensions agreed. To fix that, we
reimplement powers directly in terms of multiplication.
This also sheds light on a buggy test that needed to be fixed:
isomorphisms can't necessarily be composed.