コード例 #1
0
def add_declaration_to_internals(neuron, variable_name, init_expression):
    # type: (ASTNeuron,  str, str) -> ASTNeuron
    """
    Adds the variable as stored in the declaration tuple to the neuron.
    :param neuron: a single neuron instance
    :param variable_name: the name of the variable to add
    :param init_expression: initialization expression
    :return: the neuron extended by the variable
    """
    try:
        tmp = ModelParser.parse_expression(init_expression)
        vector_variable = ASTUtils.get_vectorized_variable(
            tmp, neuron.get_scope())

        declaration_string = variable_name + ' real' + (
            '[' + vector_variable.get_vector_parameter() +
            ']' if vector_variable is not None
            and vector_variable.has_vector_parameter() else
            '') + ' = ' + init_expression
        ast_declaration = ModelParser.parse_declaration(declaration_string)
        if vector_variable is not None:
            ast_declaration.set_size_parameter(
                vector_variable.get_vector_parameter())
        neuron.add_to_internal_block(ast_declaration)
        return neuron
    except:
        raise RuntimeError('Must not fail by construction.')
コード例 #2
0
def add_declaration_to_initial_values(neuron, variable, initial_value):
    # type: (ASTNeuron, str, str) -> ASTNeuron
    """
    Adds a single declaration to the initial values block of the neuron.
    :param neuron: a neuron
    :param variable: state variable to add
    :param initial_value: corresponding initial value
    :return: a modified neuron
    """
    try:

        tmp = ModelParser.parse_expression(initial_value)
        vector_variable = ASTUtils.get_vectorized_variable(
            tmp, neuron.get_scope())
        declaration_string = variable + ' real' + (
            '[' + vector_variable.get_vector_parameter() +
            ']' if vector_variable is not None
            and vector_variable.has_vector_parameter() else
            '') + ' = ' + initial_value
        ast_declaration = ModelParser.parse_declaration(declaration_string)
        if vector_variable is not None:
            ast_declaration.set_size_parameter(
                vector_variable.get_vector_parameter())
        neuron.add_to_initial_values_block(ast_declaration)
        return neuron
    except:
        raise RuntimeError('Must not fail by construction.')
コード例 #3
0
def integrate_exact_solution(neuron, exact_solution):
    # type: (ASTNeuron, map[str, list]) -> ASTNeuron
    """
    Adds a set of instructions to the given neuron as stated in the solver output.
    :param neuron: a single neuron instance
    :param exact_solution: exact solution
    :return: a modified neuron with integrated exact solution and without equations block
    """
    neuron.add_to_internal_block(
        ModelParser.parse_declaration('__h ms = resolution()'))
    neuron = add_declarations_to_internals(neuron,
                                           exact_solution["propagator"])

    state_shape_variables_declarations = compute_state_shape_variables_declarations(
        exact_solution)
    neuron = add_declarations_to_initial_values(
        neuron, state_shape_variables_declarations)

    state_shape_variables_updates = compute_state_shape_variables_updates(
        exact_solution)
    neuron = add_state_updates(state_shape_variables_updates, neuron)

    neuron = replace_integrate_call(neuron, exact_solution["ode_updates"])

    return neuron
コード例 #4
0
ファイル: ast_transformers.py プロジェクト: pythonjam/nestml
def add_declaration_to_internals(neuron: ASTNeuron, variable_name: str,
                                 init_expression: str) -> ASTNeuron:
    """
    Adds the variable as stored in the declaration tuple to the neuron. The declared variable is of type real.
    :param neuron: a single neuron instance
    :param variable_name: the name of the variable to add
    :param init_expression: initialization expression
    :return: the neuron extended by the variable
    """
    tmp = ModelParser.parse_expression(init_expression)
    vector_variable = ASTUtils.get_vectorized_variable(tmp, neuron.get_scope())

    declaration_string = variable_name + ' real' + (
        '[' + vector_variable.get_vector_parameter() + ']' if
        vector_variable is not None and vector_variable.has_vector_parameter()
        else '') + ' = ' + init_expression
    ast_declaration = ModelParser.parse_declaration(declaration_string)
    if vector_variable is not None:
        ast_declaration.set_size_parameter(
            vector_variable.get_vector_parameter())
    neuron.add_to_internal_block(ast_declaration)
    ast_declaration.update_scope(neuron.get_internals_blocks().get_scope())
    symtable_visitor = ASTSymbolTableVisitor()
    symtable_visitor.block_type_stack.push(BlockType.INTERNALS)
    ast_declaration.accept(symtable_visitor)
    symtable_visitor.block_type_stack.pop()
    return neuron
