Module Documentation

Algebra

class kingdon.algebra.Algebra(p: int = 0, q: int = 0, r: int = 0, signature: List[int] = None, start_index: int = None, basis: List[str] = <factory>, registry: dict = <factory>, numspace: dict = <factory>, cse: bool = True, graded: bool = False, pretty_blade: str = '𝐞', large: bool = None, wrapper: Callable = None, codegen_symbolcls: object = None, simp_func: Callable = <function Algebra.<lambda>>)[source]

A Geometric (Clifford) algebra with p positive dimensions, q negative dimensions, and r null dimensions.

The default settings of cse = simplify = True usually strike a good balance between initiation times and subsequent code execution times.

Parameters:
  • p – number of positive dimensions.

  • q – number of negative dimensions.

  • r – number of null dimensions.

  • signature – Optional signature of the algebra, e.g. [0, 1, 1] for 2DPGA. Mutually exclusive with p, q, r.

  • start_index – Optionally set the start index of the dimensions. For PGA this defualts to 0, otherwise 1.

  • basis – Custom basis order, e.g. [“e”, “e1”, “e2”, “e0”, “e20”, “e01”, “e12”, “e012”] for 2DPGA.

  • cse – If True (default), attempt Common Subexpression Elimination (CSE) on symbolically optimized expressions.

  • graded – If True (default is False), perform binary and unary operations on a graded basis. This will still be more sparse than computing with a full multivector, but not as sparse as possible. It does however, vastly reduce the number of possible expressions that have to be symbolically optimized.

  • simplify – If True (default), we attempt to simplify as much as possible. Setting this to False will reduce the number of calls to simplify. However, it seems that True is still faster, probably because it keeps sympy expressions from growing too large, which makes both symbolic computations and printing into a python function slower.

  • wrapper – A function that is always applied to the generated functions as a decorator. For example, using numba.njit as a wrapper will ensure that all kingdon code is jitted using numba.

  • codegen_symbolcls – The symbol class used during codegen. By default, this is our own fast RationalPolynomial class.

  • simp_func – This function is applied as a filter function to every multivector coefficient.

  • pretty_blade – character to use for basis blades when pretty printing to string. Default is 𝐞.

  • large – if true this is considered a large algebra. This means various cashing options are removed to save memory, and codegen is replaced by direct computation since codegen is very resource intensive for big expressions. By default, algebras of \(d > 6\) are considered large, but the user can override this setting because also in large algebras it is still true that the generated code will perform order(s) of magnitude better than direct computation.

acp: OperatorDict
add: OperatorDict
basis: List[str]
bin2canon: dict
bivector(*args, **kwargs) MultiVector[source]
blades: BladeDict
canon2bin: dict
property cayley

Cayley table of the algebra.

codegen_symbolcls: object = None
conjugate: UnaryOperatorDict
cp: OperatorDict
cse: bool = True
d: int
div: OperatorDict
evenmv(*args, **kwargs) MultiVector[source]

Create a new MultiVector in the even subalgebra.

property frame: list

The set of orthogonal basis vectors, \(\{ e_i \}\). Note that for a frame linear independence suffices, but we already have orthogonal basis vectors so why not use those?

classmethod fromname(name: str, **kwargs)[source]

Initialize a well known algebra by its name. Options are 2DPGA, 3DPGA, and STAP. This uses sensible ordering of the basis vectors in the basis blades to avoid minus superfluous signs.

gp: OperatorDict
graded: bool = False
graph(*subjects, graph_widget=<class 'kingdon.graph.GraphWidget'>, **options)[source]

The graph function outputs ganja.js renders and is meant for use in jupyter notebooks. The syntax of the graph function will feel familiar to users of ganja.js: all position arguments are considered as subjects to graph, while all keyword arguments are interpreted as options to ganja.js’s Algebra.graph method.

Example usage:

alg.graph(
    0xD0FFE1, [A,B,C],
    0x224488, A, "A", B, "B", C, "C",
    lineWidth=3, grid=1, labels=1
)

Will create

_images/graph_triangle.png

If a function is given to Algebra.graph then it is called without arguments. This can be used to make animations in a manner identical to ganja.js.

Example usage:

