def dist(prod): if not isinstance(prod, Product): return prod leading = [] for i in prod.children: if isinstance(i, Sum): break else: leading.append(i) if len(leading) == len(prod.children): # no more sums found result = pymbolic.flattened_product(prod.children) return result else: sum = prod.children[len(leading)] assert isinstance(sum, Sum) rest = prod.children[len(leading)+1:] if rest: rest = dist(Product(rest)) else: rest = 1 result = self.collect(pymbolic.flattened_sum( pymbolic.flattened_product(leading) * dist(sumchild*rest) for sumchild in sum.children )) return result
def expand(prod): if not isinstance(prod, Product): return prod leading = [] for i in prod.children: if isinstance(i, Sum): break else: leading.append(i) if len(leading) == len(prod.children): # no more sums found result = pymbolic.flattened_product(prod.children) return result else: sum = prod.children[len(leading)] assert isinstance(sum, Sum) rest = prod.children[len(leading)+1:] if rest: rest = expand(Product(rest)) else: rest = 1 result = self.collector(pymbolic.flattened_sum( pymbolic.flattened_product(leading) * expand(sumchild*rest) for sumchild in sum.children )) return result
def map_power(self, expr): from pymbolic.primitives import Expression, Sum if isinstance(expr.base, Product): return self.rec(pymbolic.flattened_product( child**expr.exponent for child in newbase)) if isinstance(expr.exponent, int): newbase = self.rec(expr.base) if isinstance(newbase, Sum): return self.map_product(pymbolic.flattened_product(expr.exponent*(newbase,))) else: return IdentityMapper.map_power(self, expr) else: return IdentityMapper.map_power(self, expr)
def map_product(self, expr, *args): return pymbolic.flattened_sum( pymbolic.flattened_product( [self.rec_undiff(ch, *args) for ch in expr.children[0:i]] + [self.rec(child, *args)] + [self.rec_undiff(ch, *args) for ch in expr.children[i + 1:]]) for i, child in enumerate(expr.children))
def map_product(self, expr): return pymbolic.flattened_sum( pymbolic.flattened_product( expr.children[0:i] + (self.rec(child),) + expr.children[i+1:]) for i, child in enumerate(expr.children))
def map_quotient(self, expr): if is_zero(expr.numerator - 1): return expr else: # not the smartest thing we can do, but at least *something* return pymbolic.flattened_product([ type(expr)(1, self.rec(expr.denominator)), self.rec(expr.numerator)])
def map_product(self, expr, *args): return pymbolic.flattened_sum( pymbolic.flattened_product( [self.rec_undiff(ch, *args) for ch in expr.children[0:i]] + [self.rec(child, *args)] + [self.rec_undiff(ch, *args) for ch in expr.children[i+1:]] ) for i, child in enumerate(expr.children))
def map_quotient(self, expr): if is_zero(expr.numerator - 1): return expr else: # not the smartest thing we can do, but at least *something* return pymbolic.flattened_product([ type(expr)(1, self.rec(expr.denominator)), self.rec(expr.numerator) ])
def split_term(self, mul_term): """Returns a pair consisting of: - a frozenset of (base, exponent) pairs - a product of coefficients (i.e. constants and parameters) The set takes care of order-invariant comparison for us and is hashable. The argument `product' has to be fully expanded already. """ from pymbolic.primitives import Product, Power, AlgebraicLeaf def base(term): if isinstance(term, Power): return term.base else: return term def exponent(term): if isinstance(term, Power): return term.exponent else: return 1 if isinstance(mul_term, Product): terms = mul_term.children elif isinstance(mul_term, (Power, AlgebraicLeaf)): terms = [mul_term] elif not bool(self.get_dependencies(mul_term)): terms = [mul_term] else: raise RuntimeError("split_term expects a multiplicative term") base2exp = {} for term in terms: mybase = base(term) myexp = exponent(term) if mybase in base2exp: base2exp[mybase] += myexp else: base2exp[mybase] = myexp coefficients = [] cleaned_base2exp = {} for base, exp in six.iteritems(base2exp): term = base**exp if self.get_dependencies(term) <= self.parameters: coefficients.append(term) else: cleaned_base2exp[base] = exp term = frozenset( (base, exp) for base, exp in six.iteritems(cleaned_base2exp)) return term, self.rec(pymbolic.flattened_product(coefficients))
def rep2term(rep): return pymbolic.flattened_product(base**exp for base, exp in rep)
def map_product(self, expr): return pymbolic.flattened_sum( pymbolic.flattened_product(expr.children[0:i] + (self.rec(child), ) + expr.children[i + 1:]) for i, child in enumerate(expr.children))