예제 #1
0
 def int_f(x, t, *args):
     df, linear_part, g = f(x, t, *args)
     dW = backend.normal(0., 1., backend.shape(x))
     dg = dt_sqrt * g * dW
     exp = backend.exp(linear_part * dt)
     y1 = x + (exp - 1) / linear_part * df + exp * dg
     return y1
예제 #2
0
    def __init__(self, v0, delay_len, before_t0=0., t0=0., dt=None):
        # size
        self.size = backend.shape(v0)

        # delay_len
        self.delay_len = delay_len
        self.dt = backend.get_dt() if dt is None else dt
        self.num_delay = int(math.ceil(delay_len / self.dt))

        # other variables
        self._delay_in = self.num_delay - 1
        self._delay_out = 0
        self.current_time = t0

        # before_t0
        self.before_t0 = before_t0

        # delay data
        self.data = backend.zeros((self.num_delay + 1, ) + self.size)
        if callable(before_t0):
            for i in range(self.num_delay):
                self.data[i] = before_t0(t0 + (i - self.num_delay) * self.dt)
        else:
            self.data[:-1] = before_t0
        self.data[-1] = v0
예제 #3
0
    def run(self, duration, inputs=(), report=False, report_percent=0.1):
        """The running function.

        Parameters
        ----------
        duration : float, int, tuple, list
            The running duration.
        inputs : list, tuple
            The model inputs with the format of ``[(key, value [operation])]``.
        report : bool
            Whether report the running progress.
        report_percent : float
            The percent of progress to report.
        """

        # times
        # ------
        start, end = utils.check_duration(duration)
        times = backend.arange(start, end, backend.get_dt())
        run_length = backend.shape(times)[0]

        # build run function
        # ------------------
        self.run_func = self.build(inputs,
                                   inputs_is_formatted=False,
                                   mon_length=run_length,
                                   return_code=False)

        # run the model
        # -------------
        utils.run_model(self.run_func, times, report, report_percent)
        self.mon['ts'] = times
예제 #4
0
 def reshape(self, run_length):
     for var in self['vars']:
         val = self[var]
         shape = backend.shape(val)
         if run_length < shape[0]:
             self[var] = val[:run_length]
         elif run_length > shape[0]:
             append = backend.zeros((run_length - shape[0], ) + shape[1:])
             self[var] = backend.vstack([val, append])
예제 #5
0
파일: base.py 프로젝트: FeynmanW/BrainPy
def mat2ij(conn_mat):
    """Get the i-j connections from connectivity matrix.

    Parameters
    ----------
    conn_mat : np.ndarray
        Connectivity matrix with `(num_pre, num_post)` shape.
    
    Returns
    -------
    conn_tuple : tuple
        (Pre-synaptic neuron indexes,
         post-synaptic neuron indexes).
    """
    if len(backend.shape(conn_mat)) != 2:
        raise errors.ModelUseError('Connectivity matrix must be in the '
                                   'shape of (num_pre, num_post).')
    pre_ids, post_ids = backend.where(conn_mat > 0)
    return backend.as_tensor(pre_ids), backend.as_tensor(post_ids)
예제 #6
0
    def run(self, duration, report=False, report_percent=0.1):
        if isinstance(duration, (int, float)):
            duration = [0, duration]
        elif isinstance(duration, (tuple, list)):
            assert len(duration) == 2
            duration = tuple(duration)
        else:
            raise ValueError

        # get the times
        times = backend.arange(duration[0], duration[1], backend.get_dt())
        # reshape the monitor
        for key in self.mon.keys():
            self.mon[key] = backend.zeros((len(times), ) +
                                          backend.shape(self.mon[key])[1:])
        # run the model
        run_model(run_func=self.run_func,
                  times=times,
                  report=report,
                  report_percent=report_percent)
