def __contains__(self, item): """Return ``True`` if ``item`` is a member of this Multiset. If ``item`` is not a `MathObject`, it is converted into an :class:`~.Atom`. This allows Boolean expressions of the form ``element in Multiset``. """ return auto_convert(item) in self.data
def __init__(self, *args, direct_load=False): """Construct a :class:`Multiset` from a single `MathObject` or value or an iterable collection of such. :param args: Zero or more unnamed arguments that are placed into the created Multiset. :param direct_load: Flag they allows bypassing the normal auto-converting of elements. The elements must all be instances of `MathObject`. The prefered argument type will be a dictionary whose keys are mapped to positive integers. The keys will be auto-converted based on the direct_load parameter. .. note:: A string is an iterable, so an explicit conversion to an :class:`~.Atom` (or wrapping it into brackets or braces) is required for multi-character strings. """ super().__init__() elements = args[0] if len(args) == 1 else args # Normally load an argument. May come from 'elements' or from unnamed arguments. if isinstance(elements, Multiset): # A Multiset as argument: create a Multiset that contains a Multiset. self._data = _collections.Counter({elements: 1}) elif isinstance(elements, _collections.Counter) or isinstance(elements, dict): self._data = _collections.Counter() for key in elements.keys(): if direct_load: self._data[key] = elements[key] else: # only asserting in non direct mode, assumption is direct load has good data. assert isinstance(elements[key], int) and elements[key] > 0 self._data[auto_convert(key)] = elements[key] elif isinstance(elements, str): # Strings are iterable, but that is undesired behaviour in this instance self._data = _collections.Counter({auto_convert(elements): 1}) elif isinstance(elements, _collections.Iterable) and not isinstance(elements, MathObject): # An Iterable (that is not a Multiset) as argument: create a Multiset with all elements. if direct_load: self._data = _collections.Counter(elements) else: self._data = _collections.Counter([auto_convert(elem) for elem in elements]) else: # Anything else as argument: create a Multiset with a single element. if direct_load: self._data = _collections.Counter({elements: 1}) else: self._data = _collections.Counter({auto_convert(elements): 1}) self._hash = 0
def __init__(self, left, right=None, direct_load=False): """Construct an instance, consisting of two `MathObject` instances ``left`` and ``right``. If either of the arguments is not a `MathObject`, make it an :class:`~.Atom` with the argument as value. """ super().__init__() if direct_load: assert isinstance(left, MathObject) assert isinstance(right, MathObject) self._left = left self._right = right else: self._left = auto_convert(left) self._right = auto_convert(right) self._hash = 0
def _getitem_multirelation(self, left): left_mo = auto_convert(left) def _sum_same_left_relations(left_mo): return_count = _collections.Counter() for elem, multi in self.data.items(): if elem.left == left_mo: return_count[elem.right] = multi return return_count return Multiset(_sum_same_left_relations(left_mo), direct_load=True)