Esempio n. 1
0
 def compress(cls, operators):
     sets = OrderedDict()
     incs = OrderedDict()
     rval = []
     for op in operators:
         if isinstance(op, cls):
             if op.as_update:
                 rval.append(op)
             else:
                 assert op.sets or op.incs
                 if op.sets:
                     sets.setdefault(op.sets[0], []).append(op)
                 if op.incs:
                     incs.setdefault(op.incs[0], []).append(op)
         else:
             rval.append(op)
     done = set()
     for view, set_ops in sets.items():
         set_op, = set_ops
         done.add(set_op)
         for inc_op in incs.get(view, []):
             set_op.As.extend(inc_op.As)
             set_op.Xs.extend(inc_op.Xs)
             done.add(inc_op)
         rval.append(set_op)
     for view, inc_ops in incs.items():
         for inc_op in inc_ops:
             if inc_op not in done:
                 rval.append(inc_op)
     return rval
Esempio n. 2
0
 def compress(cls, operators):
     sets = OrderedDict()
     incs = OrderedDict()
     rval = []
     for op in operators:
         if isinstance(op, cls):
             if op.as_update:
                 rval.append(op)
             else:
                 assert op.sets or op.incs
                 if op.sets:
                     sets.setdefault(op.sets[0], []).append(op)
                 if op.incs:
                     incs.setdefault(op.incs[0], []).append(op)
         else:
             rval.append(op)
     done = set()
     for view, set_ops in iteritems(sets):
         set_op, = set_ops
         done.add(set_op)
         for inc_op in incs.get(view, []):
             set_op.As.extend(inc_op.As)
             set_op.Xs.extend(inc_op.Xs)
             done.add(inc_op)
         rval.append(set_op)
     for view, inc_ops in iteritems(incs):
         for inc_op in inc_ops:
             if inc_op not in done:
                 rval.append(inc_op)
     return rval
Esempio n. 3
0
    def __init__(self,
                 source,
                 globals_dict,
                 closure_dict,
                 in_dims=None,
                 out_dim=None):
        self.source = source
        self.globals = globals_dict
        self.closures = closure_dict

        # self.init: key=local variable name, value=initialization statement
        self.init = OrderedDict()
        self.temp_names = OrderedDict()  # for comprehensions

        # parse and make code
        a = ast.parse(source)
        ff = Function_Finder()
        ff.visit(a)
        function_def = ff.fn_node

        try:
            self.arg_names = [arg.id for arg in function_def.args.args]
        except AttributeError:
            self.arg_names = [arg.arg for arg in function_def.args.args]
        if in_dims is None:
            in_dims = [None] * len(self.arg_names)
        self.arg_dims = in_dims
        self.out_dim = out_dim
        assert len(self.arg_names) == len(self.arg_dims)

        if isinstance(function_def, ast.FunctionDef):
            self.function_name = function_def.name
            self.body = self.visit_block(function_def.body)
        elif isinstance(function_def, ast.Lambda):
            if hasattr(function_def, 'targets'):
                self.function_name = function_def.targets[0].id
            else:
                self.function_name = "<lambda>"

            # wrap lambda expression to look like a one-line function
            r = ast.Return()
            r.value = function_def.body
            r.lineno = 1
            r.col_offset = 4
            self.body = self.visit_block([r])
        else:
            raise ValueError(
                "Expected function definition or lambda function assignment, "
                "got " + str(type(function_def)))
Esempio n. 4
0
 def __init__(self, sources, sinks, effect):
     self.effect = OrderedDict()
     # Splits by ',' and separates into lvalue=rvalue. We cannot simply use
     # split, because the rvalue may contain commas in the case of dot(*,*).
     # However, *? is lazy, and * is greedy, making this regex work.
     for lvalue, rvalue in re.findall("(.*?)=([^=]*)(?:,|$)", effect):
         sink = lvalue.strip()
         if sink not in sinks:
             raise NameError("Left-hand module '%s' from effect '%s=%s' "
                             "is not defined." % (lvalue, lvalue, rvalue))
         if sink in self.effect:
             raise ValueError("Left-hand module '%s' from effect '%s=%s' "
                              "is assigned to multiple times in '%s'." %
                              (lvalue, lvalue, rvalue, effect))
         self.effect[sink] = Expression(sources, rvalue)