コード例 #5
0
ファイル: ast_transformers.py プロジェクト: pythonjam/nestml
def add_declaration_to_state_block(neuron: ASTNeuron, variable: str,
                                   initial_value: str) -> ASTNeuron:
    """
    Adds a single declaration to the state block of the neuron. The declared variable is of type real.
    :param neuron: a neuron
    :param variable: state variable to add
    :param initial_value: corresponding initial value
    :return: a modified neuron
    """
    tmp = ModelParser.parse_expression(initial_value)
    vector_variable = ASTUtils.get_vectorized_variable(tmp, neuron.get_scope())
    declaration_string = variable + ' real' + (
        '[' + vector_variable.get_vector_parameter() + ']' if
        vector_variable is not None and vector_variable.has_vector_parameter()
        else '') + ' = ' + initial_value
    ast_declaration = ModelParser.parse_declaration(declaration_string)
    if vector_variable is not None:
        ast_declaration.set_size_parameter(
            vector_variable.get_vector_parameter())
    neuron.add_to_state_block(ast_declaration)
    ast_declaration.update_scope(neuron.get_state_blocks().get_scope())

    symtable_visitor = ASTSymbolTableVisitor()
    symtable_visitor.block_type_stack.push(BlockType.STATE)
    ast_declaration.accept(symtable_visitor)
    symtable_visitor.block_type_stack.pop()

    return neuron
コード例 #6
0
 def test_declaration_with_comments(self):
     declaration = '\n' \
                   '/*pre*/\n' \
                   'test mV = 10mV # in\n' \
                   '/*post*/\n\n'
     model = ModelParser.parse_declaration(declaration)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(declaration, model_printer.print_node(model))
コード例 #7
0
 def test_declaration_with_comments(self):
     declaration = '\n' \
                   '/*pre*/\n' \
                   'test mV = 10mV # in\n' \
                   '/*post*/\n\n'
     model = ModelParser.parse_declaration(declaration)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(declaration, model_printer.print_node(model))
コード例 #8
0
 def add_timestep_symbol(self, neuron):
     assert neuron.get_initial_value(
         "__h"
     ) is None, "\"__h\" is a reserved name, please do not use variables by this name in your NESTML file"
     assert not "__h" in [
         sym.name for sym in neuron.get_internal_symbols()
     ], "\"__h\" is a reserved name, please do not use variables by this name in your NESTML file"
     neuron.add_to_internal_block(
         ModelParser.parse_declaration('__h ms = resolution()'), index=0)
