Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion brainpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
)

NeuGroup = NeuGroupNS = dyn.NeuDyn
dyn.DynamicalSystem = DynamicalSystem
setattr(dyn, 'DynamicalSystem', DynamicalSystem)

# common tools
from brainpy.context import (share as share)
Expand Down
31 changes: 16 additions & 15 deletions brainpy/algorithms/offline.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# limitations under the License.
# ==============================================================================
import warnings
from typing import Any, Dict, Optional

import jax.numpy as jnp
import numpy as np
Expand Down Expand Up @@ -48,7 +49,7 @@
'register_offline_method',
]

name2func = dict()
name2func: Dict[str, Any] = dict()


class OfflineAlgorithm(BrainPyObject):
Expand Down Expand Up @@ -78,7 +79,7 @@ def __call__(self, targets, inputs, outputs=None):
"""
return self.call(targets, inputs, outputs)

def call(self, targets, inputs, outputs=None) -> ArrayType:
def call(self, targets, inputs, outputs=None):
"""The training procedure.

Parameters
Expand Down Expand Up @@ -132,10 +133,10 @@ class RegressionAlgorithm(OfflineAlgorithm):

def __init__(
self,
max_iter: int = None,
learning_rate: float = None,
regularizer: Regularization = None,
name: str = None
max_iter: Optional[int] = None,
learning_rate: Optional[float] = None,
regularizer: Optional[Regularization] = None,
name: Optional[str] = None
):
super(RegressionAlgorithm, self).__init__(name=name)
self.max_iter = max_iter
Expand Down Expand Up @@ -192,7 +193,7 @@ class LinearRegression(RegressionAlgorithm):

