Ejemplo n.º 1
0
    def _compile(self, expression, variables):
        import pymbolic.primitives as primi
        self._Expression = expression
        self._Variables = [primi.make_variable(v) for v in variables]
        ctx = self.context().copy()

        try:
            import numpy
        except ImportError:
            pass
        else:
            ctx["numpy"] = numpy

        from pymbolic.mapper.dependency import DependencyMapper
        used_variables = DependencyMapper(composite_leaves=False)(
            self._Expression)
        used_variables -= set(self._Variables)
        used_variables -= set(pymbolic.var(key) for key in list(ctx.keys()))
        used_variables = list(used_variables)
        used_variables.sort()
        all_variables = self._Variables + used_variables

        expr_s = CompileMapper()(self._Expression, PREC_NONE)
        func_s = "lambda %s: %s" % (",".join(str(v)
                                             for v in all_variables), expr_s)
        self._code = eval(func_s, ctx)
Ejemplo n.º 2
0
    def _compile(self, expression, variables):
        import pymbolic.primitives as primi
        self._Expression = expression
        self._Variables = [primi.make_variable(v) for v in variables]
        ctx = self.context().copy()

        try:
            import numpy
        except ImportError:
            pass
        else:
            ctx["numpy"] = numpy

        from pymbolic.mapper.dependency import DependencyMapper
        used_variables = DependencyMapper(
                composite_leaves=False)(self._Expression)
        used_variables -= set(self._Variables)
        used_variables -= set(pymbolic.var(key) for key in list(ctx.keys()))
        used_variables = list(used_variables)
        used_variables.sort()
        all_variables = self._Variables + used_variables

        expr_s = CompileMapper()(self._Expression, PREC_NONE)
        func_s = "lambda %s: %s" % (",".join(str(v) for v in all_variables),
                expr_s)
        self._code = eval(func_s, ctx)
Ejemplo n.º 3
0
def test_func_dep_consistency():
    from pymbolic import var
    from pymbolic.mapper.dependency import DependencyMapper
    f = var('f')
    x = var('x')
    dep_map = DependencyMapper(include_calls="descend_args")
    assert dep_map(f(x)) == set([x])
    assert dep_map(f(x=x)) == set([x])
Ejemplo n.º 4
0
def test_mappers():
    from pymbolic import variables
    f, x, y, z = variables("f x y z")

    for expr in [f(x, (y, z), name=z**2)]:
        from pymbolic.mapper import WalkMapper
        from pymbolic.mapper.dependency import DependencyMapper
        str(expr)
        IdentityMapper()(expr)
        WalkMapper()(expr)
        DependencyMapper()(expr)
Ejemplo n.º 5
0
    def get_phase_step_matrix(self, phase_name, shapes=None, sparse=False):
        """
        `shapes` maps variable names to vector lengths.

        `sparse` controls whether the output is sparse or dense. When
             `sparse=True`, returns a SparseStepMatrix.
             Otherwise returns a numpy object array.
        """

        if shapes is None:
            shapes = {}

        components, initial_vals = self.run_symbolic_step(phase_name, shapes)

        from pymbolic.mapper.differentiator import DifferentiationMapper
        from pymbolic.mapper.dependency import DependencyMapper
        dependencies = DependencyMapper()

        nv = len(components)
        shape = (nv, nv)
        if not sparse:
            step_matrix = np.zeros(shape, dtype=np.object)
        else:
            indices = []
            data = []

        iv_to_index = {iv: i for i, iv in enumerate(initial_vals)}
        for i, v in enumerate(components):
            # Get the expression for v.
            if isinstance(v, self.VectorComponent):
                expr = self.context[v.name][v.index]
            else:
                expr = self.context[v]

            # Selectively evaluate the derivative only for components that are
            # actually present in the expression. This takes advantage of
            # sparsity.
            component_vars = dependencies(expr)
            for iv in component_vars:
                if iv not in iv_to_index:
                    continue
                j = iv_to_index[iv]
                entry = DifferentiationMapper(iv)(expr)

                if not sparse:
                    step_matrix[i, j] = entry
                else:
                    indices.append((i, j))
                    data.append(entry)

        if not sparse:
            return step_matrix
        else:
            return SparseStepMatrix(shape, indices, data)
Ejemplo n.º 6
0
 def post_stat(self, i: int) -> PostSumStat:
     """
     Post-summation expressions can refer to 'sum' or 'mean' special
     names referring to the summation or its average.
     This function looks at variables used in the i'th post-summation
     expression and returns 'sum' if found, 'mean' if found, otherwise
     raises an exception.
     """
     mapper = DependencyMapper(include_calls=False)
     dep_names = [dep.name for dep in mapper(self.post_sum_sym[i])]
     if 'mean' in dep_names:
         return PostSumStat('mean')
     if 'sum' in dep_names:
         return PostSumStat('sum')
     raise ValueError('unknown stat in %r' % (self.post_sum, ))
Ejemplo n.º 7
0
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""

from pymbolic import parse, var
from pymbolic.mapper.dependency import DependencyMapper

x = var("x")
y = var("y")

expr2 = 3 * x + 5 - y
expr = parse("3*x+5-y")

print(expr)
print(expr2)

dm = DependencyMapper()
print(dm(expr))
Ejemplo n.º 8
0
 def get_dependencies(self, expr):
     from pymbolic.mapper.dependency import DependencyMapper
     return DependencyMapper()(expr)
