Source code for algebraixlib.mathobjects.atom

r"""Provide the class :class:`Atom` that represents :term:`atom`\s and the function
:func:`auto_convert` that passes through instances of `MathObject`\s and converts other types into
:class:`Atom` instances.
"""

# $Id: atom.py 22702 2015-07-28 20:20:56Z jaustell $
# Copyright Algebraix Data Corporation 2015 - $Date: 2015-07-28 15:20:56 -0500 (Tue, 28 Jul 2015) $
#
# This file is part of algebraixlib <http://github.com/AlgebraixData/algebraixlib>.
#
# algebraixlib is free software: you can redistribute it and/or modify it under the terms of version
# 3 of the GNU Lesser General Public License as published by the Free Software Foundation.
#
# algebraixlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with algebraixlib.
# If not, see <http://www.gnu.org/licenses/>.
# --------------------------------------------------------------------------------------------------
import algebraixlib.structure as _structure
from algebraixlib.util.miscellaneous import get_hash as _get_hash

from algebraixlib.mathobjects.mathobject import MathObject


# --------------------------------------------------------------------------------------------------

[docs]def auto_convert(arg): """Return always a `MathObject`. If ``arg`` is not a `MathObject`, make it an :class:`Atom`. This function is used in several constructors as convenience wrapper to allow the creation of `MathObject` instances from non-`MathObject` values. """ return arg if isinstance(arg, MathObject) else Atom(arg)
[docs]class Atom(MathObject): """Represent a value (of a non-`MathObject`, hashable type) like numbers or strings. All instances of :class:`Atom` are members of :term:`set A` (:math:`A`), or conversely, :term:`set A` is the set of all instances of :class:`Atom`. .. note:: Instances of :class:`Atom` are immutable and hashable. Therefore they only accept immutable and hashable values. """
[docs] def __new__(cls, value, direct_load=False): """If ``value`` is an instance of :class:`Atom`, reuse it. This mechanism is used to reduce the number of created :class:`Atom` instances. We then need to check in ``__init__`` whether we have an already initialized instance or still have to initialize it. ``__init__`` is always called after ``__new__``. :return: ``value`` if it is an instance of :class:`Atom` (in this case we simply reuse it). If not, follow the normal path for creating an instance. """ if isinstance(value, Atom): return value return super().__new__(cls)
def __init__(self, value, direct_load=False): """ :param value: The value of this instance. May not be an instance of `MathObject` other than :class:`Atom`. (If it is of type :class:`Atom`, the instance is re-used; see `__new__`.) ``value`` must be immutable and hashable. :param direct_load: Set to ``True`` if you can be sure that ``value`` is not an instance of `MathObject`. Default is ``False``. :raise: `TypeError` if ``value`` is not hashable. """ # Check whether we received an already initialized instance (by __new__). if hasattr(self, '_value'): return super().__init__() if direct_load: assert not isinstance(value, MathObject) else: if isinstance(value, MathObject): raise TypeError("'value' must not be a MathObject") self._value = value self._hash = _get_hash('algebraixlib.mathobjects.atom.Atom', self._value) self._flags._not_relation = True self._flags._not_clan = True self._flags._not_multiclan = True # ---------------------------------------------------------------------------------------------- # Characteristics of the instance. @property def value(self) -> '( A )': """Read-only; return the value of this instance. Is always a member of :term:`set A`.""" return self._value
[docs] def get_ground_set(self) -> _structure.Structure: """Return the :term:`ground set` of the lowest-level algebra of ``self``. Is always :math:`A`. """ return _structure.GenesisSetA() # ---------------------------------------------------------------------------------------------- # (Python-)Special functions.
[docs] def __eq__(self, other): """A value-based comparison for equality. Return ``True`` if types and values match. Type-matching follows Python rules, so ``Atom(1) != Atom(1.0)``. """ return (isinstance(other, Atom) and isinstance( other.value, type(self.value)) and other.value == self.value)
[docs] def __ne__(self, other): """A value-based comparison for inequality. Return ``True`` if types or values don't match. Type-matching follows Python rules, so ``Atom(1) != Atom(1.0)``. """ return (not isinstance(other, Atom) or not isinstance( other.value, type(self.value)) or other.value != self.value)
def __lt__(self, other): """A value-based comparison for less than. Return ``True`` if ``self < other``.""" return not isinstance(other, Atom) or (repr(self.value) < repr(other.value))
[docs] def __hash__(self): """Return a hash based on the value calculated during construction.""" return self._hash
[docs] def __repr__(self): """Return the instance's code representation.""" return 'Atom({value})'.format(value=repr(self._value))
[docs] def __str__(self): """Return the instance's string representation.""" return repr(self._value)