Beispiel #1
0
    def product(*args, **kwargs):
        """Product of multiple :py:class:`MonomialSum`s"""
        rename_map = kwargs.pop('rename_map', None)
        if rename_map is None:
            rename_map = make_rename_map()
        if kwargs:
            raise ValueError("Unrecognised keyword argument: " + kwargs.pop())

        result = MonomialSum()
        for monomials in product(*args):
            renamer = make_renamer(rename_map)
            sum_indices = []
            atomics = []
            rest = one
            for s, a, r in monomials:
                s_, applier = renamer(s)
                sum_indices.extend(s_)
                atomics.extend(map(applier, a))
                rest = Product(applier(r), rest)
            result.add(sum_indices, atomics, rest)
        return result
Beispiel #2
0
    def product(*args, **kwargs):
        """Product of multiple :py:class:`MonomialSum`s"""
        rename_map = kwargs.pop('rename_map', None)
        if rename_map is None:
            rename_map = make_rename_map()
        if kwargs:
            raise ValueError("Unrecognised keyword argument: " + kwargs.pop())

        result = MonomialSum()
        for monomials in product(*args):
            renamer = make_renamer(rename_map)
            sum_indices = []
            atomics = []
            rest = one
            for s, a, r in monomials:
                s_, applier = renamer(s)
                sum_indices.extend(s_)
                atomics.extend(map(applier, a))
                rest = Product(applier(r), rest)
            result.add(sum_indices, atomics, rest)
        return result
Beispiel #3
0
def collect_monomials(expressions, classifier):
    """Refactorises expressions into a sum-of-products form, using
    distributivity rules (i.e. a*(b + c) -> a*b + a*c).  Expansion
    proceeds until all "compound" expressions are broken up.

    :arg expressions: GEM expressions to refactorise
    :arg classifier: a function that can classify any GEM expression
                     as ``ATOMIC``, ``COMPOUND``, or ``OTHER``.  This
                     classification drives the factorisation.

    :returns: list of :py:class:`MonomialSum`s

    :raises FactorisationError: Failed to break up some "compound"
                                expressions with expansion.
    """
    # Get ComponentTensors out of the way
    expressions = remove_componenttensors(expressions)

    # Get ListTensors out of the way
    must_unroll = []  # indices to unroll
    for node in traversal(expressions):
        if isinstance(node, Indexed):
            child, = node.children
            if isinstance(child, ListTensor) and classifier(node) == COMPOUND:
                must_unroll.extend(node.multiindex)
    if must_unroll:
        must_unroll = set(must_unroll)
        expressions = unroll_indexsum(expressions,
                                      predicate=lambda i: i in must_unroll)
        expressions = remove_componenttensors(expressions)

    # Expand Conditional nodes which are COMPOUND
    conditional_predicate = lambda node: classifier(node) == COMPOUND
    expressions = expand_conditional(expressions, conditional_predicate)

    # Finally, refactorise expressions
    mapper = Memoizer(_collect_monomials)
    mapper.classifier = classifier
    mapper.rename_map = make_rename_map()
    return list(map(mapper, expressions))
Beispiel #4
0
def collect_monomials(expressions, classifier):
    """Refactorises expressions into a sum-of-products form, using
    distributivity rules (i.e. a*(b + c) -> a*b + a*c).  Expansion
    proceeds until all "compound" expressions are broken up.

    :arg expressions: GEM expressions to refactorise
    :arg classifier: a function that can classify any GEM expression
                     as ``ATOMIC``, ``COMPOUND``, or ``OTHER``.  This
                     classification drives the factorisation.

    :returns: list of :py:class:`MonomialSum`s

    :raises FactorisationError: Failed to break up some "compound"
                                expressions with expansion.
    """
    # Get ComponentTensors out of the way
    expressions = remove_componenttensors(expressions)

    # Get ListTensors out of the way
    must_unroll = []  # indices to unroll
    for node in traversal(expressions):
        if isinstance(node, Indexed):
            child, = node.children
            if isinstance(child, ListTensor) and classifier(node) == COMPOUND:
                must_unroll.extend(node.multiindex)
    if must_unroll:
        must_unroll = set(must_unroll)
        expressions = unroll_indexsum(expressions,
                                      predicate=lambda i: i in must_unroll)
        expressions = remove_componenttensors(expressions)

    # Expand Conditional nodes which are COMPOUND
    conditional_predicate = lambda node: classifier(node) == COMPOUND
    expressions = expand_conditional(expressions, conditional_predicate)

    # Finally, refactorise expressions
    mapper = Memoizer(_collect_monomials)
    mapper.classifier = classifier
    mapper.rename_map = make_rename_map()
    return list(map(mapper, expressions))