Skip to main content

Cayley Dickson Calculator

The aim of module Cayley_Calculator is to convert the REPL shell, ipython shell or idle into a fast, programmable table calculator for doing scientific and linear calculations with Cayley-Dickson numbers.

What are Cayley-Dickson numbers (CDN)? CDN's extend real (dimension 1), complex (dimension 2) and quaternionic (dimension 4) numbers (either split or non-split) to octonions (dimension 8), sedenions (dimension 16), pathions (dimension 32), chingons (dimension 64) or routons (dimension 128). These classes are included in the Cayley_Calculator. Further included are extensions of standard functions like exp, log, sin, arcsin, sinh, arsinh, ... to these classes. It is even possible to extend some scientific functions in scipy.special. (Of course in this case scipy has to be installed.) Routines for doing linear algebra with CDN's are included and solving equations like a*x + x*a = b or x^3 + a*x^2 + b*x + c = 0 is simple (even much more complicated equations).

To run Cayley_Calculator the module numpy must be installed. Modules scipy and numpy-quaternion are not necessary, but they extend the functionality of Cayley_Calculator.

Elementary background

(Citation from https://pypi.org/project/hypercomplex/): The complex numbers may be viewed as an extension of the everyday real numbers. A complex number has two real-number coefficients, one multiplied by 1, the other multiplied by i.

In a similar way, a quaternion, which has 4 components, can be constructed by combining two complex numbers. Likewise, two quaternions can construct an octonion (8 components), and two octonions can construct a sedenion (16 components).

The method for this construction is known as the Cayley-Dickson construction and the resulting classes of numbers are types of hypercomplex numbers. There is no limit to the number of times you can repeat the Cayley-Dickson construction to create new types of hypercomplex numbers, doubling the number of components each time.

Hypercomplex numbers containment diagram

Theoretical background: The only aim of this background is to fix notation, not understanding. A Cayley algebra over R is an ordered pair (A,s), where A is an algebra over R with unit element 1 and s, the conjugation, is an antiautomorphism of A such that trace T(a) = a + s(a) in R and norm N(a) = a * s(a) in R. Here s(a0,a1,...,a7) = (a0,-a1,...,a7) and * is the not necessary commutative or associative multiplication, where (a0,...,a7) is a special Octonion. To show how Sedenions are defined, let B = A x A with usual addition and let the multiplication in B be defined by

(x1,y1) * (x2,y2) = (x1*x2 + gamma4*s(y2)*y1, y1*s(x2)+y2*x1)

for (x1,y1) and (x2,y2) in B. Note that order matters. gamma1 is used for the definition of complex numbers from the real numbers, gamma2 for quaternions from complex numbers, ... gamma1 = 1 gives split complex numbers while gamma1 = -1 gives the (usual) complex numbers.

With t((x,y)) = (s(x),-y) the ordered pair (B,t) is a Cayley algebra again with trace T((x,y)) = T(x) and norm N((x,y)) = N(x) - gamma4 * N(y), in this case the algebra of Sedenions.

Literature: A standard text is N. Bourbaki (1989): Algebra I, in particular ch. III.2.4, III.7.4 and ch. III, Appendix. Here you find full proofs about commutativity, associativity and alternativity of Cayley algebras. A well known article is from J. Baez (2001), The Octonions, unfortunately only about Octonions and without proofs of some relevant results.

Installation

pip install Cayley_Calculator

and possibly

pip uninstall Octonion_Sedenion

(Cayley_Calculator generalizes Octonion_Sedenion and name conflicts are possible.)

View on PyPI - View on GitHub

This package was built with Python 3.14.6 and has been tested to be compatible with python 3.9 through 3.14 on Linux. Since there is no compiled code it should be compatible with python on Mac and Windows. An installation of numpy is absolutely necessary.

Basic Usage

import Cayley_Calculator
from octonion import *

That's all. To test your installation, try

a,b,c = randinteger(-10,11,3)
a,b
# (Octonion(-9, 9, -9, 2, 10, -5, -9, 6), Octonion(-3, 7, 3, 6, 1, -6, 4, -7))
a*b, b*a
# (Octonion( 17, -244, 80, 28, 39, 25, -171, -43), Octonion( 17, 64, -80, -148, -117, 113, 153, 133)) 
sin(a)
# Octonion(-1.21986179e+08, -1.20165952e+08, 1.20165952e+08, -2.67035450e+07, -1.33517725e+08, 6.67588625e+07, 1.20165952e+08, -8.01106349e+07)
d = randinteger(-10,11,Class=QQ)
# Quaternion(-8, 7, 5, -3)
log(d)
# Quaternion( 2.49521629, 1.76058705, 1.25756218, -0.75453731)

The first line in the initialization is always necessary, but the second line may be replaced by from pathion import *. Then by default randinteger(-10,11) generates a random Pathion with integer coefficients. If we do not want to change the defaults then randinteger(-10,11,Class=PP) has the same effect.

Input of numbers is always handled by __init__(self,*v,array=None). For example

a = Sedenion(Quaternion(1,2,3))
a
# Sedenion(1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

first generates Quaternion(1,2,3,0) and then converts this into a Sedenion. As a further example (Sedenion may be written as SS)

Sedenion(3,4,5)
SS(array = (3,4,5))
Sedenion(array = np.array([3,4,5]))
SS(*range(3,6))

all result in

Sedenion(3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).

A final example (after from sedenion import *, otherwise e10 is not defined) with some special functions

from sedenion import *
e10
# Sedenion(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0)
u = Sedenion(4+5j)
v = Sedenion(4+5*e10)
w = 4+5*e10
print(exp(u))
print(log(v))
print(sin(w))

results in

15.48743 -52.35549i
1.85679 +0.89606r
-56.16227 -48.50246r

These initializations imply that the numbers generated are non-split. If we want to gerate split Cayley numbers, then we have to add the line set_split() as in

import Cayley_Calculator
from octonion import *
set_split()

(set_split() is equivalent to set_gamma(gamma1=1,gamma2=1,gamma3=1,gamma4=1,gamma5=1,gamma6=1,gamma7=1). The result are split Cayley numbers. Without this command gamma1=-1,...,gamma7=-1, which results in non split Cayley numbers.

Let's try again with the same values.

a = Octonion(-9, 9, -9, 2, 10, -5, -9, 6)
b = Octonion(-3, 7, 3, 6, 1, -6, 4, -7)
a*b,b*a
# (Octonion( 25, -14, 62, 32, -17, -9, 75, -43), Octonion( 25, -166, -62, -152, -61, 147, -93, 133))
a._gamma
# [1, 1, 1, 1, 1, 1, 1]

When a Cayley number is generated, it stores the actual gamma as an attribute as in a._gamma.

(Note: The last values in the corresponding results of a*b and b*a are always equal to the values for non split Cayley numbers. Why?)

Each single initialization makes all classes Complex, Quaternion, Octonion, Sedenion, Pathion, Chingon, Routon accessible.

Functionality

  • Arithmetic

    After initialization of Cayley_Calculator addition, subtraction, right and left multiplication, right and left division (as far as possible) and the power function are definied. This allows standard notation. Calculations like (1+2j)*Octonion(3,4,5,6,7) or OO(1,2,3)/PP(*range(32)) (same as Octonion(1,2,3,0,0,0,0,0)/Pathion(0,1,2,...,31)) are possible. If numpy.quaternion is installed a calculation like quaternion(1,2,3,0)*OO(*range(1,9)) is possible. The result should be Octonion(-12, 16, -2, 4, -28, -8, 38, 12) (for the non split case).

    We have two sorts of division: (a/b)*b = a = b*(a//b) = a. Note that (a*b)/b = a and (a*b)//a = b hold true also (if a resp. b is no zero divisor). Division by zero divisors is not implemented, but should be possible sometimes by replacing numpy.linalg.solve by something more appropriate for ill-conditioned systems.

    As usual a**b is the power of a by b. Often the power is not defined if the norm N(a) is not positive (possible for split Cayley numbers), except for integer b. If N(a) > 0 then we have (approximately) (a**b)**(1/b) = a. (Implemented are calculations with polar coordinates which solves partially the problem with multivalued log. The module cmath does not implement this algorithm.) Remark: For equality in (a**b)**(1/b) = a b must be an element in an alternative algebra, like reals, complex, quaternion or octonions. Is b is a Sedenion, then equality no longer holds true.

    getitem and setitem methods are available for Cayley numbers. a.z1 gets/sets the first part of a, a.z2 the second. Thus

    from octonion import *
    set_split()
    a = Octonion( 2, 4, -8, -5, 10, 10, -8, -4)
    a.z1
    # Quaternion( 2, 4, -8, -5)
    a.z2 = -a.z1
    a
    # Octonion( 2, 4, -8, -5, -2, -4, 8, 5)
    print(a*a.conj)
    # 0
    a[1:8:2] = -a[:8:2]
    a
    # Octonion( 2, -2, -8, 8, -2, 2, 8, -8)
    print(a*a.conj)
    # 0
    

    Here a.conj is the conjugation.

  • Functions

    1. Standard functions known for the fields R and C are extended to Cayley Numbers. We get the functions exp, sin, cos, tan, sinh, cosh and tanh and their inverses log, arcsin, arccos, arctan, arsinh, arcosh, artanh, further sqrt, pow, norm (the l2-norm). All these functions return values of the same type as the input. Note that some of these don't return a valid value, if the argument is split. Often these functions are implemented as methods. As an example, a.sin() and sin(a) return the same value.

    2. The function sedenize extends functions f : C -> C to functions f : B -> B, where B is some non split Cayley algebra. Example:

    from octonion import *
    a = Octonion(1,2,3,4,5)
    ssin = sedenize(cmath.sin)
    sin(a) # implemented sin
    ssin(a) # sedenized sin
    series.sin(a) # Taylor series of sin
    # Always Octonion(653.74588161, 114.24557755, 171.36836632, 228.4911551 , 285.61394387, 0, 0, 0)
    

    Note: series is a module, which (for testing) computes some functions the resulting value with Taylor series (slow).

    Attentition This extension does not make sense for function f without f(R) c R. Example: If f(x) = 1j*x, then sedenize(f)(x) != 1j*x for x in B. Maybe we need additional assumptions which imply that sedenize(f) makes sense.

    1. Similar, for split Cayley numbers (after set_split()) there is split_sedenize, which extends functions f : R -> R to functions f : B -> B, where B now is some split Cayley algebra. Example:
    from octonion import *
    set_split()
    a = Octonion(1,2,3,4,5)
    ssin = split_sedenize(math.sin)
    sin(a) # implemented sin
    ssin(a) # sedenized sin
    series.sin(a) # Taylor series of sin
    # Always Octonion(-0.01848834, -0.23033006, -0.34549509, -0.46066012, -0.57582515, 0, 0, 0)
    
    1. There are random generators randinteger(a,b,n=1,Class=CLASS) and uniform(a,b,n=1,Class=CLASS), which generate n random Cayley numbers of class CLASS with integer resp. real values. After starting with from sedenion import * randinteger(a,b,Class=Sedenion) and randinteger(a,b) have the same effect. Similarly, random_ball(r=1,n=1,Class=CLASS) gerates random Cayley numbers in the ball with radius r.
  • Linear Algebra

    After initialization a class Operator exist. from octonion import * actually initializes two generators self.left_matrix() and self.right_matrix() for each class of Cayley numbers. Try

    a = Octonion(*range(1,9))
    a.left_matrix()
    a.right_matrix()
    

    Fast left and right multiplication is done with these generators. Essentially a * b is a.__class__(array = a.left_matrix().array @ b._list). Even these simple operators allow solving the equation a*x+x*a = b with (a.left_matrix()+a.right_matrix()).solve(b). (Note that a*x+x*a and 2*a*x are different.)

    More linear algebra is available with

    from linear_octonion import *
    

    (or linear_pathion, linear_chingon, etc.) As a simple example try

    from linear_octonion import *
    A = random_operator(5,5)
    b = random_matrix(5)
    x = solve(A,b)
    A @ x - b
    

    The result is an array of 5 Octonions of value 0. Here random_operator(5,5) generates a random 5 x 5 - array of Octonion-Operators, random_matrix(5) a random 5-array of Octonions, x = solve(A,b) solves the equation A * x = b. Note that the coefficients all are Octonions.

    To solve a system of equations like a*x + c*(y*b) = d, g*(x*f) + u*y = h, where a,b,c,d,f,g,h,u are known Octonions (maybe generated with a,b,c,d,f,g,h,u = randinteger(-10,11,8), we can proceed like

    L = lambda a : a.left_matrix()
    R = lambda a : a.right_matrix()
    A = np.zeros((2,2),dtype = object)
    A[0,0] = L(a)
    A[0,1] = L(c)*R(b) # first multiplication from right with `b`, then from left with `c` (order matters)
    A[1,0] = L(g)*R(f)
    A[1,1] = L(u)
    v = np.array(((d),(h))) # v now is a column vector of dtype object
    w = solve(A,v)
    

    Then with x = w[0] and y = w[1] the equations hold true.

    Remark: There are more routines in this paket, probably mostly not of general interest. As an example, rankalg([a,b]) computes the rank of the algebra generated by the elements a and b. You are free to search through the files.

  • Analysis You can always do simple analysis with Cayley Calculator.

    An example is finding roots of functions f : B -> B.

    from octonion import *
    a = Octonion( -9, -5, 3, -10, -8, -4, 6, 9)
    b = Octonion(-1, 4, 9, -8, -7, 7, 10, 10)
    c = Octonion( 6, -4, 1, 6, 2, -9, -8, -5)
    f = lambda x: x**3+a*x**2+b*x+c
    u = root(f)
    u
    # Octonion( 0.46409658, 0.09019479, 0.25877159, -0.07301889, 0.04045148, 0.03196905, 0.03334842, 0.00237735)
    f(u)
    # Octonion( 0, 0, 0, 0, 0, 0, 0, 0)
    

    This solves the polynomial equation x**3 + a*x**2 + b*x + c = 0. Note that the multilplication is neither commutative nor associative. Actually root(f) is the same as root(f,x0 = 0). To find other solutions you have to change the starting value, as in

    v = root(f,2.7-50j)
    v
    # Octonion( 9.65076995, 4.91561477, -3.68071099, 10.16854247, 8.29879297, 3.9619796 , -6.07204099, -8.89880019)
    

About me

I have been a mathematician (retired) at the KIT in Karlsruhe, Germany. I have studied physics as well. Programming, particularly in python, is a hobby, not a profession.

Metadata

Release files for Cayley-Calculator 1.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Cayley-Calculator 1.3.1
File Size Uploaded
cayley_calculator-1.3.1.tar.gz 57.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for Cayley-Calculator 1.3.1
File Interpreter ABI Platform
cayley_calculator-1.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 142.8 kB

Release files / cayley_calculator-1.3.1.tar.gz

Download URL cayley_calculator-1.3.1.tar.gz
Size 57.6 kB
Tags Source
SHA-256 checksum
How to use checksums
65922fc90cc0d8159830e5d90424cb7cda6c6306824bea628542c647f364d55b
BLAKE2b-256 checksum
How to use checksums
ceac900ec61f84527a9c1330aa3c23f748ea8e0930b303702e500175a5c018f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / cayley_calculator-1.3.1-py3-none-any.whl

Download URL cayley_calculator-1.3.1-py3-none-any.whl
Size 85.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
149ead539e0bedf62b54996afc14060092c16f26468d74533ff1813968875b7e
BLAKE2b-256 checksum
How to use checksums
95d353b84210cf2f79139476464f0af85618df7d117408053fe9d20d7b21b826
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

This release

1.3.1 This release

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page