def graph_func():
    return [
        0xD0FFE1, [A,B,C],
        0x224488, A, "A", B, "B", C, "C"
    ]

alg.graph(
    graph_func,
    lineWidth=3, grid=1, labels=1
)
Parameters:
  • *subjects – Subjects to be graphed. Can be strings, hexadecimal colors, (lists of) MultiVector, (lists of) callables.

  • camera – [optional] a motor that places the camera at the desired viewpoint.

  • up – [optional] the ‘up’ (C) function that takes a Euclidean point and casts it into a larger embedding space. This will invoke ganja’s OPNS renderer, which can be used to render any algebra. Examples include 2D CSGA, 3D CCGA, 3D Mother Algebra, etc. See the teahouse for examples.

  • **options – Other options passed to ganja.js’s Algebra.graph.

hodge: UnaryOperatorDict
indices_for_grade(grade: int)[source]

Function that returns a generator for all the indices for a given grade. E.g. in 2D VGA, this returns

>>> alg = Algebra(2)
>>> tuple(alg.indices_for_grade(1))
(1, 2)
indices_for_grades(grades: Tuple[int])[source]

Function that returns a generator for all the indices from a sequence of grades. E.g. in 2D VGA, this returns

>>> alg = Algebra(2)
>>> tuple(alg.indices_for_grades((1, 2)))
(1, 2, 3)
inv: UnaryOperatorDict
involute: UnaryOperatorDict
ip: OperatorDict
large: bool = None
lc: OperatorDict
property matrix_basis
multivector(*args, **kwargs) MultiVector[source]

Create a new MultiVector.

neg: UnaryOperatorDict
normsq: UnaryOperatorDict
numspace: dict
oddmv(*args, **kwargs) MultiVector[source]

Create a new MultiVector of odd grades. (There is technically no such thing as an odd subalgebra, but otherwise this is similar to evenmv.)

op: OperatorDict
outercos: UnaryOperatorDict
outerexp: UnaryOperatorDict
outersin: UnaryOperatorDict
outertan: UnaryOperatorDict
p: int = 0
polarity: UnaryOperatorDict
pretty_blade: str = '𝐞'
pretty_digits: dict
proj: OperatorDict
pseudobivector(*args, **kwargs) MultiVector[source]
pseudoquadvector(*args, **kwargs) MultiVector[source]
pseudoscalar(*args, **kwargs) MultiVector[source]
pseudotrivector(*args, **kwargs) MultiVector[source]
pseudovector(*args, **kwargs) MultiVector[source]
pss: object
purevector(*args, grade, **kwargs) MultiVector[source]

Create a new MultiVector of a specific grade.

Parameters:

grade – Grade of the mutivector to create.

q: int = 0
quadvector(*args, **kwargs) MultiVector[source]
r: int = 0
rc: OperatorDict
property reciprocal_frame: list

The reciprocal frame is a set of vectors \(\{ e^i \}\) that satisfies \(e^i \cdot e_j = \delta^i_j\) with the frame vectors \(\{ e_i \}\).

register(expr=None, /, *, name=None, symbolic=False)[source]

Register a function with the algebra to optimize its execution times.

The function must be a valid GA expression, not an arbitrary python function.

Example:

@alg.register
def myexpr(a, b):
    return a @ b

@alg.register(symbolic=True)
def myexpr(a, b):
    return a @ b

With default settings, the decorator will ensure that every GA unary or binary operator is replaced by the corresponding numerical function, and produces numerically much more performant code. The speed up is particularly notible when e.g. self.wrapper=numba.njit, because then the cost for all the python glue surrounding the actual computation has to be paid only once.

When symbolic=True the expression is symbolically optimized before being turned into a numerical function. Beware that symbolic optimization of longer expressions (currently) takes exorbitant amounts of time, and often isn’t worth it if the end goal is numerical computation.

Parameters:
  • expr – Python function of a valid kingdon GA expression.

  • name – (optional) name by which the function will be known to the algebra. By default, this is the expr.__name__.

  • symbolic – (optional) If true, the expression is symbolically optimized. By default this is False, given the cost of optimizing large expressions.

