예제 #1
0
    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
예제 #2
0
    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
예제 #3
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
예제 #4
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)