def __init__(
self,
name: str = None,
name: Optional[str] = None,

# parameters for using gradient descent
max_iter: int = 1000,
Expand Down Expand Up @@ -248,8 +249,8 @@ class RidgeRegression(RegressionAlgorithm):
def __init__(
self,
alpha: float = 1e-7,
beta: float = None,
name: str = None,
beta: Optional[float] = None,
name: Optional[str] = None,

# parameters for using gradient descent
max_iter: int = 1000,
Expand Down Expand Up @@ -321,7 +322,7 @@ def __init__(
alpha: float = 1.0,
degree: int = 2,
add_bias: bool = False,
name: str = None,
name: Optional[str] = None,

# parameters for using gradient descent
max_iter: int = 1000,
Expand Down Expand Up @@ -378,15 +379,15 @@ def __init__(
learning_rate: float = .1,
gradient_descent: bool = True,
max_iter: int = 4000,
name: str = None,
name: Optional[str] = None,
):
super(LogisticRegression, self).__init__(name=name,
max_iter=max_iter,
learning_rate=learning_rate)
self.gradient_descent = gradient_descent
self.sigmoid = Sigmoid()

def call(self, targets, inputs, outputs=None) -> ArrayType:
def call(self, targets, inputs, outputs=None):
# prepare data
inputs = _check_data_2d_atls(bm.as_jax(inputs))
targets = _check_data_2d_atls(bm.as_jax(targets))
Expand Down Expand Up @@ -437,7 +438,7 @@ class PolynomialRegression(LinearRegression):
def __init__(
self,
degree: int = 2,
name: str = None,
name: Optional[str] = None,
add_bias: bool = False,

# parameters for using gradient descent
Expand Down Expand Up @@ -472,7 +473,7 @@ def __init__(
self,
alpha: float = 1.0,
degree: int = 2,
name: str = None,
name: Optional[str] = None,
add_bias: bool = False,

# parameters for using gradient descent
Expand Down Expand Up @@ -528,7 +529,7 @@ def __init__(
alpha: float = 1.0,
degree: int = 2,
l1_ratio: float = 0.5,
name: str = None,
name: Optional[str] = None,
add_bias: bool = False,

# parameters for using gradient descent
Expand Down
2 changes: 1 addition & 1 deletion brainpy/algorithms/online.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
'register_online_method',
]

name2func = dict()
name2func: "dict[str, type[OnlineAlgorithm] | OnlineAlgorithm]" = dict()


class OnlineAlgorithm(BrainPyObject):
Expand Down
56 changes: 30 additions & 26 deletions brainpy/analysis/highdim/slow_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import math
import time
import warnings
from typing import Callable, Union, Dict, Sequence, Tuple
from typing import Callable, Union, Dict, Sequence, Tuple, Optional, Any, cast

import jax
import jax.numpy as jnp
Expand Down Expand Up @@ -124,21 +124,21 @@ class SlowPointFinder(base.DSAnalyzer):
def __init__(
self,
f_cell: Union[Callable, DynamicalSystem],
f_type: str = None,
f_loss: Callable = None,
f_type: Optional[str] = None,
f_loss: Optional[Callable] = None,
verbose: bool = True,
args: Tuple = (),

# parameters for `f_cell` is DynamicalSystem instance
inputs: Sequence = None,
t: float = None,
dt: float = None,
target_vars: Dict[str, bm.Variable] = None,
excluded_vars: Union[Sequence[bm.Variable], Dict[str, bm.Variable]] = None,
inputs: Optional[Sequence] = None,
t: Optional[float] = None,
dt: Optional[float] = None,
target_vars: Optional[Dict[str, bm.Variable]] = None,
excluded_vars: Optional[Union[Sequence[bm.Variable], Dict[str, bm.Variable]]] = None,

# deprecated
f_loss_batch: Callable = None,
fun_inputs: Callable = None,
f_loss_batch: Optional[Callable] = None,
fun_inputs: Optional[Callable] = None,
):
super().__init__()

Expand All @@ -149,7 +149,7 @@ def __init__(

# update function
if target_vars is None:
self.target_vars = bm.ArrayCollector()
self.target_vars: bm.ArrayCollector = bm.ArrayCollector()
else:
if not isinstance(target_vars, dict):
raise TypeError(f'"target_vars" must be a dict but we got {type(target_vars)}')
Expand Down Expand Up @@ -181,14 +181,14 @@ def __init__(
else:
self.target_vars = all_vars
if len(excluded_vars):
excluded_vars = [id(v) for v in excluded_vars]
excluded_ids = [id(v) for v in excluded_vars]
for key, val in tuple(self.target_vars.items()):
if id(val) in excluded_vars:
if id(val) in excluded_ids:
self.target_vars.pop(key)

# input function
if callable(inputs):
self._inputs = inputs
self._inputs: Any = inputs
else:
if inputs is None:
self._inputs = None
Expand Down Expand Up @@ -258,13 +258,13 @@ def __init__(
self.f_loss = f_loss

# essential variables
self._losses = None
self._fixed_points = None
self._selected_ids = None
self._opt_losses = None
self._losses: Any = None
self._fixed_points: Any = None
self._selected_ids: Any = None
self._opt_losses: Any = None

# functions
self._opt_functions = dict()
self._opt_functions: Dict[str, Any] = dict()

@property
def opt_losses(self) -> np.ndarray:
Expand Down Expand Up @@ -315,7 +315,7 @@ def find_fps_with_gd_method(
tolerance: Union[float, Dict[str, float]] = 1e-5,
num_batch: int = 100,
num_opt: int = 10000,
optimizer: optim.Optimizer = None,
optimizer: Optional[optim.Optimizer] = None,
):
"""Optimize fixed points with gradient descent methods.

Expand Down Expand Up @@ -456,9 +456,9 @@ def find_fps_with_opt_solver(
indices = [0]
for v in candidates.values():
indices.append(v.shape[1])
indices = np.cumsum(indices)
offsets = np.cumsum(indices)
keys = tuple(candidates.keys())
self._fixed_points = {key: fixed_points[:, indices[i]: indices[i + 1]]
self._fixed_points = {key: fixed_points[:, offsets[i]: offsets[i + 1]]
for i, key in enumerate(keys)}
else:
self._fixed_points = fixed_points
Expand Down Expand Up @@ -538,7 +538,9 @@ def exclude_outliers(self, tolerance: float = 1e0):
return

# Compute pairwise distances between all fixed points.
distances = np.asarray(utils.euclidean_distance_jax(self.fixed_points, num_fps))
# ``fixed_points`` property returns ndarray-or-dict; the outlier path
# operates on the array branch, so narrow it for the distance helper.
distances = np.asarray(utils.euclidean_distance_jax(cast(jnp.ndarray, self.fixed_points), num_fps))

# Find the second smallest element in each column of the pairwise distance matrix.
# This corresponds to the closest neighbor for each fixed point.
Expand Down Expand Up @@ -597,7 +599,9 @@ def compute_jacobians(
else:
raise ValueError('Only support points of 1D: (num_feature,) or 2D: (num_point, num_feature)')
if isinstance(points, dict) and stack_dict_var:
points = jnp.hstack(tuple(points.values()))
# ``points`` is a constrained-TypeVar param; stacking a dict yields a
# concrete jax.Array that mypy cannot reconcile with every constraint.
points = jnp.hstack(tuple(points.values())) # type: ignore[assignment, arg-type]

# get Jacobian matrix
jacobian = self._get_f_jocabian(stack_dict_var)(points)
Expand Down Expand Up @@ -761,8 +765,8 @@ def call_opt(x):

def _generate_ds_cell_function(
self, target,
t: float = None,
dt: float = None,
t: Optional[float] = None,
dt: Optional[float] = None,
):
if dt is None: dt = bm.get_dt()
if t is None: t = 0.
Expand Down
23 changes: 12 additions & 11 deletions brainpy/analysis/lowdim/lowdim_bifurcation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# ==============================================================================
from copy import deepcopy
from functools import partial
from typing import Any, Optional

import jax
import jax.numpy as jnp
Expand All @@ -26,7 +27,7 @@
from brainpy.analysis import stability, plotstyle, utils, constants as C
from brainpy.analysis.lowdim.lowdim_analyzer import *

pyplot = None
pyplot: Any = None

__all__ = [
'Bifurcation1D',
Expand Down Expand Up @@ -380,10 +381,10 @@ def plot_limit_cycle_by_sim(
duration=100,
with_plot: bool = True,
with_return: bool = False,
plot_style: dict = None,
plot_style: Optional[dict] = None,
tol: float = 0.001,
show: bool = False,
dt: float = None,
dt: Optional[float] = None,
offset: float = 1.
):
global pyplot
Expand All @@ -404,8 +405,8 @@ def plot_limit_cycle_by_sim(
mon_res = traject_model.run(duration=duration)

# find limit cycles
vs_limit_cycle = tuple({'min': [], 'max': []} for _ in self.target_var_names)
ps_limit_cycle = tuple([] for _ in self.target_par_names)
vs_limit_cycle: tuple = tuple({'min': [], 'max': []} for _ in self.target_var_names)
ps_limit_cycle: tuple = tuple([] for _ in self.target_par_names)
for i in range(mon_res[self.x_var].shape[1]):
data = mon_res[self.x_var][:, i]
max_index = utils.find_indexes_of_limit_cycle_max(data, tol=tol)
Expand Down Expand Up @@ -468,10 +469,10 @@ def __init__(
model,
fast_vars: dict,
slow_vars: dict,
fixed_vars: dict = None,
pars_update: dict = None,
fixed_vars: Optional[dict] = None,
pars_update: Optional[dict] = None,
resolutions=None,
options: dict = None
options: Optional[dict] = None
):
super().__init__(model=model,
target_pars=slow_vars,
Expand Down Expand Up @@ -559,10 +560,10 @@ def __init__(
model,
fast_vars: dict,
slow_vars: dict,
fixed_vars: dict = None,
pars_update: dict = None,
fixed_vars: Optional[dict] = None,
pars_update: Optional[dict] = None,
resolutions=0.1,
options: dict = None
options: Optional[dict] = None
):
super().__init__(model=model,
target_pars=slow_vars,
Expand Down
2 changes: 1 addition & 1 deletion brainpy/analysis/utils/others.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def keep_unique(candidates: Union[np.ndarray, Dict[str, np.ndarray]],

# If point A and point B are within identical_tol of each other, and the
# A is first in the list, we keep A.
distances = np.asarray(euclidean_distance_jax(candidates, num_fps))
distances = np.asarray(euclidean_distance_jax(candidates, num_fps)) # type: ignore[arg-type] # candidates is an array here; euclidean_distance_jax annotation omits np.ndarray
example_idxs = np.arange(num_fps)
all_drop_idxs = []
for fidx in range(num_fps - 1):
Expand Down
Loading
Loading