registry: dict
reverse: UnaryOperatorDict
rp: OperatorDict
scalar(*args, **kwargs) MultiVector[source]
signature: List[int] = None
signs: dict
simp_func()
sp: OperatorDict
sqrt: UnaryOperatorDict
start_index: int = None
sub: OperatorDict
sw: OperatorDict
trivector(*args, **kwargs) MultiVector[source]
unhodge: UnaryOperatorDict
unpolarity: UnaryOperatorDict
vector(*args, **kwargs) MultiVector[source]
wrapper: Callable = None
class kingdon.algebra.BladeDict(algebra: Algebra, lazy: bool = False)[source]

Dictionary of basis blades. Use getitem or getattr to retrieve a basis blade from this dict, e.g.:

alg = Algebra(3, 0, 1)
blade_dict = BladeDict(alg, lazy=True)
blade_dict['e03']
blade_dict.e03

When lazy=True, the basis blade is only initiated when requested. This is done for performance in higher dimensional algebras.

algebra: Algebra
blades: dict
grade(*grades) dict[source]

Return blades of grade grades.

Parameters:

grades – tuple or ints, grades to select.

lazy: bool = False
class kingdon.algebra.DefaultKeyDict(factory)[source]

A lightweight dict subclass that behaves like a defaultdict but calls the factory function with the key as argument.

MultiVector

class kingdon.multivector.MultiVector(algebra: 'Algebra', values=None, keys=None, *, name=None, grades=None, symbolcls=<class 'sympy.core.symbol.Symbol'>, **items)[source]
acp(other)[source]

Calculate the anti-commutator product of x := self and y := other: x.cp(y) = 0.5*(x*y+y*x).

add(other)[source]
algebra: Algebra
asfullmv(canonical=True)[source]

Returns a full version of the same multivector.

Parameters:

canonical – If True (default) the values are in canonical order, even if the mutivector was already dense.

asmatrix()[source]

Returns a matrix representation of this multivector.

conjugate()[source]

Clifford conjugation: involution and reversion combined.

cp(other)[source]

Calculate the commutator product of x := self and y := other: x.cp(y) = 0.5*(x*y-y*x).

div(other)[source]
dual(kind='auto')[source]

Compute the dual of self. There are three different kinds of duality in common usage. The first is polarity, which is simply multiplying by the inverse PSS from the right. This is the only game in town for non-degenerate metrics (Algebra.r = 0). However, for degenerate spaces this no longer works, and we have two popular options: Poincaré and Hodge duality.

By default, kingdon will use polarity in non-degenerate spaces, and Hodge duality for spaces with Algebra.r = 1. For spaces with r > 2, little to no literature exists, and you are on your own.

Parameters:

kind – if ‘auto’ (default), kingdon will try to determine the best dual on the basis of the signature of the space. See explenation above. To ensure polarity, use kind='polarity', and to ensure Hodge duality, use kind='hodge'.

exp(cosh=None, sinhc=None, sqrt=None)[source]

Calculate the exponential of simple elements, meaning an element that squares to a scalar. Works for python float, int and complex dtypes, and for symbolic expressions using sympy. For more control, it is possible to explicitly provide a cosh, sinhc, and sqrt function. If you provide one, you must provide all.

The argument to sqrt is the scalar \(s = \langle x^2 \rangle_0\), while the input to the cosh and sinhc functions is the output of the sqrt function applied to \(s\).

For example, for a simple rotation kingdon’s implementation is equivalent to

alg = Algebra(2)
x = alg.bivector(e12=1)
x.exp(
    cosh=np.cos,
    sinhc=np.sinc,
    sqrt=lambda s: (-s)**0.5,
)
filter(func=None) MultiVector[source]

Returns a new multivector containing only those elements for which func was true-ish. If no function was provided, use the simp_func of the Algebra. If func has one argument, it is called on each entry of self.values(). If func has two arguments, the function is called with the key, value pairs as per self.items() instead.

property free_symbols: set
classmethod fromkeysvalues(algebra, keys, values)[source]

Initiate a multivector from a sequence of keys and a sequence of values.

classmethod frommatrix(algebra, matrix)[source]

Initiate a multivector from a matrix. This matrix is assumed to be generated by asmatrix, and thus we only read the first column of the input matrix.

gp(other)[source]
grade(*grades)[source]

Returns a new MultiVector instance with only the selected grades from self.