Esempio n. 5
0
 def __init__(self, sources, sinks, effect):
     self.effect = OrderedDict()
     # Splits by ',' and separates into lvalue=rvalue. We cannot simply use
     # split, because the rvalue may contain commas in the case of dot(*,*).
     # However, *? is lazy, and * is greedy, making this regex work.
     for lvalue, rvalue in re.findall("(.*?)=([^=]*)(?:,|$)", effect):
         sink = lvalue.strip()
         if sink not in sinks:
             raise NameError("Left-hand module '%s' from effect '%s=%s' "
                             "is not defined." %
                             (lvalue, lvalue, rvalue))
         if sink in self.effect:
             raise ValueError("Left-hand module '%s' from effect '%s=%s' "
                              "is assigned to multiple times in '%s'." %
                              (lvalue, lvalue, rvalue, effect))
         self.effect[sink] = Expression(sources, rvalue)
Esempio n. 6
0
class Effect(object):
    """Parses an Action effect given a set of module outputs.

    Parameters
    ----------
    sources : list of string
        The names of valid sources of information (SPA module outputs)
    sinks : list of string
        The names of valid places to send information (SPA module inputs)
    effect: string
        The action to implement.  This is a set of assignment statements
        which can be parsed into a VectorList.

    The following are valid effects:
        "motor=A"
        "motor=A*B, memory=vision+DOG"
        "motor=0.5*(memory*A + vision*B)"
    """

    def __init__(self, sources, sinks, effect):
        self.effect = OrderedDict()
        # Splits by ',' and separates into lvalue=rvalue. We cannot simply use
        # split, because the rvalue may contain commas in the case of dot(*,*).
        # However, *? is lazy, and * is greedy, making this regex work.
        for lvalue, rvalue in re.findall("(.*?)=([^=]*)(?:,|$)", effect):
            sink = lvalue.strip()
            if sink not in sinks:
                raise NameError("Left-hand module '%s' from effect '%s=%s' "
                                "is not defined." %
                                (lvalue, lvalue, rvalue))
            if sink in self.effect:
                raise ValueError("Left-hand module '%s' from effect '%s=%s' "
                                 "is assigned to multiple times in '%s'." %
                                 (lvalue, lvalue, rvalue, effect))
            self.effect[sink] = Expression(sources, rvalue)

    def __str__(self):
        return ", ".join("%s=%s" % x for x in self.effect.items())
Esempio n. 7
0
class Effect(object):
    """Parses an Action effect given a set of module outputs.

    Parameters
    ----------
    sources : list of string
        The names of valid sources of information (SPA module outputs)
    sinks : list of string
        The names of valid places to send information (SPA module inputs)
    effect: string
        The action to implement.  This is a set of assignment statements
        which can be parsed into a VectorList.

    The following are valid effects:
        "motor=A"
        "motor=A*B, memory=vision+DOG"
        "motor=0.5*(memory*A + vision*B)"
    """
    def __init__(self, sources, sinks, effect):
        self.effect = OrderedDict()
        # Splits by ',' and separates into lvalue=rvalue. We cannot simply use
        # split, because the rvalue may contain commas in the case of dot(*,*).
        # However, *? is lazy, and * is greedy, making this regex work.
        for lvalue, rvalue in re.findall("(.*?)=([^=]*)(?:,|$)", effect):
            sink = lvalue.strip()
            if sink not in sinks:
                raise NameError("Left-hand module '%s' from effect '%s=%s' "
                                "is not defined." % (lvalue, lvalue, rvalue))
            if sink in self.effect:
                raise ValueError("Left-hand module '%s' from effect '%s=%s' "
                                 "is assigned to multiple times in '%s'." %
                                 (lvalue, lvalue, rvalue, effect))
            self.effect[sink] = Expression(sources, rvalue)

    def __str__(self):
        return ", ".join("%s=%s" % x for x in self.effect.items())
