Source code for algebraixlib.mathobjects.mathobject
"""The abstract base class for all math objects."""
# $Id: mathobject.py 22614 2015-07-15 18:14:53Z gfiedler $
# Copyright Algebraix Data Corporation 2015 - $Date: 2015-07-15 13:14:53 -0500 (Wed, 15 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 abc
import algebraixlib.structure as _structure
from algebraixlib.mathobjects.flags import Flags as _Flags
from algebraixlib.undef import make_or_raise_undef as _make_or_raise_undef
[docs]def raise_if_not_mathobject(obj):
"""Raise a `TypeError` exception if ``obj`` is not an instance of `MathObject`."""
if not isinstance(obj, MathObject):
raise TypeError(
"'obj' must be instance of 'mathobjects.MathObject'. It is a {type}.".format(
type=type(obj)))
[docs]def raise_if_not_mathobjects(*objs):
"""Raise a `TypeError` exception if any member of ``objs`` is not a `MathObject`."""
for obj in objs:
raise_if_not_mathobject(obj)
[docs]class MathObject(abc.ABC):
"""An abstract base class (see the base class `abc.ABC`) for all classes that represent data.
.. note:: This class can't be instantiated. Only derived classes that implement all abstract
methods can be instantiated. Since derived classes are expected to be hashable, they must
be immutable.
"""
def __init__(self):
self._flags = _Flags()
@abc.abstractmethod
[docs] def get_ground_set(self) -> _structure.Structure:
"""Return the :term:`ground set` of the lowest-level :term:`algebra` of this
`MathObject`."""
[docs] def get_left_set(self) -> bool:
"""Return the :term:`left set` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def get_right_set(self) -> bool:
"""Return the :term:`right set` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_left_regular(self) -> bool:
"""Return ``True`` if :term:`left-regular` or `Undef()` if not applicable."""
[docs] def is_left_functional(self) -> bool:
"""Return ``True`` if :term:`left-functional` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_right_functional(self) -> bool:
"""Return ``True`` if :term:`right-functional` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_bijection(self) -> bool:
"""Return ``True`` if left- and right-functional or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_reflexive(self) -> bool:
"""Return ``True`` if :term:`reflexive` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_symmetric(self) -> bool:
"""Return ``True`` if :term:`symmetric` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_transitive(self) -> bool:
"""Return ``True`` if :term:`transitive` or `Undef()` if not applicable."""
return _make_or_raise_undef()
[docs] def is_equivalence_relation(self) -> bool:
"""Return ``True`` if :term:`equivalence relation` or `Undef()` if not applicable."""
return _make_or_raise_undef()
@abc.abstractmethod
[docs] def get_repr(self) -> str:
"""Return the instance's code representation."""
@abc.abstractmethod
[docs] def get_str(self) -> str:
"""Return the instance's string representation."""
# ----------------------------------------------------------------------------------------------
@abc.abstractmethod
[docs] def __eq__(self, other) -> bool:
"""Return ``True`` if ``self`` and ``other`` are equal, based on their values."""
@abc.abstractmethod
[docs] def __ne__(self, other) -> bool:
"""Return ``True`` if ``self`` and ``other`` are not equal, based on their values."""
def __call__(self, *args, **kwargs) -> '( M )':
"""With the syntax ``mo(left)``, return the right associated with ``left``.
:param args: Exactly one argument is expected; it is the :term:`left` of the
:term:`couplet` of which the :term:`right` is returned.
:param kwargs: Named arguments are not supported.
:return: If ``self`` is a :term:`left-functional` :term:`relation`, return the right
of the couplet that has as left the single argument if one exists; return `Undef()` if
no couplet with the given left exists. Also return `Undef()` if ``self`` is not a
left-functional relation.
"""
return _make_or_raise_undef()
def __getitem__(self, left) -> 'P( M )':
"""With the syntax ``mo[left]``, return a set of rights associated with ``left``.
:param left: The :term:`left` of the :term:`couplet`\(s) of which the
:term:`right`\(s) are returned.
:return: If ``self`` is a :term:`relation`, return a :term:`set` that contains the
right(s) of the couplet(s) that have a left that matches ``left``. (This set may
be empty if no couplet with the given left exists.) Return `Undef()` if ``self`` is not
a relation.
"""
return _make_or_raise_undef()
@abc.abstractmethod
[docs] def __hash__(self) -> int:
"""Return a hash based on the member values (must match the implementation of `__eq__`).
.. note:: The fact that we calculate a hash of an instance requires that instances of
classes derived from this class are immutable (see also `Immutable Sequence Types`_)
and all its contained elements `hashable`_ (see also `object.__hash__`_).
.. _object.__hash__:
https://docs.python.org/3/reference/datamodel.html#object.__hash__
.. _hashable:
https://docs.python.org/3/glossary.html#term-hashable
.. _Immutable Sequence Types:
https://docs.python.org/3/library/stdtypes.html?immutable-sequence-types
"""
@abc.abstractmethod
[docs] def __repr__(self) -> str:
"""Return the instance's code representation."""
@abc.abstractmethod
[docs] def __str__(self) -> str:
"""Return the instance's string representation."""
@property
def cached_is_not_relation(self) -> bool:
return self._flags.not_relation
@property
def cached_is_relation(self) -> bool:
return self._flags.relation
[docs] def cache_is_relation(self, value: bool):
assert not value
self._flags.relation = False
return self
@property
def cached_is_not_clan(self) -> bool:
return self._flags.not_clan
@property
def cached_is_clan(self) -> bool:
return self._flags.clan
[docs] def cache_is_clan(self, value: bool):
assert not value
self._flags.clan = False
return self
@property
def cached_is_not_multiclan(self) -> bool:
return self._flags.not_multiclan
@property
def cached_is_multiclan(self) -> bool:
return self._flags.multiclan
[docs] def cache_is_multiclan(self, value: bool):
assert not value
self._flags.multiclan = False
return self
@property
def cached_is_not_left_functional(self) -> bool:
return self._flags.not_left_functional
@property
def cached_is_left_functional(self) -> bool:
return self._flags.left_functional
[docs] def cache_is_left_functional(self, value: bool):
assert not value
self._flags.left_functional = False
return self
@property
def cached_is_not_right_functional(self) -> bool:
return self._flags.not_right_functional
@property
def cached_is_right_functional(self) -> bool:
return self._flags.right_functional
[docs] def cache_is_right_functional(self, value: bool):
assert not value
self._flags.right_functional = False
return self
@property
def cached_is_not_left_regular(self) -> bool:
return self._flags.not_left_regular
@property
def cached_is_left_regular(self) -> bool:
return self._flags.left_regular
[docs] def cache_is_left_regular(self, value: bool):
assert not value
self._flags.left_regular = False
return self
@property
def cached_is_not_reflexive(self) -> bool:
return self._flags.not_reflexive
@property
def cached_is_reflexive(self) -> bool:
return self._flags.reflexive
[docs] def cache_is_reflexive(self, value: bool):
assert not value
self._flags.reflexive = False
return self
@property
def cached_is_not_symmetric(self) -> bool:
return self._flags.not_symmetric
@property
def cached_is_symmetric(self) -> bool:
return self._flags.symmetric
[docs] def cache_is_symmetric(self, value: bool):
assert not value
self._flags.symmetric = False
return self
@property
def cached_is_not_transitive(self) -> bool:
return self._flags.not_transitive
@property
def cached_is_transitive(self) -> bool:
return self._flags.transitive
[docs] def cache_is_transitive(self, value: bool):
assert not value
self._flags.transitive = False
return self