Parameters:

grades – tuple or ints, grades to select.

property grades

Tuple of the grades present in self.

hodge()[source]
inv()[source]

Inverse of this multivector.

involute()[source]

Main grade involution.

ip(other)[source]
property issymbolic

True if this mv contains Symbols, False otherwise.

items()[source]
itermv(axis=None) Generator[MultiVector, None, None][source]

Deprecated, do for x in mv: instead.

Returns an iterator over the multivectors within this multivector, if it is a multidimensional multivector. For example, if you have a pointcloud of N points, itermv will iterate over these points one at a time.

Parameters:

axis – Axis over which to iterate. Default is to iterate over all possible mv.

keys()[source]
lc(other)[source]
map(func) MultiVector[source]

Returns a new multivector where func has been applied to all the values. If func has one argument, it is called on each entry of self.values(). If func has two arguments, the function is called with the key, value pairs as per self.items() instead.

neg()[source]
norm()[source]
normalized()[source]

Normalized version of this multivector.

normsq()[source]
op(other)[source]
outercos()[source]
outerexp()[source]
outersin()[source]
outertan()[source]
polarity()[source]
proj(other)[source]

Project x := self onto y := other: x @ y = (x | y) * ~y. For correct behavior, x and y should be normalized (k-reflections).

rc(other)[source]
reverse()[source]

Reversion

rp(other)[source]
property shape: tuple

Return the shape of the .values() attribute of this multivector.

sp(other)[source]

Scalar product: \(\langle x \cdot y \rangle\).

sqrt()[source]
sub(other)[source]
sw(other)[source]

Apply the normalized versor (k-reflection) x := self to the \(\ell\)-blade:code:y := other under conjugation: \(x[y] = (-1)^{k \ell} x y x^{-1}\). If y is a multivector instead of a blade, the formula is applied to each pure grade component of y separately to ensure a consistent result. Important: note that x is assumed to be normalized such that \(x \widetilde{x} = 1\) (i.e. x.normsq() == 1). Moreover, grade preservation is enforced by the code. Expect unexpected results if this operator is used with non-versors.

property type_number: int
undual(kind='auto')[source]

Compute the undual of self. See dual for more information.

unhodge()[source]
unpolarity()[source]
values()[source]

Codegen

The codegen module generates python functions from operations between/on purely symbolic MultiVector objects.

As a general rule, these functions take in pure symbolic MultiVector objects and return a tuple of keys present in the output, and a pure python function which represents the respective operation.

E.g. codegen_gp() computes the geometric product between two multivectors for the specific non-zero basis blades present in the input.

class kingdon.codegen.CodegenOutput(keys_out: Tuple[int], func: Callable)[source]

Output of a codegen function.

Parameters:
  • keys_out – tuple with the output blades in binary rep.

  • func – callable that takes (several) sequence(s) of values returns a tuple of len(keys_out).

func: Callable

Alias for field number 1

keys_out: Tuple[int]

Alias for field number 0

class kingdon.codegen.Fraction(numer, denom)

Tuple representing a fraction.

denom

Alias for field number 1

numer

Alias for field number 0

class kingdon.codegen.KingdonPrinter(printer=None, dummify=False)[source]
doprint(funcname, args, names, expr, *, cses=())[source]

Returns the function definition code as a string.

kingdon.codegen.codegen_acp(x, y)[source]

Generate the anti-commutator product of x and y: x.acp(y) = 0.5*(x*y+y*x).

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_add(x, y)[source]
kingdon.codegen.codegen_conjugate(x)[source]
kingdon.codegen.codegen_cp(x, y)[source]

Generate the commutator product of x and y: x.cp(y) = 0.5*(x*y-y*x).

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_div(x, y)[source]

Generate code for \(x y^{-1}\).

kingdon.codegen.codegen_gp(x, y)[source]

Generate the geometric product between x and y.

Parameters:
Returns:

tuple with integers indicating the basis blades present in the product in binary convention, and a lambda function that perform the product.

kingdon.codegen.codegen_hitzer_inv(x, symbolic=False)[source]

Generate code for the inverse of x using the Hitzer inverse, which works up to 5D algebras.