Esempio n. 8
0
def piecewise(data):
    """Create a piecewise constant function from a dictionary.

    Given an input of data={0: 0, 0.5: 1, 0.75: -1, 1: 0} this will generate a
    function that returns 0 up until t=0.5, then outputs a 1 until t=0.75,
    then a -1 until t=1, and then returns 0 after that. This is meant as a
    shortcut for::

        def function(t):
            if t < 0.5:
                return 0
            elif t < 0.75
                return 1
            elif t < 1:
                return -1
            else:
                return 0

    The keys in the dictionary must be times (floats or ints). The values in
    the data dictionary can be floats, lists, or functions that return
    floats or lists. All lists must be of the same length.

    For times before the first specified time, it will default to zero (of
    the correct length). This means the above example can be simplified to::

        piecewise({0.5: 1, 0.75: -1, 1: 0})

    Parameters
    ----------
    data : dict
        The values to change to. Keys are the beginning time for the value.
        Values can be int, float, list, or functions that return those.

    Returns
    -------
    function:
        A function that takes a variable t and returns the corresponding
        value from the dictionary.

    Examples
    --------

      >>> func = piecewise({0.5: 1, 0.75: -1, 1: 0})
      >>> func(0.2)
      [0]
      >>> func(0.58)
      [1]

      >>> func = piecewise({0.5: [1, 0], 0.75: [0, 1]})
      >>> func(0.2)
      [0,0]
      >>> func(0.58)
      [1,0]
      >>> func(100)
      [0,1]

      >>> import math
      >>> func = piecewise({0: math.sin, 0.5: math.cos})
      >>> func(0.499)
      [0.47854771647582706]
      >>> func(0.5)
      [0.8775825618903728]

    """

    # first, sort the data (to simplify finding the right element
    # when calling the function)
    output_length = None  # the dimensionality of the returned values
    for time in data:
        if not is_number(time):
            raise TypeError('Keys must be times (floats or ints), not "%s"' %
                            repr(time.__class__))

        # figure out the length of this item
        if callable(data[time]):
            length = np.asarray(data[time](0.0)).size
        else:
            data[time] = np.asarray(data[time])
            length = data[time].size

        # make sure this is the same length as previous items
        if length != output_length and output_length is not None:
            raise ValueError('Invalid data for piecewise function: '
                             'time %4g has %d items instead of %d' %
                             (time, length, output_length))
        output_length = length

    # make a default output of 0 when t before what was passed
    data[np.finfo(float).min] = np.zeros(output_length)
    ordered_data = OrderedDict(sorted(iteritems(data)))

    # build the function to return
    def piecewise_function(t, data=ordered_data):
        # get the t we'll use for output
        for time in (time for time in data if time <= t):
            out_t = time

        # if it's a function, call it
        if callable(data[out_t]):
            return np.asarray(data[out_t](t))
        return data[out_t]

    return piecewise_function
Esempio n. 9
0
    def plan_SimPyFunc(self, ops):
        # TODO: test with a hybrid program (Python and OCL)

        # group nonlinearities
        unique_ops = OrderedDict()
        for op in ops:
            # assert op.n_args in (1, 2), op.n_args
            op_key = (op.fn, op.t_in, op.x is not None)
            if op_key not in unique_ops:
                unique_ops[op_key] = {'in': [], 'out': []}
            unique_ops[op_key]['in'].append(op.x)
            unique_ops[op_key]['out'].append(op.output)

        # make plans
        plans = []
        for (fn, t_in, x_in), signals in unique_ops.items():
            fn_name = (fn.__name__ if inspect.isfunction(fn) else
                       fn.__class__.__name__)
            if fn_name == "<lambda>":
                fn_name += "%d" % len(plans)

            # check signal input and output shape (implicitly checks
            # for indexing errors)
            vector_dims = lambda shape, dim: len(
                shape) == 1 and shape[0] == dim
            unit_stride = lambda es: len(es) == 1 and es[0] == 1

            if x_in:
                in_dim = signals['in'][0].size
                for sig_in in signals['in']:
                    assert sig_in.size == in_dim
                    assert vector_dims(sig_in.shape, in_dim)
                    assert unit_stride(sig_in.elemstrides)
            else:
                in_dim = None

            # if any functions have no output, must do them in Python
            if any(s is None for s in signals['out']):
                assert all(s is None for s in signals['out'])
                warnings.warn(
                    "Function '%s' could not be converted to OCL since it has "
                    "no outputs." % (fn_name), RuntimeWarning)
                plans.append(self._plan_pythonfn(
                    fn, t_in, signals, fn_name=fn_name))
                continue

            out_dim = signals['out'][0].size
            for sig_out in signals['out']:
                assert sig_out.size == out_dim
                assert vector_dims(sig_out.shape, out_dim)
                assert unit_stride(sig_out.elemstrides)

            # try to get OCL code
            try:
                in_dims = [1] if t_in else []
                in_dims += [in_dim] if x_in else []
                ocl_fn = OCL_Function(fn, in_dims=in_dims, out_dim=out_dim)
                input_names = ocl_fn.translator.arg_names
                inputs = []
                if t_in:  # append time
                    inputs.append(self.all_data[
                        [self.sidx[self._time] for i in signals['out']]])
                if x_in:  # append x
                    inputs.append(self.all_data[
                        [self.sidx[i] for i in signals['in']]])
                output = self.all_data[[self.sidx[i] for i in signals['out']]]
                plan = plan_direct(self.queue, ocl_fn.code, ocl_fn.init,
                                   input_names, inputs, output, tag=fn_name)
                plans.append(plan)
            except Exception as e:
                if self.ocl_only:
                    raise

                warnings.warn(
                    "Function '%s' could not be converted to OCL due to %s%s"
                    % (fn_name, e.__class__.__name__, e.args), RuntimeWarning)

                # not successfully translated to OCL, so do it in Python
                plans.append(self._plan_pythonfn(
                    fn, t_in, signals, fn_name=fn_name))

        return plans
