From 6c5483eb20a66a730fe4dc06d911c6cd09ec42f1 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Thu, 7 Jul 2005 14:54:01 +0000 Subject: [PATCH] [pymbolic @ Arch-1:inform@tiker.net--iam-2005%pymbolic--mainline--1.0--patch-23] Towards a usable Fempy --- TODO | 3 +- src/__init__.py | 17 ++++++ src/compiler.py | 1 - src/mapper/dependency.py | 2 - src/mapper/differentiator.py | 20 +++---- src/primitives.py | 113 +++++++++++++++++++++++++++-------- 6 files changed, 116 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 2426b28..a410aec 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ Build out traits -Fix mappers wrt rationals, polynomials + +add traits types to expressions diff --git a/src/__init__.py b/src/__init__.py index 197c9aa..65da7c6 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -10,6 +10,10 @@ import pymbolic.primitives var = pymbolic.primitives.Variable const = pymbolic.primitives.Constant +sum = pymbolic.primitives.sum +subscript = pymbolic.primitives.subscript +product = pymbolic.primitives.product +linear_combination = pymbolic.primitives.linear_combination parse = pymbolic.parser.parse evaluate = pymbolic.mapper.evaluator.evaluate @@ -20,11 +24,24 @@ get_dependencies = pymbolic.mapper.dependency.get_dependencies substitute = pymbolic.mapper.substitutor.substitute differentiate = pymbolic.mapper.differentiator.differentiate +def simplify(x): + return x + +def grad(expr, variables): + return [simplify(differentiate(expression, var)) for var in variables] + +def jacobian(expression_list, variables): + return [grad(expr, variables) for expr in expression_list] + +def laplace(expression, variables): + return sum([differentiate(differentiate(expression,var),var) for var in variables]) + if __name__ == "__main__": import math ex = parse("0 + 4.3e3j * alpha * math.cos(x+math.pi)") + 5 print ex + print repr(parse("x+y")) print evaluate(ex, {"alpha":5, "math":math, "x":-math.pi}) compiled = compile(substitute(ex, {var("alpha"): const(5)})) print compiled(-math.pi) diff --git a/src/compiler.py b/src/compiler.py index 465323f..c4174f9 100644 --- a/src/compiler.py +++ b/src/compiler.py @@ -27,7 +27,6 @@ class CompiledExpression: expr_s = "lambda %s:%s" % (",".join(str(v) for v in all_variables), str(self._Expression)) - print expr_s self.__call__ = eval(expr_s, self._Context) def __getinitargs__(self): diff --git a/src/mapper/dependency.py b/src/mapper/dependency.py index 636fa61..524c8c8 100644 --- a/src/mapper/dependency.py +++ b/src/mapper/dependency.py @@ -16,8 +16,6 @@ class DependencyMapper(pymbolic.mapper.CombineMapper): def map_variable(self, expr): return sets.Set([expr]) - map_subscript = map_variable - diff --git a/src/mapper/differentiator.py b/src/mapper/differentiator.py index ce273b1..9e2d579 100644 --- a/src/mapper/differentiator.py +++ b/src/mapper/differentiator.py @@ -39,13 +39,13 @@ class DifferentiationMapper: def map_variable(self, expr): if expr == self.Variable: return primitives.Constant(1) - elif expr in self.parameters: + elif expr in self.Parameters: return expr else: return primitives.Constant(0) def map_call(self, expr): - return primitives.make_sum(tuple( + return pymbolic.sum(tuple( self.FunctionMap(i, expr.function, expr.parameters) * par.invoke_mapper(self) for i, par in enumerate(expr.parameters) @@ -53,19 +53,19 @@ class DifferentiationMapper: map_subscript = map_variable - def map_neg(self, expr): + def map_negation(self, expr): return -expr.child.invoke_mapper(self) def map_sum(self, expr): - return primitives.make_sum(tuple(child.invoke_mapper(self) - for child in expr.Children - if not self._isc(child))) + return pymbolic.sum(*(child.invoke_mapper(self) + for child in expr.children + if not self._isc(child))) def map_product(self, expr): - return primitives.make_sum(tuple( - primitives.make_product(expr.children[0:i] + - (child.invoke_mapper(self),) + - expr.children[i+1:]) + return pymbolic.sum(*( + pymbolic.product(*(expr.children[0:i] + + (child.invoke_mapper(self),) + + expr.children[i+1:])) for i, child in enumerate(expr.children) if not self._isc(child))) diff --git a/src/primitives.py b/src/primitives.py index 6e7fea6..6c71c4a 100644 --- a/src/primitives.py +++ b/src/primitives.py @@ -15,7 +15,7 @@ class Expression(object): other = Constant(other) if not other: return self - return Sum((self, other)) + return Sum(self, other) def __radd__(self, other): assert not isinstance(other, Expression) @@ -24,14 +24,14 @@ class Expression(object): return self else: other = Constant(other) - return Sum((other, self)) + return Sum(other, self) def __sub__(self, other): if not isinstance(other, Expression): other = Constant(other) if not other: return self - return Sum((self, -other)) + return Sum(self, -other) def __rsub__(self, other): assert not isinstance(other, Expression) @@ -40,16 +40,18 @@ class Expression(object): return Negation(self) else: other = Constant(other) - return Sum((other, -self)) + return Sum(other, -self) def __mul__(self, other): if not isinstance(other, Expression): other = Constant(other) if not (other - 1): return self - if not other: + elif not (other+1): + return Negation(self) + elif not other: return Constant(0) - return Product((self, other)) + return Product(self, other) def __rmul__(self, other): assert not isinstance(other, Expression) @@ -58,8 +60,10 @@ class Expression(object): return self elif not other: return Constant(0) + elif not (other+1): + return Negation(self) else: - return Product((other, self)) + return Product(Constant(other), self) def __div__(self, other): if not isinstance(other, Expression): @@ -112,10 +116,17 @@ class Expression(object): def __str__(self): return self.invoke_mapper(pymbolic.mapper.stringifier.StringifyMapper()) + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, + ", ".join(repr(i) for i in self.__getinitargs__())) + class Constant(Expression): def __init__(self, value): self._Value = value + def __getinitargs__(self): + return self._Value, + def _value(self): return self._Value value = property(_value) @@ -235,6 +246,9 @@ class Variable(Expression): def __init__(self, name): self._Name = name + def __getinitargs__(self): + return self._Name, + def _name(self): return self._Name name = property(_name) @@ -248,9 +262,6 @@ class Variable(Expression): def __eq__(self, other): return isinstance(other, Variable) and self._Name == other._Name - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._Name)) - def invoke_mapper(self, mapper): return mapper.map_variable(self) @@ -259,6 +270,9 @@ class Call(Expression): self._Function = function self._Parameters = parameters + def __getinitargs__(self): + return self._Function, self._Parameters + def _function(self): return self._Function function = property(_function) @@ -280,6 +294,9 @@ class Subscript(Expression): self._Aggregate = aggregate self._Index = index + def __getinitargs__(self): + return self._Aggregate, self._Index + def _aggregate(self): return self._Aggregate aggregate = property(_aggregate) @@ -301,6 +318,9 @@ class ElementLookup(Expression): self._Aggregate = aggregate self._Name = name + def __getinitargs__(self): + return self._Aggregate, self._Name + def _aggregate(self): return self._Aggregate aggregate = property(_aggregate) @@ -321,6 +341,9 @@ class Negation(Expression): def __init__(self, child): self._Child = child + def __getinitargs__(self): + return self._Child, + def _child(self): return self._Child child = property(_child) @@ -332,10 +355,13 @@ class Negation(Expression): return mapper.map_negation(self) class Sum(Expression): - def __init__(self, children): + def __init__(self, *children): assert isinstance(children, tuple) self._Children = children + def __getinitargs__(self): + return self._Children + def _children(self): return self._Children children = property(_children) @@ -347,20 +373,20 @@ class Sum(Expression): if not isinstance(other, Expression): other = Constant(other) elif isinstance(other, Sum): - return Sum(self._Children + other._Children) - return Sum(self._Children + (other,)) + return Sum(*(self._Children + other._Children)) + return Sum(*(self._Children + (other,))) def __radd__(self, other): if not isinstance(other, Expression): other = Constant(other) elif isinstance(other, Sum): - return Sum(other._Children + self._Children) - return Sum(other, + self._Children) + return Sum(*(other._Children + self._Children)) + return Sum(*(other, + self._Children)) def __sub__(self, other): if not isinstance(other, Expression): other = Constant(other) - return Sum(self._Children + (-other,)) + return Sum(*(self._Children + (-other,))) def __nonzero__(self): if len(self._Children) == 0: @@ -375,10 +401,13 @@ class Sum(Expression): return mapper.map_sum(self) class Product(Expression): - def __init__(self, children): + def __init__(self, *children): assert isinstance(children, tuple) self._Children = children + def __getinitargs__(self): + return self._Children + def _children(self): return self._Children children = property(_children) @@ -390,15 +419,15 @@ class Product(Expression): if not isinstance(other, Expression): other = Constant(other) elif isinstance(other, Product): - return Product(self._Children + other._Children) + return Product(*(self._Children + other._Children)) return Product(self._Children + (other,)) def __rmul__(self, other): if not isinstance(other, Expression): other = Constant(other) elif isinstance(other, Product): - return Product(other._Children + self._Children) - return Product(other, + self._Children) + return Product(*(other._Children + self._Children)) + return Product(*(other, + self._Children)) def __nonzero__(self): for i in self._Children: @@ -511,25 +540,58 @@ class List(Expression): # intelligent makers --------------------------------------------------------- -def make_sum(components): +def sum(*components): + components = tuple(c for c in components if c) if len(components) == 0: return Constant(0) elif len(components) == 1: return components[0] else: - return Sum(components) + return Sum(*components) + + + + +def linear_combination(coefficients, expressions): + print coefficients, expressions + return sum(*(coefficient * expression + for coefficient, expression in zip(coefficients, expressions) + if coefficient and expression)) + + + + +def product(*components): + for c in components: + if not c: + return Constant(0) + + components = tuple(c for c in components if (c-1)) -def make_product(components): if len(components) == 0: - return primitives.Constant(1) + return Constant(1) elif len(components) == 1: return components[0] else: - return Product(components) + return Product(*components) + + + + +def subscript(expression, index): + if not isinstance(index, Expression): + index = Constant(index) + return Subscript(expression, index) + + + def polynomial_from_expression(expression): pass + + + def make_quotient(numerator, denominator): try: if isinstance(traits.common_traits(numerator, denominator), @@ -542,4 +604,3 @@ def make_quotient(numerator, denominator): return QuotientExpression(numerator, denominator) -# FIXME: add traits types to expressions -- GitLab