Exemplo n.º 1
0
    def get_spike_update_expressions(self, neuron: ASTNeuron, kernel_buffers, solver_dicts, delta_factors) -> List[ASTAssignment]:
        """
        Generate the equations that update the dynamical variables when incoming spikes arrive. To be invoked after ode-toolbox.

        For example, a resulting `assignment_str` could be "I_kernel_in += (in_spikes/nS) * 1". The values are taken from the initial values for each corresponding dynamical variable, either from ode-toolbox or directly from user specification in the model.

        Note that for kernels, `initial_values` actually contains the increment upon spike arrival, rather than the initial value of the corresponding ODE dimension.
        """
        spike_updates = []
        initial_values = neuron.get_initial_values_blocks()

        for kernel, spike_input_port in kernel_buffers:
            if neuron.get_scope().resolve_to_symbol(str(spike_input_port), SymbolKind.VARIABLE) is None:
                continue

            buffer_type = neuron.get_scope().resolve_to_symbol(str(spike_input_port), SymbolKind.VARIABLE).get_type_symbol()

            if is_delta_kernel(kernel):
                continue

            for kernel_var in kernel.get_variables():
                for var_order in range(get_kernel_var_order_from_ode_toolbox_result(kernel_var.get_name(), solver_dicts)):
                    kernel_spike_buf_name = construct_kernel_X_spike_buf_name(
                        kernel_var.get_name(), spike_input_port, var_order)
                    expr = get_initial_value_from_ode_toolbox_result(kernel_spike_buf_name, solver_dicts)
                    assert expr is not None, "Initial value not found for kernel " + kernel_var
                    expr = str(expr)
                    if expr in ["0", "0.", "0.0"]:
                        continue    # skip adding the statement if we're only adding zero

                    assignment_str = kernel_spike_buf_name + " += "
                    assignment_str += "(" + str(spike_input_port) + ")"
                    if not expr in ["1.", "1.0", "1"]:
                        assignment_str += " * (" + \
                            self._printer.print_expression(ModelParser.parse_expression(expr)) + ")"

                    if not buffer_type.print_nestml_type() in ["1.", "1.0", "1"]:
                        assignment_str += " / (" + buffer_type.print_nestml_type() + ")"

                    ast_assignment = ModelParser.parse_assignment(assignment_str)
                    ast_assignment.update_scope(neuron.get_scope())
                    ast_assignment.accept(ASTSymbolTableVisitor())

                    spike_updates.append(ast_assignment)

        for k, factor in delta_factors.items():
            var = k[0]
            inport = k[1]
            assignment_str = var.get_name() + "'" * (var.get_differential_order() - 1) + " += "
            if not factor in ["1.", "1.0", "1"]:
                assignment_str += "(" + self._printer.print_expression(ModelParser.parse_expression(factor)) + ") * "
            assignment_str += str(inport)
            ast_assignment = ModelParser.parse_assignment(assignment_str)
            ast_assignment.update_scope(neuron.get_scope())
            ast_assignment.accept(ASTSymbolTableVisitor())

            spike_updates.append(ast_assignment)

        return spike_updates
Exemplo n.º 2
0
def apply_incoming_spikes(neuron):
    """
    Adds a set of update instructions to the handed over neuron.
    :param neuron: a single neuron instance
    :type neuron: ASTNeuron
    :return: the modified neuron
    :rtype: ASTNeuron
    """
    assert (neuron is not None and isinstance(neuron, ASTNeuron)), \
        '(PyNestML.Solver.BaseTransformer) No or wrong type of neuron provided (%s)!' % type(neuron)
    conv_calls = OdeTransformer.get_sum_function_calls(neuron)
    printer = ExpressionsPrettyPrinter()
    spikes_updates = list()
    for convCall in conv_calls:
        shape = convCall.get_args()[0].get_variable().get_complete_name()
        buffer = convCall.get_args()[1].get_variable().get_complete_name()
        initial_values = (
            neuron.get_initial_values_blocks().get_declarations()
            if neuron.get_initial_values_blocks() is not None else list())
        for astDeclaration in initial_values:
            for variable in astDeclaration.get_variables():
                if re.match(shape + "[\']*",
                            variable.get_complete_name()) or re.match(
                                shape + '__[\\d]+$',
                                variable.get_complete_name()):
                    spikes_updates.append(
                        ModelParser.parse_assignment(
                            variable.get_complete_name() + " += " + buffer +
                            " * " + printer.print_expression(
                                astDeclaration.get_expression())))
    for update in spikes_updates:
        add_assignment_to_update_block(update, neuron)
    return neuron