kingdon.codegen.codegen_hodge(x, undual=False)[source]
kingdon.codegen.codegen_inv(y, symbolic=False)[source]
kingdon.codegen.codegen_involute(x)[source]
kingdon.codegen.codegen_involutions(x, invert_grades=(2, 3))[source]

Codegen for the involutions of Clifford algebras: reverse, grade involute, and Clifford involution.

Parameters:

invert_grades – The grades that flip sign under this involution mod 4, e.g. (2, 3) for reversion.

kingdon.codegen.codegen_ip(x, y, diff_func=<built-in function abs>)[source]

Generate the inner product of x and y.

Parameters:

diff_func – How to treat the difference between the binary reps of the basis blades. if abs, compute the symmetric inner product. When lambda x: -x this function generates left-contraction, and when lambda x: x, right-contraction.

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_lc(x, y)[source]

Generate the left-contraction of x and y.

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_neg(x)[source]
kingdon.codegen.codegen_normsq(x)[source]
kingdon.codegen.codegen_op(x, y)[source]

Generate the outer product of x and y: x.op(y) = x ^ y.

X:

MultiVector

Y:

MultiVector

Returns:

dictionary with integer keys indicating the corresponding basis blade in binary convention, and values which are a 3-tuple of indices in x, indices in y, and a lambda function.

kingdon.codegen.codegen_outercos(x)[source]
kingdon.codegen.codegen_outerexp(x, asterms=False)[source]
kingdon.codegen.codegen_outersin(x)[source]
kingdon.codegen.codegen_outertan(x)[source]
kingdon.codegen.codegen_polarity(x, undual=False)[source]
kingdon.codegen.codegen_product(x, y, filter_func=None, sign_func=None, keyout_func=<built-in function xor>)[source]

Helper function for the codegen of all product-type functions.

Parameters:
  • x – Fully symbolic MultiVector.

  • y – Fully symbolic MultiVector.

  • filter_func – A condition which should be true in the preprocessing of terms. Input is a TermTuple.

  • sign_func – function to compute sign between terms. E.g. algebra.signs[ei, ej] for metric dependent products. Input: 2-tuple of blade indices, e.g. (ei, ej).

  • keyout_func

kingdon.codegen.codegen_proj(x, y)[source]
kingdon.codegen.codegen_rc(x, y)[source]

Generate the right-contraction of x and y.

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_reverse(x)[source]
kingdon.codegen.codegen_rp(x, y)[source]

Generate the regressive product of x and y:, \(x \vee y\).

Parameters:
  • x

  • y

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_shirokov_inv(x, symbolic=False)[source]

Generate code for the inverse of x using the Shirokov inverse, which is works in any algebra, but it can be expensive to compute.

kingdon.codegen.codegen_sp(x, y)[source]

Generate the scalar product of x and y.

Returns:

tuple of keys in binary representation and a lambda function.

kingdon.codegen.codegen_sqrt(x)[source]

Take the square root using the study number approach as described in https://doi.org/10.1002/mma.8639

kingdon.codegen.codegen_sub(x, y)[source]
kingdon.codegen.codegen_sw(x, y)[source]

Generate the conjugation of y by the versor (k-reflection) x, using the conjugation formula \((-1)^{k \ell} x y x^{-1}\), where \(k\) is the grade of x and \(\ell\) is the grade of the blade y. (Eq 7.18 in [GA4CS]) If y is a multivector instead of a blade, the formula is applied to each pure grade component of y separately to ensure a consistent result. Important: note that x is assumed to be normalized such that \(x \widetilde{x} = 1\) (i.e. x.normsq() == 1). Moreover, grade preservation is enforced by the code. Expect unexpected results if this operator is used with non-versors.

[GA4CS]

Dorst, Lasenby, and Fontijne. Geometric Algebra for Computer Science. Morgan Kaufmann, 2007.

Parameters:
  • x – The versor (k-reflection), i.e. a multivector satisfying \(x \widetilde{x} = 1\).

  • y – The multivector to be conjugated.

Returns:

tuple of keys in binary representation and a lambda function.

Raises:

TypeError – If x is not a versor (k-reflection) and thus neither even nor odd.

