Source code for qhronology.utilities.symbolics

# Project: Qhronology (https://github.com/lgbishop/qhronology)
# Author: lgbishop <lgbishop@protonmail.com>
# Copyright: Lachlan G. Bishop 2025
# License: AGPLv3 (non-commercial use), proprietary (commercial use)
# For more details, see the README in the project repository:
# https://github.com/lgbishop/qhronology,
# or visit the website:
# https://qhronology.org.

"""
A mixin for symbolic algebra.
Not intended to be used directly by the user.
"""

# https://peps.python.org/pep-0649/
# https://peps.python.org/pep-0749/
from __future__ import annotations

from typing import Any

import sympy as sp

from qhronology.utilities.classification import num, sym


[docs] class SymbolicsProperties: """A mixin for endowing derived classes with algebraic symbolism. Not intended to be instantiated itself, but rather indirectly via the constructor in its child classes. """ def __init__( self, symbols: dict[sym | str, dict[str, Any]] | None = None, conditions: list[tuple[num | expr | str, num | expr | str]] | None = None, ): symbols = {} if symbols is None else symbols conditions = [] if conditions is None else conditions self.symbols = symbols self.conditions = conditions @property def symbols(self) -> dict[sym | str, dict[str, Any]]: """A dictionary in which the keys are individual symbols (contained within the object's matrix representation) and the values are dictionaries of their respective SymPy keyword-argument :python:`assumptions` ("predicates"). A full list of currently supported predicates, and their defaults, is as follows: - :python:`"algebraic"`: :python:`True` - :python:`"commutative"`: :python:`True` - :python:`"complex"`: :python:`True` - :python:`"extended_negative"`: :python:`False` - :python:`"extended_nonnegative"`: :python:`True` - :python:`"extended_nonpositive"`: :python:`False` - :python:`"extended_nonzero"`: :python:`True` - :python:`"extended_positive"`: :python:`True` - :python:`"extended_real"`: :python:`True` - :python:`"finite"`: :python:`True` - :python:`"hermitian"`: :python:`True` - :python:`"imaginary"`: :python:`False` - :python:`"infinite"`: :python:`False` - :python:`"integer"`: :python:`True` - :python:`"irrational"`: :python:`False` - :python:`"negative"`: :python:`False` - :python:`"noninteger"`: :python:`False` - :python:`"nonnegative"`: :python:`True` - :python:`"nonpositive"`: :python:`False` - :python:`"nonzero"`: :python:`True` - :python:`"positive"`: :python:`True` - :python:`"rational"`: :python:`True` - :python:`"real"`: :python:`True` - :python:`"transcendental"`: :python:`False` - :python:`"zero"`: :python:`False` """ return dict(self._symbols) @symbols.setter def symbols(self, symbols: dict[sym | str, dict[str, Any]]): self._symbols = symbols # self.symbols_list = symbols_list @property def symbols_list(self) -> list[sym]: symbols_list = [] for key, value in self.symbols.items(): symbol = sp.Symbol(str(key), **value) symbols_list.append(symbol) return list(symbols_list) @property def conditions(self) -> list[tuple[num | expr | str, num | expr | str]]: """A list of :math:`2`-tuples of conditions to be applied to the object's matrix representation.""" return list(self._conditions) @conditions.setter def conditions(self, conditions): self._conditions = conditions