Ejemplo n.º 9
0
    def _get_expr_dep_data(self, parsed):
        class Nth:
            def __init__(self, n):
                self.n = n

            def __call__(self, lst):
                return lst[self.n]

        from pymbolic.mapper.dependency import DependencyMapper

        deps = DependencyMapper(include_calls=False)(parsed)

        # gather information on aggregation expressions
        dep_data = []
        from pymbolic.primitives import Variable, Lookup, Subscript
        for dep_idx, dep in enumerate(deps):
            nonlocal_agg = True

            if isinstance(dep, Variable):
                name = dep.name

                if name == "math":
                    continue

                agg_func = self.quantity_data[name].default_aggregator
                if agg_func is None:
                    if self.is_parallel:
                        raise ValueError(
                                "must specify explicit aggregator for '%s'" % name)

                    agg_func = lambda lst: lst[0]
            elif isinstance(dep, Lookup):
                assert isinstance(dep.aggregate, Variable)
                name = dep.aggregate.name
                agg_name = dep.name

                if agg_name == "loc":
                    agg_func = Nth(self.rank)
                    nonlocal_agg = False
                elif agg_name == "min":
                    agg_func = min
                elif agg_name == "max":
                    agg_func = max
                elif agg_name == "avg":
                    from pytools import average
                    agg_func = average
                elif agg_name == "sum":
                    agg_func = sum
                elif agg_name == "norm2":
                    from math import sqrt
                    agg_func = lambda iterable: sqrt(
                            sum(entry**2 for entry in iterable))
                else:
                    raise ValueError("invalid rank aggregator '%s'" % agg_name)
            elif isinstance(dep, Subscript):
                assert isinstance(dep.aggregate, Variable)
                name = dep.aggregate.name

                from pymbolic import evaluate
                agg_func = Nth(evaluate(dep.index))

            qdat = self.quantity_data[name]

            from pytools import Record

            class DependencyData(Record):
                pass

            this_dep_data = DependencyData(name=name, qdat=qdat, agg_func=agg_func,
                    varname="logvar%d" % dep_idx, expr=dep,
                    nonlocal_agg=nonlocal_agg)
            dep_data.append(this_dep_data)

        # substitute in the "logvar" variable names
        from pymbolic import var, substitute
        parsed = substitute(parsed,
                dict((dd.expr, var(dd.varname)) for dd in dep_data))

        return parsed, dep_data
Ejemplo n.º 10
0
def solve_affine_equations_for(unknowns, equations):
    """
    :arg unknowns: A list of variable names for which to solve.
    :arg equations: A list of tuples ``(lhs, rhs)``.
    :return: a dict mapping unknown names to their values.
    """
    import numpy as np

    from pymbolic.mapper.dependency import DependencyMapper
    dep_map = DependencyMapper(composite_leaves=True)

    # fix an order for unknowns
    from pymbolic import var
    unknowns = [var(u) for u in unknowns]
    unknowns_set = set(unknowns)
    unknown_idx_lut = dict(
        (tgt_name, idx) for idx, tgt_name in enumerate(unknowns))

    # Find non-unknown variables, fix order for them
    # Last non-unknown is constant.
    parameters = set()
    for lhs, rhs in equations:
        parameters.update(dep_map(lhs) - unknowns_set)
        parameters.update(dep_map(rhs) - unknowns_set)

    parameters_list = list(parameters)
    parameter_idx_lut = dict(
        (var_name, idx) for idx, var_name in enumerate(parameters_list))

    from pymbolic.mapper.coefficient import CoefficientCollector
    coeff_coll = CoefficientCollector()

    # {{{ build matrix and rhs

    mat = np.zeros((len(equations), len(unknowns_set)), dtype=object)
    rhs_mat = np.zeros((len(equations), len(parameters) + 1), dtype=object)

    for i_eqn, (lhs, rhs) in enumerate(equations):
        for lhs_factor, coeffs in [(1, coeff_coll(lhs)),
                                   (-1, coeff_coll(rhs))]:
            for key, coeff in six.iteritems(coeffs):
                if key in unknowns_set:
                    mat[i_eqn, unknown_idx_lut[key]] = lhs_factor * coeff
                elif key in parameters:
                    rhs_mat[i_eqn,
                            parameter_idx_lut[key]] = -lhs_factor * coeff
                elif key == 1:
                    rhs_mat[i_eqn, -1] = -lhs_factor * coeff
                else:
                    raise ValueError("key '%s' not understood" % key)

    # }}}

    mat, rhs_mat = gaussian_elimination(mat, rhs_mat)

    # FIXME /!\ Does not check for overdetermined system.

    result = {}
    for j, unknown in enumerate(unknowns):
        (nonz_row, ) = np.where(mat[:, j])
        if len(nonz_row) != 1:
            raise RuntimeError("cannot uniquely solve for '%s'" % unknown)

        (nonz_row, ) = nonz_row

        if abs(mat[nonz_row, j]) != 1:
            raise RuntimeError(
                "division with remainder in linear solve for '%s'" % unknown)
        div = mat[nonz_row, j]

        unknown_val = int(rhs_mat[nonz_row, -1]) // div
        for parameter, coeff in zip(parameters_list, rhs_mat[nonz_row]):
            unknown_val += (int(coeff) // div) * parameter

        result[unknown] = unknown_val

    if 0:
        for lhs, rhs in equations:
            print(lhs, '=', rhs)
        print("-------------------")
        for lhs, rhs in six.iteritems(result):
            print(lhs, '=', rhs)

    return result
Ejemplo n.º 11
0
 def is_constant(self, expr):
     from pymbolic.mapper.dependency import DependencyMapper
     return not bool(DependencyMapper()(expr))
Ejemplo n.º 12
0
 def get_dependency_mapper(self, include_calls="descend_args"):
     from pymbolic.mapper.dependency import DependencyMapper
     return DependencyMapper(include_subscripts=False,
                             include_lookups=False,
                             include_calls=include_calls)