kingdon.codegen.codegen_unhodge(x)[source]
kingdon.codegen.codegen_unpolarity(x)[source]
kingdon.codegen.do_codegen(codegen, *mvs) CodegenOutput[source]
Parameters:
  • codegen – callable that performs codegen for the given mvs. This can be any callable that returns either a MultiVector, a dictionary, or an instance of CodegenOutput.

  • mvs – Any remaining positional arguments are taken to be symbolic MultiVector’s.

Returns:

Instance of CodegenOutput.

kingdon.codegen.do_compile(codegen, *tapes)[source]
kingdon.codegen.func_builder(res_vals: defaultdict, *mvs, funcname: str) CodegenOutput[source]

Build a Python function for the product between given multivectors.

Parameters:
  • res_vals – Dict to be converted into a function. The keys correspond to the basis blades in binary, while the values are strings to be converted into source code.

  • mvs – all the multivectors that the resulting function is a product of.

  • funcname – Name of the function. Be aware: if a function by that name already existed, it will be overwritten.

Returns:

tuple of output keys of the callable, and the callable.

kingdon.codegen.lambdify(args: dict, exprs: list, funcname: str, printer=None, func_printer=None, dummify=False, cse=False)[source]

Function that turns symbolic expressions into Python functions. Heavily inspired by sympy’s function by the same name, but adapted for the needs of kingdon.

Particularly, this version gives us more control over the names of the function and its arguments, and is more performant, particularly when the given expressions are strings.

Example usage:

alg = Algebra(2)
a = alg.multivector(name='a')
b = alg.multivector(name='b')
args = {'A': a.values(), 'B': b.values()}
exprs = tuple(codegen_cp(a, b).values())
func = lambdify(args, exprs, funcname='cp', cse=False)

This will produce the following code:

def cp(A, B):
    [a, a1, a2, a12] = A
    [b, b1, b2, b12] = B
    return (+a1*b2-a2*b1,)

Note

As a kingdon end user, you should probably not need to call this functon directly, be sure to check out register() first. And even for experienced users or kingdon developers it is recommended to use do_codegen() which provides a clean API around this function.

Parameters:
  • args – dictionary of type dict[str | Symbol, tuple[Symbol]].

  • exprs – tuple[Expr]

  • funcname – string to be used as the bases for the name of the function.

  • printer – Instance of the sympy style printer used to print individual sympy expressions.

  • func_printer – Instance of the sympy style printer used to generate functions using the printer.

  • cse – If True (default), CSE is applied to the expressions. This typically greatly improves performance and reduces numba’s initialization time.

Returns:

Function that represents that can be used to calculate the values of exprs.

Operator dicts

exception kingdon.operator_dict.AlgebraError[source]
class kingdon.operator_dict.OperatorDict(name: str, codegen: Callable, algebra: Algebra, codegen_symbolcls: Callable = <bound method RationalPolynomial.fromname of <class 'kingdon.polynomial.RationalPolynomial'>>)[source]

A dict-like object which performs codegen of a particular operator, and caches the result for future use. For example, to generate the geometric product, we create an OperatorDict as follows:

alg = Algebra(3, 0, 1)
gp = OperatorDict('gp', codegen=codegen_gp, algebra=alg)

Here, codegen_gp is a function that outputs the keys of the result, and a callable that produces the corresponding values. See CodegenOutput for more info.

algebra: Algebra
codegen: Callable
classmethod codegen_symbolcls(name)
filter(keys_out, values_out)[source]

For given keys and values, keep only symbolically non-zero elements.

name: str
operator_dict: dict
class kingdon.operator_dict.Registry(name: str, codegen: Callable, algebra: Algebra, codegen_symbolcls: Callable = <bound method RationalPolynomial.fromname of <class 'kingdon.polynomial.RationalPolynomial'>>)[source]
class kingdon.operator_dict.UnaryOperatorDict(name: str, codegen: Callable, algebra: Algebra, codegen_symbolcls: Callable = <bound method RationalPolynomial.fromname of <class 'kingdon.polynomial.RationalPolynomial'>>)[source]

Specialization of OperatorDict for unary operators. In the case of unary operators, we can do away with all of the overhead that is necessary for operators that act on multiple multivectors.

kingdon.operator_dict.do_operation(*mvs, codegen, algebra) MultiVector[source]

