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
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
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
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])
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)
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)
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)'], }
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
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
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