Source code for drudge.clifford

"""Drudges for clifford algebra."""

import functools
import itertools
import operator
import typing

from pyspark import RDD
from sympy import Expr, Integer, KroneckerDelta

from .term import Vec, Term
from .wick import WickDrudge


def inner_by_delta(vec1: Vec, vec2: Vec):
    """Compute the inner product of two vectors by delta.

    The two vectors are assumed to be from the same base and have the same
    number of indices, or ValueError will be raised.
    """

    indices1 = vec1.indices
    indices2 = vec2.indices
    if vec1.label != vec2.label or len(indices1) != len(indices2):
        raise ValueError(
            'Invalid vectors to computer inner product by delta', (vec1, vec2)
        )

    return functools.reduce(operator.mul, (
        KroneckerDelta(i, j) for i, j in zip(indices1, indices2)
    ), Integer(1))


[docs]class CliffordDrudge(WickDrudge): r"""Drudge for Clifford algebras. A Clifford algebra over a inner product space :math:`V` is an algebraic system with .. math:: uv + vu = 2 \langle u, v \rangle for all :math:`u, v \in V`. This drudge should work for any Clifford algebra with given inner product function. """ Inner = typing.Callable[[Vec, Vec], Expr]
[docs] def __init__(self, ctx, inner: Inner = inner_by_delta, **kwargs): """Initialize the drudge. Parameters ---------- ctx The context for Spark. inner The callable to compute the inner product of two vectors. By default, the inner product of vectors of the same base and the same number of indices will be computed to be the delta, or ``ValueError`` will be raised. kwargs All other keyword arguments will be forwarded to the base class :py:class:`WickDrudge`. """ super().__init__(ctx, **kwargs) self._inner = inner self._contractor = functools.partial( _contract4clifford, inner=inner ) self._collapse = functools.partial( _collapse4clifford, inner=inner )
@property def phase(self): """The phase for Clifford algebra, negative unity.""" return Integer(-1) @property def comparator(self): """Comparator for Clifford algebra. Here we just compare vectors by the default sort key for vectors. """ return _compare_by_sort_key @property def contractor(self): """Contractor for Clifford algebra. The inner product function will be invoked. """ return self._contractor
[docs] def normal_order(self, terms: RDD, **kwargs): """Put vectors in Clifford algebra in normal-order. After the normal-ordering by Wick expansion, adjacent equal vectors will be collapsed by rules of Clifford algebra. """ res = super().normal_order(terms, **kwargs) return res.map(self._collapse)
def _compare_by_sort_key(vec1: Vec, vec2: Vec, _: Term): """Compare the two vectors just by their sort key.""" return vec1.sort_key > vec2.sort_key def _contract4clifford( vec1: Vec, vec2: Vec, _: Term, *, inner ): """Contract two vectors by Clifford rules.""" return inner(vec1, vec2) * Integer(2) def _collapse4clifford(term: Term, *, inner): """Collapse adjacent equal vectors by Clifford algebras.""" vecs = [] amp = term.amp for k, g in itertools.groupby(term.vecs): n_vecs = sum(1 for _ in g) n_inners = n_vecs // 2 n_rem = n_vecs % 2 # Skip inner product computation when it is not needed. if n_inners > 0: amp *= inner(k, k) ** n_inners if n_rem > 0: vecs.append(k) continue return Term(term.sums, amp, tuple(vecs))