예제 #7
0
    def get_monitor_func(self, mon_length, show_code=False):
        mon = self.host.mon
        if len(mon['vars']) > 0:
            monitor_func_name = 'monitor_step'
            host = self.host.name
            code_scope = {host: self.host}
            code_lines = [f'def {monitor_func_name}(_i):']
            for key in mon['vars']:
                if not hasattr(self.host, key):
                    raise errors.ModelUseError(
                        f'{self.host} do not have {key}, '
                        f'thus it cannot be monitored.')

                # initialize monitor array #
                shape = backend.shape(getattr(self.host, key))
                mon[key] = backend.zeros((mon_length, ) + shape)

                # add line #
                line = f'  {host}.mon["{key}"][_i] = {host}.{key}'
                code_lines.append(line)

            # function
            code = '\n'.join(code_lines)
            if show_code:
                print(code)
                print(code_scope)
                print()
            exec(compile(code, '', 'exec'), code_scope)
            self.set_data(monitor_func_name, code_scope[monitor_func_name])
            # results
            self.formatted_funcs['monitor'] = {
                'func': code_scope[monitor_func_name],
                'scope': {
                    host: self.host
                },
                'call': [f'{host}.{monitor_func_name}(_i)'],
            }
예제 #8
0
    def get_input_func(self, formatted_inputs, show_code=False):
        need_rebuild = False
        # check whether the input is changed
        # --
        new_inputs = {}
        input_keep_same = True
        old_input_keys = list(self.last_inputs.keys())
        for key, val, ops, data_type in formatted_inputs:
            # set data
            self.set_data(self.input_data_name(key), val)
            # compare
            if key in old_input_keys:
                old_input_keys.remove(key)
                if backend.shape(
                        self.last_inputs[key][0]) != backend.shape(val):
                    input_keep_same = False
                    if show_code:
                        print(
                            f'The current "{key}" input shape {backend.shape(val)} is different '
                            f'from the last input shape {backend.shape(self.last_inputs[key][0])}.'
                        )
                if self.last_inputs[key][1] != ops:
                    input_keep_same = False
                    if show_code:
                        print(
                            f'The current "{key}" input operation "{ops}" is different '
                            f'from the last operation "{self.last_inputs[key][1]}". '
                        )
            else:
                input_keep_same = False
                if show_code:
                    print(f'The input to a new key "{key}" in {self.host}.')
            new_inputs[key] = (val, ops, data_type)
        self.last_inputs = new_inputs
        if len(old_input_keys):
            input_keep_same = False
            if show_code:
                print(
                    f'The inputs of {old_input_keys} in {self.host} are not provided.'
                )

        # get the function of the input
        # ---
        if not input_keep_same:
            # codes
            input_func_name = 'input_step'
            host_name = self.host.name
            code_scope = {host_name: self.host}
            code_lines = [f'def {input_func_name}(_i):']
            for key, val, ops, data_type in formatted_inputs:
                if ops == '=':
                    line = f'  {host_name}.{key} = {host_name}.{self.input_data_name(key)}'
                else:
                    line = f'  {host_name}.{key} {ops}= {host_name}.{self.input_data_name(key)}'
                if data_type == 'iter':
                    line = line + '[_i]'
                code_lines.append(line)
            if len(formatted_inputs) == 0:
                code_lines.append('  pass')

            # function
            code = '\n'.join(code_lines)
            if show_code:
                print(code)
                print(code_scope)
                print()
            exec(compile(code, '', 'exec'), code_scope)
            self.set_data(input_func_name, code_scope[input_func_name])
            # results
            self.formatted_funcs['input'] = {
                'func': code_scope[input_func_name],
                'scope': {
                    host_name: self.host
                },
                'call': [f'{host_name}.{input_func_name}(_i)'],
            }
            need_rebuild = True
        return need_rebuild