This function just does the operation directly on the MV’s, no codegen is performed. This is used for large algebras, where codegen is too costly. The result is the multivector resulting from codegen(*mvs).

kingdon.operator_dict.resolve_and_expand(func)[source]

Decorator which makes func compatible function over MVs compatible with the broader ganja.js style broadcasting rules: - binary and unary operators can be applied to lists & tuples, e.g. x * [y, z] or alg.gp([y, z], x). - binary and unary operators can be applied to functions without any arguments, e.g. x * lambda: y * z or alg.gp(lambda: y * z, x).

Matrix reps

This module contains support functions to turn MultiVector’s into matrices.

This follows the approach outlined in Graded Symmetry Groups: Plane and Simple, section 10. See the paper for more details.

kingdon.matrixreps.expr_as_matrix(expr: Callable, *inputs, res_like: MultiVector = None)[source]

This represents any GA expression as a matrix. To illustrate by example, we might want to represent the multivector equation y = R >> x as a matrix equation y = Ax. (If the multivector x is of pure grade, the matrix A will be in irrep of the transformation.) To obtain A, call this function as follows:

alg = Algebra(3, 0, 1)
R = alg.evenmv(name='R')
x = alg.vector(name='x')
A, y = expr_as_matrix(lambda R, x: R >> x, R, x)

In order to build the matrix rep the input expr is evaluated, so make sure the inputs to the expression are given in the correct order. The last of the positional arguments is assumed to be the vector x in the linear equation y = Ax, and is assumed to be symbolic. The other arguments can also be numeric or e.g. a multidimensional array/torsor, in which case the returned matrix A will be numerical as well. This can e.g. be used to easily generate the matrix representations of a given (dual-)quaternion:

>>> alg = Algebra(3, 0, 1)
>>> R = alg.evenmv(e12=0.25*numpy.pi).exp()
>>> x = alg.vector(name='x')
>>> A, y = expr_as_matrix(lambda R, x: R >> x, R, x)
>>> A
[[ 1.  0.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0. -1.  0.  0.]
 [ 0.  0.  0.  1.]]
Expr:

Callable representing a valid GA expression. Can also be a OperatorDict.

Inputs:

All positional arguments are consider symbolic input arguments to expr. The last of these is assumed to represent the vector x in y = Ax.

Res_like:

(optional) multivector corresponding to the desired output. If None, then the full output is returned. However, if only a subsegment of the output is desired, provide a multivector with the desired shape. In the example above setting, res_like = alg.vector(e1=1) would mean only the e1 component of the matrix is returned. This does not have to be a symbolic multivector, only the keys are checked.

Returns:

This function returns the matrix representation, and the result of applying the expression to the input. If at least one of the inputs other than the last one is symbolic, the result will be a sympy symbolic matrix. Otherwise, the result will be a numpy array.

kingdon.matrixreps.matrix_rep(p=0, q=0, r=0, signature=None)[source]

Create the matrix reps of all the basis blades of an algebra. These are selected such that the entries in the first column of the matrix have positive sign, and thus matrix-matrix multiplication is identical to matrix-vector multiplication.

Parameters:
  • p – number of positive dimensions.

  • q – number of negative dimensions.

  • r – number of null dimensions.

Returns:

sequence of matrix reps for the basis-blades.

kingdon.matrixreps.ordering_matrix(Rs)[source]

Matrix reps are determined up to similarity transform. But not all similarity transforms are equal. This function creates the one similarity transform that gives all entries in the first column of the matrix a positive sign. In doing so, matrix-matrix multiplication is identical to matrix-vector multiplication.

Parameters:

Rs – sequence of matrix reps for all the basis blades of an algebra.

Returns:

The similarity transform to beat all similarity transforms.

Graph

class kingdon.graph.GraphWidget(*args: t.Any, **kwargs: t.Any)[source]
algebra

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

basis

An instance of a Python list.

draggable_points

An instance of a Python list.

draggable_points_idxs

An instance of a Python list.

get_basis
get_draggable_points
get_draggable_points_idxs
get_graded
get_key2idx
get_pre_subjects
get_signature
get_subjects
graded

A boolean (True, False) trait.

inplacereplace(old_subjects, new_subjects: List[Tuple[int, dict]])[source]