Exemplo n.º 3
0
    def apply_spikes_from_buffers(self, neuron, shape_to_buffers):
        """generate the equations that update the dynamical variables when incoming spikes arrive.

        For example, a resulting `assignment_string` could be "I_shape_in += (in_spikes/nS) * 1".

        The definition of the spike kernel shape is then set to 0.
        """
        spike_updates = []
        initial_values = neuron.get_initial_values_blocks()
        for declaration in initial_values.get_declarations():
            variable = declaration.get_variables()[0]
            for shape in shape_to_buffers:
                matcher_computed_shape_odes = re.compile(shape + r"(__\d+)?")
                if re.match(matcher_computed_shape_odes, str(variable)):
                    buffer_type = neuron.get_scope(). \
                        resolve_to_symbol(shape_to_buffers[shape], SymbolKind.VARIABLE).get_type_symbol()
                    assignment_string = variable.get_complete_name() + " += (" + shape_to_buffers[
                        shape] + '/' + buffer_type.print_nestml_type() + ") * " + \
                                        self._printer.print_expression(declaration.get_expression())
                    spike_updates.append(
                        ModelParser.parse_assignment(assignment_string))
                    # the IV is applied. can be reset
                    declaration.set_expression(
                        ModelParser.parse_expression("0"))
        for assignment in spike_updates:
            add_assignment_to_update_block(assignment, neuron)
Exemplo n.º 4
0
def apply_incoming_spikes(neuron):
    """
    Adds a set of update instructions to the handed over neuron.
    :param neuron: a single neuron instance
    :type neuron: ASTNeuron
    :return: the modified neuron
    :rtype: ASTNeuron
    """
    assert (neuron is not None and isinstance(neuron, ASTNeuron)), \
        '(PyNestML.Solver.BaseTransformer) No or wrong type of neuron provided (%s)!' % type(neuron)
    conv_calls = OdeTransformer.get_sum_function_calls(neuron)
    printer = ExpressionsPrettyPrinter()
    spikes_updates = list()
    for convCall in conv_calls:
        shape = convCall.get_args()[0].get_variable().get_complete_name()
        buffer = convCall.get_args()[1].get_variable().get_complete_name()
        initial_values = (
            neuron.get_initial_values_blocks().get_declarations() if neuron.get_initial_values_blocks() is not None else list())
        for astDeclaration in initial_values:
            for variable in astDeclaration.get_variables():
                if re.match(shape + "[\']*", variable.get_complete_name()) or re.match(shape + '__[\\d]+$',
                                                                                       variable.get_complete_name()):
                    spikes_updates.append(ModelParser.parse_assignment(
                        variable.get_complete_name() + " += " + buffer + " * " + printer.print_expression(
                            astDeclaration.get_expression())))
    for update in spikes_updates:
        add_assignment_to_update_block(update, neuron)
    return neuron
Exemplo n.º 5
0
 def test_assignment_with_comments(self):
     assignment = '\n' \
                  '/* pre */\n' \
                  'a = b # in\n' \
                  '/* post */\n' \
                  '\n'
     model = ModelParser.parse_assignment(assignment)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(assignment, model_printer.print_node(model))
Exemplo n.º 6
0
 def test_assignment_with_comments(self):
     assignment = '\n' \
                  '/* pre */\n' \
                  'a = b # in\n' \
                  '/* post */\n' \
                  '\n'
     model = ModelParser.parse_assignment(assignment)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(assignment, model_printer.print_node(model))
Exemplo n.º 7
0
def add_state_updates(neuron: ASTNeuron, update_expressions: Mapping[str, str]) -> ASTNeuron:
    """
    Adds all update instructions as contained in the solver output to the update block of the neuron.
    :param neuron: a single neuron
    :param update_expressions: map of variables to corresponding updates during the update step.
    :return: a modified version of the neuron
    """
    for variable, update_expression in update_expressions.items():
        declaration_statement = variable + '__tmp real = ' + update_expression
        add_declaration_to_update_block(ModelParser.parse_declaration(declaration_statement), neuron)
    for variable, update_expression in update_expressions.items():
        add_assignment_to_update_block(ModelParser.parse_assignment(variable + ' = ' + variable + '__tmp'), neuron)
    return neuron