コード例 #9
0
def integrate_delta_solution(equations_block, neuron, shape, shape_to_buffers):
    def ode_is_lin_const_coeff(ode_symbol, ode_definition, shapes):
        """
        TODO: improve the original code: the function should take a list of shape names, not objects
        :param ode_symbol string encoding the LHS
        :param ode_definition string encoding RHS
        :param shapes A list with shape names
        :return true iff the ode definition is a linear and constant coefficient ODE
        """

        ode_symbol_sp = parse_expr(ode_symbol)
        ode_definition_sp = parse_expr(ode_definition)

        # Check linearity
        ddvar = diff(diff(ode_definition_sp, ode_symbol_sp), ode_symbol_sp)

        if simplify(ddvar) != 0:
            return False

        # Check coefficients
        dvar = diff(ode_definition_sp, ode_symbol_sp)

        for shape in shapes:
            for symbol in dvar.free_symbols:
                if shape == str(symbol):
                    return False
        return True

    ode_lhs = str(equations_block.get_ode_equations()[0].get_lhs().get_name())
    ode_rhs = str(equations_block.get_ode_equations()[0].get_rhs())
    shape_name = shape.get_variable().get_name()
    if not (ode_is_lin_const_coeff(ode_lhs, ode_rhs, [shape_name])):
        raise Exception("Cannot handle delta shape in a not linear constant coefficient ODE.")
    ode_lhs = parse_expr(ode_lhs)
    ode_rhs = parse_expr(ode_rhs)
    # constant input
    const_input = simplify(1 / diff(ode_rhs, parse_expr(shape_name)) *
                           (ode_rhs - diff(ode_rhs, ode_lhs) * ode_lhs) - (parse_expr(shape_name)))
    # ode var factor
    c1 = diff(ode_rhs, ode_lhs)
    # The symbol must be declared again. Otherwise, the right hand side will be used for the derivative
    c2 = diff(ode_rhs, parse_expr(shape_name))
    # tau is passed as the second argument of the 'delta' function
    tau_constant = parse_expr(str(shape.get_expression().get_function_call().get_args()[1]))
    ode_var_factor = exp(-Symbol('__h') / tau_constant)
    ode_var_update_instructions = [
        str(ode_lhs) + " = " + str(ode_var_factor * ode_lhs),
        str(ode_lhs) + " += " + str(simplify(c2 / c1 * (exp(Symbol('__h') * c1) - 1)) * const_input)]
    for k in shape_to_buffers:
        ode_var_update_instructions.append(str(ode_lhs) + " += " + shape_to_buffers[k])
    neuron.add_to_internal_block(ModelParser.parse_declaration('__h ms = resolution()'))
    replace_integrate_call(neuron, ode_var_update_instructions)
    return neuron
コード例 #10
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
コード例 #11
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
コード例 #12
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
コード例 #13
0
def add_declaration_to_initial_values(neuron, variable, initial_value):
    # type: (ASTNeuron, str, str) -> ASTNeuron
    """
    Adds a single declaration to the initial values block of the neuron.
    :param neuron: a neuron
    :param variable: state variable to add
    :param initial_value: corresponding initial value
    :return: a modified neuron
    """
    tmp = ModelParser.parse_expression(initial_value)
    vector_variable = ASTUtils.get_vectorized_variable(tmp, neuron.get_scope())
    declaration_string = variable + ' real' + (
        '[' + vector_variable.get_vector_parameter() + ']'
        if vector_variable is not None and vector_variable.has_vector_parameter() else '') + ' = ' + initial_value
    ast_declaration = ModelParser.parse_declaration(declaration_string)
    if vector_variable is not None:
        ast_declaration.set_size_parameter(vector_variable.get_vector_parameter())
    neuron.add_to_initial_values_block(ast_declaration)
    return neuron
コード例 #14
0
def add_declaration_to_internals(neuron, variable_name, init_expression):
    # type: (ASTNeuron,  str, str) -> ASTNeuron
    """
    Adds the variable as stored in the declaration tuple to the neuron.
    :param neuron: a single neuron instance
    :param variable_name: the name of the variable to add
    :param init_expression: initialization expression
    :return: the neuron extended by the variable
    """
    tmp = ModelParser.parse_expression(init_expression)
    vector_variable = ASTUtils.get_vectorized_variable(tmp, neuron.get_scope())

    declaration_string = variable_name + ' real' + (
        '[' + vector_variable.get_vector_parameter() + ']'
        if vector_variable is not None and vector_variable.has_vector_parameter() else '') + ' = ' + init_expression
    ast_declaration = ModelParser.parse_declaration(declaration_string)
    if vector_variable is not None:
        ast_declaration.set_size_parameter(vector_variable.get_vector_parameter())
    neuron.add_to_internal_block(ast_declaration)
    return neuron