Given the old and the new subjects, replace the values inplace iff they have changed.

key2idx

An instance of a Python dict.

One or more traits can be passed to the constructor to validate the keys and/or values of the dict. If you need more detailed validation, you may use a custom validator method.

Changed in version 5.0: Added key_trait for validating dict keys.

Changed in version 5.0: Deprecated ambiguous trait, traits args in favor of value_trait, per_key_traits.

options

An instance of a Python dict.

One or more traits can be passed to the constructor to validate the keys and/or values of the dict. If you need more detailed validation, you may use a custom validator method.

Changed in version 5.0: Added key_trait for validating dict keys.

Changed in version 5.0: Deprecated ambiguous trait, traits args in favor of value_trait, per_key_traits.

pre_subjects

An instance of a Python list.

raw_subjects

An instance of a Python list.

signature

An instance of a Python list.

subjects

An instance of a Python list.

update(*subjects, **options)[source]

Update the subjects and options. Same API as graph(). if no options are provided, then the existing options are kept; if options are provided, then the existing options are replaced.

kingdon.graph.encode(o, tree_types=(<class 'list'>, <class 'tuple'>), root=False, graded=False)[source]
kingdon.graph.walker(encoded_generator, tree_types=(<class 'list'>, <class 'tuple'>))[source]

Rational Polynomial

class kingdon.polynomial.Polynomial(coeff)[source]
classmethod fromname(name)[source]
tosympy()[source]

Return a sympy version of this Polynomial.

class kingdon.polynomial.RationalPolynomial(numer, denom=None)[source]
classmethod fromname(name)[source]
inv()[source]
tosympy()[source]

Return a sympy version of this Polynomial.

kingdon.polynomial.compare(a, b)[source]
class kingdon.polynomial.mathstr[source]

Lightweight string subclass that overloads maths operators to form expressions.

kingdon.polynomial.poly_cse(expr, prot=None, iso=None)[source]

Common Subexpression Elimination for raw polynomial args lists.

Ported from polynomial.js.

Parameters:
  • expr – list of raw polynomial args lists (each [[coeff, var, …], …] or 0). Modified in-place.

  • prot – protected variable names (won’t be combined in products).

  • iso – variable names to use for sum detection and isolation.

Returns:

(prelude, expr) where prelude is a list of assignment strings.

kingdon.polynomial.poly_format(poly_args)[source]

Format a raw polynomial args list (or 0) to a Python code string.

Taperecorder

Used Algebra.register to generate code.

class kingdon.taperecorder.TapeRecorder(algebra, expr, keys)[source]
acp(other, *, operator: str = 'acp')
add(other, *, operator: str = 'add')
algebra: Algebra
binary_operator(other, operator: str)[source]
conjugate(*, operator: str = 'conjugate')
cp(other, *, operator: str = 'cp')
div(other, *, operator: str = 'div')
dual(kind='auto')[source]
expr: str
gp(other, *, operator: str = 'gp')
grade(*grades)[source]
hodge(*, operator: str = 'hodge')
inv(*, operator: str = 'inv')
involute(*, operator: str = 'involute')
ip(other, *, operator: str = 'ip')
keys()[source]
lc(other, *, operator: str = 'lc')
neg(*, operator: str = 'neg')
norm()[source]
normalized()[source]

Normalized version of this multivector.

normsq(*, operator: str = 'normsq')
op(other, *, operator: str = 'op')
outercos(*, operator: str = 'outercos')
outerexp(*, operator: str = 'outerexp')
outersin(*, operator: str = 'outersin')
outertan(*, operator: str = 'outertan')
polarity(*, operator: str = 'polarity')
proj(other, *, operator: str = 'proj')
rc(other, *, operator: str = 'rc')
reverse(*, operator: str = 'reverse')
rp(other, *, operator: str = 'rp')
sp(other, *, operator: str = 'sp')
sqrt(*, operator: str = 'sqrt')
sub(other, *, operator: str = 'sub')
sw(other, *, operator: str = 'sw')
property type_number: int
unary_operator(operator: str)[source]
undual(kind='auto')[source]
unhodge(*, operator: str = 'unhodge')
unpolarity(*, operator: str = 'unpolarity')