From 9e0b68ed0779025166c83a196c184dea71802d46 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Mon, 13 Nov 2006 18:39:12 -0500 Subject: [PATCH] [pymbolic @ inform@tiker.net-20061113233912-fc703fc42ec0a232] Rewrote mappers to new recursion scheme. --- src/mapper/__init__.py | 74 +++++++++++++++++++----------------- src/mapper/dependency.py | 5 +-- src/mapper/differentiator.py | 38 +++++++----------- src/mapper/evaluator.py | 34 +++++++++-------- src/mapper/stringifier.py | 35 +++++++++-------- src/mapper/substitutor.py | 2 +- src/polynomial.py | 3 -- src/rational.py | 10 ----- 8 files changed, 93 insertions(+), 108 deletions(-) diff --git a/src/mapper/__init__.py b/src/mapper/__init__.py index be8e3c3..2f71ad6 100644 --- a/src/mapper/__init__.py +++ b/src/mapper/__init__.py @@ -1,48 +1,53 @@ -class Mapper: - def __call__(self, *args, **kwargs): -class CombineMapper: +class Mapper(object): + def __call__(self, victim, *args, **kwargs): + try: + victim.invoke_mapper(self, *args, **kwargs) + except AttributeError: + self.map_constant(victim) + + def map_rational(self, expr): + return self.map_quotient(self, expr) + + + + + +class CombineMapper(Mapper): def combine(self, values): raise NotImplementedError def map_call(self, expr): - return self.combine([expr.function.invoke_mapper(self)] + - [child.invoke_mapper(self) - for child in expr.parameters]) + return self.combine([self(expr.function)] + + [self(child) for child in expr.parameters]) def map_subscript(self, expr): - return self.combine([expr.aggregate.invoke_mapper(self), - expr.index.invoke_mapper(self)]) + return self.combine( + [self(expr.aggregate), self(expr.index)]) def map_lookup(self, expr): - return expr.aggregate.invoke_mapper(self) + return self(expr.aggregate) def map_negation(self, expr): - return expr.child.invoke_mapper(self) + return self(expr.child) def map_sum(self, expr): - return self.combine(child.invoke_mapper(self) - for child in expr.children) + return self.combine(self(child) for child in expr.children) map_product = map_sum - def map_rational(self, expr): - return self.combine((expr.numerator.invoke_mapper(self), - expr.denominator.invoke_mapper(self))) + def map_quotient(self, expr): + return self.combine((self(expr.numerator), self(expr.denominator))) def map_power(self, expr): - return self.combine((expr.base.invoke_mapper(self), - expr.exponent.invoke_mapper(self))) + return self.combine(self(expr.base), self(expr.exponent)) - def map_polynomial(self, expr): - raise NotImplementedError - map_list = map_sum -class IdentityMapper: +class IdentityMapper(Mapper): def map_constant(self, expr): return expr @@ -50,34 +55,33 @@ class IdentityMapper: return expr def map_call(self, expr): - return expr.__class__(expr.function.invoke_mapper(self), - tuple(child.invoke_mapper(self) - for child in expr.parameters)) + return expr.__class__( + self(expr.function), + tuple(self(child) + for child in expr.parameters)) def map_subscript(self, expr): - return expr.__class__(expr.aggregate.invoke_mapper(self), - expr.index.invoke_mapper(self)) + return expr.__class__(self(expr.aggregate), self(expr.index)) def map_lookup(self, expr): - return expr.__class__(expr.aggregate.invoke_mapper(self), - expr.name) + return expr.__class__(self(expr.aggregate), expr.name) def map_negation(self, expr): - return expr.__class__(expr.child.invoke_mapper(self)) + return expr.__class__(self(expr.child)) def map_sum(self, expr): - return expr.__class__(*[child.invoke_mapper(self) - for child in expr.children]) + return expr.__class__( + *[self(child) for child in expr.children]) map_product = map_sum def map_rational(self, expr): - return expr.__class__(expr.numerator.invoke_mapper(self), - expr.denominator.invoke_mapper(self)) + return expr.__class__(self(expr.numerator), + self(expr.denominator)) def map_power(self, expr): - return expr.__class__(expr.base.invoke_mapper(self), - expr.exponent.invoke_mapper(self)) + return expr.__class__(self(expr.base), + self(expr.exponent)) def map_polynomial(self, expr): raise NotImplementedError diff --git a/src/mapper/dependency.py b/src/mapper/dependency.py index 524c8c8..cb84a71 100644 --- a/src/mapper/dependency.py +++ b/src/mapper/dependency.py @@ -1,6 +1,4 @@ import sets -import operator - import pymbolic.mapper @@ -8,6 +6,7 @@ import pymbolic.mapper class DependencyMapper(pymbolic.mapper.CombineMapper): def combine(self, values): + import operator return reduce(operator.or_, values) def map_constant(self, expr): @@ -20,7 +19,7 @@ class DependencyMapper(pymbolic.mapper.CombineMapper): def get_dependencies(expr): - return expr.invoke_mapper(DependencyMapper()) + return DependencyMapper()(expr) diff --git a/src/mapper/differentiator.py b/src/mapper/differentiator.py index 50f3d7e..855cf26 100644 --- a/src/mapper/differentiator.py +++ b/src/mapper/differentiator.py @@ -3,6 +3,7 @@ import cmath import pymbolic import pymbolic.primitives as primitives +import pymbolic.mapper import pymbolic.mapper.evaluator @@ -32,7 +33,7 @@ def map_math_functions_by_name(i, func, pars): -class DifferentiationMapper: +class DifferentiationMapper(pymbolic.mapper.Mapper): def __init__(self, variable, func_map): self.Variable = variable self.FunctionMap = func_map @@ -49,24 +50,24 @@ class DifferentiationMapper: def map_call(self, expr): return pymbolic.sum(*( self.FunctionMap(i, expr.function, expr.parameters) - * par.invoke_mapper(self) + * self(par) for i, par in enumerate(expr.parameters) if not self._isc(par))) map_subscript = map_variable def map_negation(self, expr): - return -expr.child.invoke_mapper(self) + return -self(expr.child) def map_sum(self, expr): - return pymbolic.sum(*(child.invoke_mapper(self) + return pymbolic.sum(*(self(child) for child in expr.children if not self._isc(child))) def map_product(self, expr): return pymbolic.sum(*( pymbolic.product(*(expr.children[0:i] + - (child.invoke_mapper(self),) + + (self(child),) + expr.children[i+1:])) for i, child in enumerate(expr.children) if not self._isc(child))) @@ -80,13 +81,11 @@ class DifferentiationMapper: if f_const and g_const: return primitives.Constant(0) elif f_const: - f = self._eval(f) - return -f*g.invoke_mapper(self)/g**2 + return -f*self(g)/g**2 elif g_const: - g = self._eval(g) - return f.invoke_mapper(self)/g + return self(f)/g else: - return (f.invoke_mapper(self)*g-g.invoke_mapper(self)*f)/g**2 + return (self(f)*g-self(g)*f)/g**2 def map_power(self, expr): f = expr.base @@ -99,26 +98,18 @@ class DifferentiationMapper: if f_const and g_const: return primitives.Constant(0) elif f_const: - f = self._eval(f) - return log(f) * f**g * g.invoke_mapper(self) + return log(f) * f**g * self(g) elif g_const: - g = self._eval(g) - return g * f**(g-1) * f.invoke_mapper(self) + return g * f**(g-1) * self(f) else: - return log(f) * f**g * g.invoke_mapper(self) + \ - g * f**(g-1) * f.invoke_mapper(self) + return log(f) * f**g * self(g) + \ + g * f**(g-1) * self(f) def map_polynomial(self, expr): raise NotImplementedError def _isc(self,subexp): return pymbolic.is_constant(subexp, [self.Variable]) - - def _eval(self,subexp): - try: - return primitives.Constant(pymbolic.evaluate(subexp)) - except KeyError: - return subexp @@ -128,5 +119,4 @@ def differentiate(expression, func_mapper=map_math_functions_by_name): if not isinstance(variable, (primitives.Variable, primitives.Subscript)): variable = primitives.make_variable(variable) - return expression.invoke_mapper(DifferentiationMapper(variable, - func_mapper)) + return DifferentiationMapper(variable, func_mapper)(expression) diff --git a/src/mapper/evaluator.py b/src/mapper/evaluator.py index 19604f8..70c60dd 100644 --- a/src/mapper/evaluator.py +++ b/src/mapper/evaluator.py @@ -1,10 +1,15 @@ +import pymbolic.mapper + + + + class UnknownVariableError(Exception): pass -class EvaluationMapper: +class EvaluationMapper(pymbolic.mapper.Mapper): def __init__(self, context={}): self.Context = context @@ -18,46 +23,43 @@ class EvaluationMapper: raise UnknownVariableError, expr.name def map_call(self, expr): - return expr.function.invoke_mapper(self)( - *[par.invoke_mapper(self) - for par in expr.parameters]) + return self(expr.function)(*[self(par) for par in expr.parameters]) def map_subscript(self, expr): - return expr.aggregate.invoke_mapper(self)[expr.index.invoke_mapper(self)] + return self(expr.aggregate)[self(expr.index)] def map_lookup(self, expr): - return getattr(expr.aggregate.invoke_mapper(self), expr.name) + return getattr(self(expr.aggregate), expr.name) def map_negation(self, expr): - return -expr.child.invoke_mapper(self) + return -self(expr.child) def map_sum(self, expr): - return sum(child.invoke_mapper(self) - for child in expr.children) + return sum(self(child) for child in expr.children) def map_product(self, expr): if len(expr.children) == 0: - return 1 - result = expr.children[0].invoke_mapper(self) + return 1 # FIXME? + result = self(expr.children[0]) for child in expr.children[1:]: - result *= child.invoke_mapper(self) + result *= self(child) return result def map_rational(self, expr): - return expr.numerator.invoke_mapper(self) / expr.denominator.invoke_mapper(self) + return self(expr.numerator) / self(expr.denominator) def map_power(self, expr): - return expr.base.invoke_mapper(self) ** expr.exponent.invoke_mapper(self) + return self(expr.base) ** self(expr.exponent) def map_polynomial(self, expr): raise NotImplementedError def map_list(self, expr): - return [child.invoke_mapper(self) for child in expr.Children] + return [self(child) for child in expr.Children] def evaluate(expression, context={}): - return expression.invoke_mapper(EvaluationMapper(context)) + return EvaluationMapper(context)(expression) diff --git a/src/mapper/stringifier.py b/src/mapper/stringifier.py index 586a6e4..80e5051 100644 --- a/src/mapper/stringifier.py +++ b/src/mapper/stringifier.py @@ -1,3 +1,8 @@ +import pymbolic.mapper + + + + PREC_CALL = 5 PREC_POWER = 4 PREC_UNARY = 3 @@ -7,7 +12,7 @@ PREC_NONE = 0 -class StringifyMapper: +class StringifyMapper(pymbolic.mapper.Mapper): def map_constant(self, expr, enclosing_prec): return str(expr.value) @@ -16,8 +21,8 @@ class StringifyMapper: def map_call(self, expr, enclosing_prec): result = "%s(%s)" % \ - (expr.function.invoke_mapper(self, PREC_CALL), - ", ".join(i.invoke_mapper(self, PREC_NONE) + (self(expr.function, PREC_CALL), + ", ".join(self(i, PREC_NONE) for i in expr.parameters)) if enclosing_prec > PREC_CALL: return "(%s)" % result @@ -26,38 +31,35 @@ class StringifyMapper: def map_subscript(self, expr, enclosing_prec): result = "%s[%s]" % \ - (expr.aggregate.invoke_mapper(self, PREC_CALL), - expr.index.invoke_mapper(self, PREC_CALL)) + (self(expr.aggregate, PREC_CALL), self(expr.index, PREC_CALL)) if enclosing_prec > PREC_CALL: return "(%s)" % result else: return result def map_lookup(self, expr, enclosing_prec): - result = "%s.%s" % \ - (expr.aggregate.invoke_mapper(self, PREC_CALL), - expr.name) + result = "%s.%s" % (self(expr.aggregate, PREC_CALL), expr.name) if enclosing_prec > PREC_CALL: return "(%s)" % result else: return result def map_negation(self, expr, enclosing_prec): - result = "-%s" % expr.child.invoke_mapper(self, PREC_UNARY) + result = "-%s" % self(expr.child, PREC_UNARY) if enclosing_prec > PREC_UNARY: return "(%s)" % result else: return result def map_sum(self, expr, enclosing_prec): - result = "+".join(i.invoke_mapper(self, PREC_SUM) for i in expr.children) + result = "+".join(self(i, PREC_SUM) for i in expr.children) if enclosing_prec > PREC_SUM: return "(%s)" % result else: return result def map_product(self, expr, enclosing_prec): - result = "*".join(i.invoke_mapper(self, PREC_PRODUCT) + result = "*".join(self(i, PREC_PRODUCT) for i in expr.children) if enclosing_prec > PREC_PRODUCT: return "(%s)" % result @@ -66,8 +68,8 @@ class StringifyMapper: def map_quotient(self, expr, enclosing_prec): result = "%s/%s" % ( - expr.numerator.invoke_mapper(self, PREC_PRODUCT), - expr.denominator.invoke_mapper(self, PREC_PRODUCT) + self(expr.numerator, PREC_PRODUCT), + self(expr.denominator, PREC_PRODUCT) ) if enclosing_prec > PREC_PRODUCT: return "(%s)" % result @@ -77,8 +79,8 @@ class StringifyMapper: def map_power(self, expr, enclosing_prec): result = "%s**%s" % ( - expr.base.invoke_mapper(self, PREC_POWER), - expr.exponent.invoke_mapper(self, PREC_POWER) + self(expr.base, PREC_POWER), + self(expr.exponent, PREC_POWER) ) if enclosing_prec > PREC_POWER: return "(%s)" % result @@ -89,4 +91,5 @@ class StringifyMapper: raise NotImplementedError def map_list(self, expr, enclosing_prec): - return "[%s]" % ", ".join([i.invoke_mapper(self) for i in expr.children]) + return "[%s]" % ", ".join([self(i, PREC_NONE) for i in expr.children]) + diff --git a/src/mapper/substitutor.py b/src/mapper/substitutor.py index 9284c79..3329da3 100644 --- a/src/mapper/substitutor.py +++ b/src/mapper/substitutor.py @@ -35,4 +35,4 @@ def substitute(expression, variable_assignments = {}): for k, v in variable_assignments.iteritems(): new_var_ass[primitives.make_variable(k)] = v - return expression.invoke_mapper(SubstitutionMapper(new_var_ass)) + return SubstitutionMapper(new_var_ass)(expression) diff --git a/src/polynomial.py b/src/polynomial.py index e9e9d8a..53495c1 100644 --- a/src/polynomial.py +++ b/src/polynomial.py @@ -211,9 +211,6 @@ class Polynomial(primitives.Expression): repr(self.Base), repr(self.Data)) - def __hash__(self): - return hash(self.Base) ^ hash(self.Children) - def invoke_mapper(self, mapper, *args, **kwargs): return mapper.map_polynomial(self, *args, **kwargs) diff --git a/src/rational.py b/src/rational.py index 6b304bb..8c42a90 100644 --- a/src/rational.py +++ b/src/rational.py @@ -90,19 +90,9 @@ class Rational(prm.Expression): def __float__(self): return float(self.Numerator) / flaot(self.Denominator) - def __hash__(self): - return 0xcafe ^ hash(self.Numerator) ^ hash(self.Denominator) - def invoke_mapper(self, mapper, *args, **kwargs): return mapper.map_rational(self, *args, **kwargs) - def __str__(self): - if isinstance(self.Numerator, primitives.Expression): - return primitives.Expression.__str__(self) - else: - return "%s/%s" % (str(self.Numerator), str(self.Denominator)) - - -- GitLab