예제 #9
0
파일: utils.py 프로젝트: FeynmanW/BrainPy
def format_pop_level_inputs(inputs, host, mon_length):
    """Format the inputs of a population.

    Parameters
    ----------
    inputs : tuple, list
        The inputs of the population.
    host : Population
        The host which contains all data.
    mon_length : int
        The monitor length.

    Returns
    -------
    formatted_inputs : tuple, list
        The formatted inputs of the population.
    """
    if inputs is None:
        inputs = []
    if not isinstance(inputs, (tuple, list)):
        raise errors.ModelUseError('"inputs" must be a tuple/list.')
    if len(inputs) > 0 and not isinstance(inputs[0], (list, tuple)):
        if isinstance(inputs[0], str):
            inputs = [inputs]
        else:
            raise errors.ModelUseError(
                'Unknown input structure, only support inputs '
                'with format of "(key, value, [operation])".')
    for input in inputs:
        if not 2 <= len(input) <= 3:
            raise errors.ModelUseError(
                'For each target, you must specify "(key, value, [operation])".'
            )
        if len(input) == 3 and input[2] not in constants.SUPPORTED_INPUT_OPS:
            raise errors.ModelUseError(
                f'Input operation only supports '
                f'"{list(constants.SUPPORTED_INPUT_OPS.keys())}", '
                f'not "{input[2]}".')

    # format inputs
    # -------------
    formatted_inputs = []
    for input in inputs:
        # key
        if not isinstance(input[0], str):
            raise errors.ModelUseError(
                'For each input, input[0] must be a string '
                'to specify variable of the target.')
        key = input[0]
        if not hasattr(host, key):
            raise errors.ModelUseError(
                f'Input target key "{key}" is not defined in {host}.')

        # value and data type
        val = input[1]
        if isinstance(input[1], (int, float)):
            data_type = 'fix'
        else:
            shape = backend.shape(input[1])
            if shape[0] == mon_length:
                data_type = 'iter'
            else:
                data_type = 'fix'

        # operation
        if len(input) == 3:
            ops = input[2]
        else:
            ops = '+'
        if ops not in constants.SUPPORTED_INPUT_OPS:
            raise errors.ModelUseError(
                f'Currently, BrainPy only support operations '
                f'{list(constants.SUPPORTED_INPUT_OPS.keys())}, '
                f'not {ops}')
        # input
        format_inp = (key, val, ops, data_type)
        formatted_inputs.append(format_inp)

    return formatted_inputs
예제 #10
0
파일: utils.py 프로젝트: FeynmanW/BrainPy
def format_net_level_inputs(inputs, run_length):
    """Format the inputs of a network.

    Parameters
    ----------
    inputs : tuple
        The inputs.
    run_length : int
        The running length.

    Returns
    -------
    formatted_input : dict
        The formatted input.
    """
    from brainpy.simulation import brain_objects

    # 1. format the inputs to standard
    #    formats and check the inputs
    if not isinstance(inputs, (tuple, list)):
        raise errors.ModelUseError('"inputs" must be a tuple/list.')
    if len(inputs) > 0 and not isinstance(inputs[0], (list, tuple)):
        if isinstance(inputs[0], brain_objects.DynamicSystem):
            inputs = [inputs]
        else:
            raise errors.ModelUseError(
                'Unknown input structure. Only supports '
                '"(target, key, value, [operation])".')
    for input in inputs:
        if not 3 <= len(input) <= 4:
            raise errors.ModelUseError('For each target, you must specify '
                                       '"(target, key, value, [operation])".')
        if len(input) == 4:
            if input[3] not in constants.SUPPORTED_INPUT_OPS:
                raise errors.ModelUseError(
                    f'Input operation only supports '
                    f'"{list(constants.SUPPORTED_INPUT_OPS.keys())}", '
                    f'not "{input[3]}".')

    # 2. format inputs
    formatted_inputs = {}
    for input in inputs:
        # target
        if isinstance(input[0], brain_objects.DynamicSystem):
            target = input[0]
            target_name = input[0].name
        else:
            raise KeyError(f'Unknown input target: {str(input[0])}')

        # key
        key = input[1]
        if not isinstance(key, str):
            raise errors.ModelUseError(
                'For each input, input[1] must be a string '
                'to specify variable of the target.')
        if not hasattr(target, key):
            raise errors.ModelUseError(
                f'Target {target} does not have key {key}. '
                f'So, it can not assign input to it.')

        # value and data type
        val = input[2]
        if isinstance(input[2], (int, float)):
            data_type = 'fix'
        else:
            shape = backend.shape(val)
            if shape[0] == run_length:
                data_type = 'iter'
            else:
                data_type = 'fix'

        # operation
        if len(input) == 4:
            ops = input[3]
        else:
            ops = '+'

        # final result
        if target_name not in formatted_inputs:
            formatted_inputs[target_name] = []
        format_inp = (key, val, ops, data_type)
        formatted_inputs[target_name].append(format_inp)
    return formatted_inputs