コード例 #15
0
def integrate_exact_solution(neuron, exact_solution):
    # type: (ASTNeuron, map[str, list]) -> ASTNeuron
    """
    Adds a set of instructions to the given neuron as stated in the solver output.
    :param neuron: a single neuron instance
    :param exact_solution: exact solution
    :return: a modified neuron with integrated exact solution and without equations block
    """
    neuron.add_to_internal_block(ModelParser.parse_declaration('__h ms = resolution()'))
    neuron = add_declarations_to_internals(neuron, exact_solution["propagator"])

    state_shape_variables_declarations = compute_state_shape_variables_declarations(exact_solution)
    neuron = add_declarations_to_initial_values(neuron, state_shape_variables_declarations)

    state_shape_variables_updates = compute_state_shape_variables_updates(exact_solution)
    neuron = add_state_updates(state_shape_variables_updates, neuron)

    neuron = replace_integrate_call(neuron, exact_solution["ode_updates"])

    return neuron
コード例 #16
0
 def test_declaration_without_comments(self):
     declaration = 'test mV = 10mV\n'
     model = ModelParser.parse_declaration(declaration)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(declaration, model_printer.print_node(model))
コード例 #17
0
 def test_declaration_without_comments(self):
     declaration = 'test mV = 10mV\n'
     model = ModelParser.parse_declaration(declaration)
     model_printer = ASTNestMLPrinter()
     self.assertEqual(declaration, model_printer.print_node(model))
コード例 #18
0
def integrate_delta_solution(equations_block, neuron, shape, shape_to_buffers):
    def ode_is_lin_const_coeff(ode_symbol, ode_definition, shapes):
        """
        TODO: improve the original code: the function should take a list of shape names, not objects
        :param ode_symbol string encoding the LHS
        :param ode_definition string encoding RHS
        :param shapes A list with shape names
        :return true iff the ode definition is a linear and constant coefficient ODE
        """

        ode_symbol_sp = parse_expr(ode_symbol)
        ode_definition_sp = parse_expr(ode_definition)

        # Check linearity
        ddvar = diff(diff(ode_definition_sp, ode_symbol_sp), ode_symbol_sp)

        if simplify(ddvar) != 0:
            return False

        # Check coefficients
        dvar = diff(ode_definition_sp, ode_symbol_sp)

        for shape in shapes:
            for symbol in dvar.free_symbols:
                if shape == str(symbol):
                    return False
        return True

    ode_lhs = str(equations_block.get_ode_equations()[0].get_lhs().get_name())
    ode_rhs = str(equations_block.get_ode_equations()[0].get_rhs())
    shape_name = shape.get_variable().get_name()
    if not (ode_is_lin_const_coeff(ode_lhs, ode_rhs, [shape_name])):
        raise Exception(
            "Cannot handle delta shape in a not linear constant coefficient ODE."
        )
    ode_lhs = parse_expr(ode_lhs)
    ode_rhs = parse_expr(ode_rhs)
    # constant input
    const_input = simplify(1 / diff(ode_rhs, parse_expr(shape_name)) *
                           (ode_rhs - diff(ode_rhs, ode_lhs) * ode_lhs) -
                           (parse_expr(shape_name)))
    # ode var factor
    c1 = diff(ode_rhs, ode_lhs)
    # The symbol must be declared again. Otherwise, the right hand side will be used for the derivative
    c2 = diff(ode_rhs, parse_expr(shape_name))
    # tau is passed as the second argument of the 'delta' function
    tau_constant = parse_expr(
        str(shape.get_expression().get_function_call().get_args()[1]))
    ode_var_factor = exp(-Symbol('__h') / tau_constant)
    ode_var_update_instructions = [
        str(ode_lhs) + " = " + str(ode_var_factor * ode_lhs),
        str(ode_lhs) + " += " +
        str(simplify(c2 / c1 * (exp(Symbol('__h') * c1) - 1)) * const_input)
    ]
    for k in shape_to_buffers:
        ode_var_update_instructions.append(
            str(ode_lhs) + " += " + shape_to_buffers[k])
    neuron.add_to_internal_block(
        ModelParser.parse_declaration('__h ms = resolution()'))
    replace_integrate_call(neuron, ode_var_update_instructions)
    return neuron