Esempio n. 10
0
def get_closures(f):
    return OrderedDict(
        zip(f.__code__.co_freevars, (c.cell_contents for c in f.__closure__)))
Esempio n. 11
0
    def plan_SimPyFunc(self, ops):
        # TODO: test with a hybrid program (Python and OCL)

        # group nonlinearities
        unique_ops = OrderedDict()
        for op in ops:
            # assert op.n_args in (1, 2), op.n_args
            op_key = (op.fn, op.t_in, op.x is not None)
            if op_key not in unique_ops:
                unique_ops[op_key] = {'in': [], 'out': []}
            unique_ops[op_key]['in'].append(op.x)
            unique_ops[op_key]['out'].append(op.output)

        # make plans
        plans = []
        for (fn, t_in, x_in), signals in unique_ops.items():
            fn_name = (fn.__name__
                       if inspect.isfunction(fn) else fn.__class__.__name__)
            if fn_name == "<lambda>":
                fn_name += "%d" % len(plans)

            # check signal input and output shape (implicitly checks
            # for indexing errors)
            vector_dims = lambda shape, dim: len(shape) == 1 and shape[0
                                                                       ] == dim
            unit_stride = lambda es: len(es) == 1 and es[0] == 1

            if x_in:
                in_dim = signals['in'][0].size
                for sig_in in signals['in']:
                    assert sig_in.size == in_dim
                    assert vector_dims(sig_in.shape, in_dim)
                    assert unit_stride(sig_in.elemstrides)
            else:
                in_dim = None

            # if any functions have no output, must do them in Python
            if any(s is None for s in signals['out']):
                assert all(s is None for s in signals['out'])
                warnings.warn(
                    "Function '%s' could not be converted to OCL since it has "
                    "no outputs." % (fn_name), RuntimeWarning)
                plans.append(
                    self._plan_pythonfn(fn, t_in, signals, fn_name=fn_name))
                continue

            out_dim = signals['out'][0].size
            for sig_out in signals['out']:
                assert sig_out.size == out_dim
                assert vector_dims(sig_out.shape, out_dim)
                assert unit_stride(sig_out.elemstrides)

            # try to get OCL code
            try:
                in_dims = [1] if t_in else []
                in_dims += [in_dim] if x_in else []
                ocl_fn = OCL_Function(fn, in_dims=in_dims, out_dim=out_dim)
                input_names = ocl_fn.translator.arg_names
                inputs = []
                if t_in:  # append time
                    inputs.append(self.all_data[[
                        self.sidx[self._time] for i in signals['out']
                    ]])
                if x_in:  # append x
                    inputs.append(
                        self.all_data[[self.sidx[i] for i in signals['in']]])
                output = self.all_data[[self.sidx[i] for i in signals['out']]]
                plan = plan_direct(self.queue,
                                   ocl_fn.code,
                                   ocl_fn.init,
                                   input_names,
                                   inputs,
                                   output,
                                   tag=fn_name)
                plans.append(plan)
            except Exception as e:
                if self.ocl_only:
                    raise

                warnings.warn(
                    "Function '%s' could not be converted to OCL due to %s%s" %
                    (fn_name, e.__class__.__name__, e.args), RuntimeWarning)

                # not successfully translated to OCL, so do it in Python
                plans.append(
                    self._plan_pythonfn(fn, t_in, signals, fn_name=fn_name))

        return plans