Exemplo n.º 8
0
def add_state_updates(state_shape_variables_updates, neuron):
    # type: (map[str, str], ASTNeuron) -> ASTNeuron
    """
    Adds all update instructions as contained in the solver output to the update block of the neuron.
    :param state_shape_variables_updates: map of variables to corresponding updates during the update step.
    :param neuron: a single neuron
    :return: a modified version of the neuron
    """
    for variable in state_shape_variables_updates:
        declaration_statement = variable + '__tmp real = ' + state_shape_variables_updates[variable]
        add_declaration_to_update_block(ModelParser.parse_declaration(declaration_statement), neuron)
    for variable in state_shape_variables_updates:
        add_assignment_to_update_block(ModelParser.parse_assignment(variable + ' = ' + variable + '__tmp'), neuron)
    return neuron
Exemplo n.º 9
0
def add_state_updates(state_shape_variables_updates, neuron):
    # type: (map[str, str], ASTNeuron) -> ASTNeuron
    """
    Adds all update instructions as contained in the solver output to the update block of the neuron.
    :param state_shape_variables_updates: map of variables to corresponding updates during the update step.
    :param neuron: a single neuron
    :return: a modified version of the neuron
    """
    for variable in state_shape_variables_updates:
        declaration_statement = variable + '__tmp real = ' + state_shape_variables_updates[
            variable]
        add_declaration_to_update_block(
            ModelParser.parse_declaration(declaration_statement), neuron)
    for variable in state_shape_variables_updates:
        add_assignment_to_update_block(
            ModelParser.parse_assignment(variable + ' = ' + variable +
                                         '__tmp'), neuron)
    return neuron
Exemplo n.º 10
0
def apply_spikes_from_buffers(neuron, shape_to_buffers):
    spike_updates = []
    initial_values = neuron.get_initial_values_blocks()
    for declaration in initial_values.get_declarations():
        variable = declaration.get_variables()[0]
        for shape in shape_to_buffers:
            matcher_computed_shape_odes = re.compile(shape + r"(__\d+)?")
            buffer_type = neuron.get_scope(). \
                resolve_to_symbol(shape_to_buffers[shape], SymbolKind.VARIABLE).get_type_symbol()
            if re.match(matcher_computed_shape_odes, str(variable)):
                assignment_string = variable.get_complete_name() + " += (" + shape_to_buffers[
                    shape] + '/' + buffer_type.print_nestml_type() + ") * " + \
                                    _printer.print_expression(declaration.get_expression())
                spike_updates.append(ModelParser.parse_assignment(assignment_string))
                # the IV is applied. can be reset
                declaration.set_expression(ModelParser.parse_expression("0"))
    for assignment in spike_updates:
        add_assignment_to_update_block(assignment, neuron)
Exemplo n.º 11
0
    def apply_spikes_from_buffers(self, neuron, shape_to_buffers):
        """generate the equations that update the dynamical variables when incoming spikes arrive.

        For example, a resulting `assignment_string` could be "I_shape_in += (in_spikes/nS) * 1".

        The definition of the spike kernel shape is then set to 0.
        """
        spike_updates = []
        initial_values = neuron.get_initial_values_blocks()
        for declaration in initial_values.get_declarations():
            variable = declaration.get_variables()[0]
            for shape in shape_to_buffers:
                matcher_computed_shape_odes = re.compile(shape + r"(__\d+)?")
                if re.match(matcher_computed_shape_odes, str(variable)):
                    buffer_type = neuron.get_scope(). \
                        resolve_to_symbol(shape_to_buffers[shape], SymbolKind.VARIABLE).get_type_symbol()
                    assignment_string = variable.get_complete_name() + " += (" + shape_to_buffers[
                        shape] + '/' + buffer_type.print_nestml_type() + ") * " + \
                                        self._printer.print_expression(declaration.get_expression())
                    spike_updates.append(ModelParser.parse_assignment(assignment_string))
                    # the IV is applied. can be reset
                    declaration.set_expression(ModelParser.parse_expression("0"))
        for assignment in spike_updates:
            add_assignment_to_update_block(assignment, neuron)
Exemplo n.º 12
0
 def test_assignment_without_comments(self):
     assignment = 'a = b\n'
     model = ModelParser.parse_assignment(assignment)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(assignment, model_printer.print_node(model))
Exemplo n.º 13
0
 def test_assignment_without_comments(self):
     assignment = 'a = b\n'
     model = ModelParser.parse_assignment(assignment)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(assignment, model_printer.print_node(model))