Skip to content

Compose explicit rotor operations

Materialize rotors when their coefficients need to be stored, combined, or used in further products. If \(R_1\) acts first and \(R_2\) second, the composite is \(R_2R_1\). Order matters: to reproduce sequential actions, multiply the rotors directly. Bivectors in different planes generally do not commute, so in general exponentiating their sum does not reproduce the sequential transformation.

import torch
from clifra import make_algebra

algebra = make_algebra(3, dtype=torch.float64)
vectors = algebra.layout((1,))
bivectors = algebra.layout((2,))
even = algebra.layout((0, 2))

exp = algebra.plan_bivector_exp(input=bivectors, output=even)
multiply = algebra.plan_product(left=even, right=even, output=even)
reverse = algebra.plan_unary(op="reverse", input=even)
sandwich = algebra.plan_sandwich_action(left=even, input=vectors, right=even, output=vectors)
action = algebra.plan_versor_action(grade=2, input=vectors, parameter=bivectors)

B1 = torch.tensor([0.4, 0., 0.], dtype=torch.float64)
B2 = torch.tensor([0., 0., -0.7], dtype=torch.float64)
R1, R2 = exp(-0.5 * B1), exp(-0.5 * B2)
R = multiply(R2, R1)
x = torch.tensor([1., 2., 3.], dtype=torch.float64)

composed = sandwich(R, x, reverse(R))
sequential = action(action(x, B1), B2)
torch.testing.assert_close(composed, sequential)
unit = multiply(R, reverse(R))
torch.testing.assert_close(unit, torch.tensor([1., 0., 0., 0.], dtype=x.dtype))

For a rotor produced by exponentiating a real bivector, reversal equals its inverse mathematically. Reversal is not an inverse for an arbitrary even coefficient tensor. A learned unconstrained tensor may not be a rotor, and dividing by its coefficient norm does not enforce the rotor constraints.

plan_sandwich_action computes \(LXR\) with the independently supplied left and right factors; it does not infer an inverse. It retains the intermediate grades required for the requested final output. Handwritten two-product compositions must do the same: selecting vectors immediately after \(Rx\) would generally discard grades needed by the second product.

Repeated floating-point multiplication can accumulate a deviation from \(R\widetilde R=1\). Monitor this relation when storing a long composition. If only the final transformed values are needed, composing induced actions also avoids storing a rotor for every step.