def test_drift_weights(self): """Check drifting the weights.""" nu = 0.1 drift_params = DriftParameter(nu=nu, t_0=1.0, nu_dtod=0.0, nu_std=0.0, w_noise_std=0.0) delta_t = 2.0 # Use custom parameters for the tile. python_tile = self.get_custom_tile(100, 122, drift=drift_params) cpp_tile = python_tile.tile init_weights = cpp_tile.get_weights().copy() cpp_tile.drift_weights(delta_t) weights = cpp_tile.get_weights() assert_array_almost_equal(weights, init_weights*(delta_t)**(-nu))
class PulsedDevice(_PrintableMixin): r"""Pulsed update resistive devices. Device are used as part of an :class:`~aihwkit.simulator.tiles.AnalogTile` to implement the `update once` characteristics, i.e. the material response properties when a single update pulse is given (a coincidence between row and column pulse train happened). Common properties of all pulsed devices include: **Reset**: Resets the weight in cross points to (around) zero with cycle-to-cycle and systematic spread around a mean. Important: Reset with given parameters is only activated when :meth:`~aihwkit.simulator.tiles.base.Base.reset_weights` is called explicitly by the user. **Decay**: .. math:: w_{ij} \leftarrow w_{ij}\,(1-\alpha_\text{decay}\delta_{ij}) Weight decay is only activated by inserting a specific call to :meth:`~aihwkit.simulator.tiles.base.Base.decay_weights`, which is done automatically for a tile each mini-batch is decay is present. Note that the device ``decay_lifetime`` parameters (1 over decay rates :math:`\delta_{ij}`) are analog tile specific and are thus set and fixed during RPU initialization. :math:`\alpha_\text{decay}` is a scaling factor that can be given during run-time. **Diffusion**: Similar to the decay, diffusion is only activated by inserting a specific call to :meth:`~aihwkit.simulator.tiles.base.Base.diffuse_weights`, which is done automatically for a tile each mini-batch is diffusion is present. The parameters of the diffusion process are set during RPU initialization and are fixed for the remainder. .. math:: w_{ij} \leftarrow w_{ij} + \rho_{ij} \, \xi; where :math:`xi` is a standard Gaussian variable and :math:`\rho_{ij}` the diffusion rate for a cross-point `ij`. Note: If diffusion happens to move the weight beyond the hard bounds of the weight it is ensured to be clipped appropriately. **Drift**: Optional power-law drift setting, as described in :class:`~aihwkit.similar.configs.utils.DriftParameter`. Important: Similar to reset, drift is *not* applied automatically each mini-batch but requires an explicit call to :meth:`~aihwkit.simulator.tiles.base.Base.drift_weights` each time the drift should be applied. """ bindings_class: ClassVar[Type] = devices.PulsedResistiveDeviceParameter construction_seed: int = 0 """If not equal 0, will set a unique seed for hidden parameters during construction.""" corrupt_devices_prob: float = 0.0 """Probability for devices to be corrupt (weights fixed to random value with hard bounds, that is min and max bounds are set to equal).""" corrupt_devices_range: int = 1000 """Range around zero for establishing corrupt devices.""" diffusion: float = 0.0 """Standard deviation of diffusion process.""" diffusion_dtod: float = 0.0 """Device-to device variation of diffusion rate in relative units.""" drift: DriftParameter = field(default_factory=DriftParameter, metadata={'hide_if': DriftParameter()}) """Parameter governing a power-law drift.""" dw_min: float = 0.001 """Mean of the minimal update step sizes across devices and directions.""" dw_min_dtod: float = 0.3 """Device-to-device std deviation of dw_min (in relative units to ``dw_min``).""" dw_min_std: float = 0.3 r"""Cycle-to-cycle variation size of the update step (related to :math:`\sigma_\text{c-to-c}` above) in relative units to ``dw_min``. Note: Many spread (device-to-device variation) parameters are given in relative units. For instance e.g. a setting of ``dw_min_std`` of 0.1 would mean 10% spread around the mean and thus a resulting standard deviation (:math:`\sigma_\text{c-to-c}`) of ``dw_min`` * ``dw_min_std``. """ enforce_consistency: bool = True """Whether to enforce weight bounds consistency during initialization. Whether to enforce that max weight bounds cannot be smaller than min weight bounds, and up direction step size is positive and down negative. Switches the opposite values if encountered during init. """ lifetime: float = 0.0 r"""One over `decay_rate`, ie :math:`1/r_\text{decay}`.""" lifetime_dtod: float = 0.0 """Device-to-device variation in the decay rate (in relative units).""" perfect_bias: bool = False """No up-down differences and device-to-device variability in the bounds for the devices in the bias row.""" reset: float = 0.01 """The reset values and spread per cross-point ``ij`` when using reset functionality of the device.""" reset_dtod: float = 0.0 """See ``reset``.""" reset_std: float = 0.01 """See ``reset``.""" up_down: float = 0.0 r"""Up and down direction step sizes can be systematically different and also vary across devices. :math:`\Delta w_{ij}^d` is set during RPU initialization (for each cross-point :math:`ij`): .. math:: \Delta w_{ij}^d = d\; \Delta w_\text{min}\, \left( 1 + d \beta_{ij} + \sigma_\text{d-to-d}\xi\right) where :math:`\xi` is again a standard Gaussian. :math:`\beta_{ij}` is the directional up `versus` down bias. At initialization ``up_down_dtod`` and ``up_down`` defines this bias term: .. math:: \beta_{ij} = \beta_\text{up-down} + \xi \sigma_\text{up-down-dtod} where :math:`\xi` is again a standard Gaussian number and :math:`\beta_\text{up-down}` corresponds to ``up_down``. Note that ``up_down_dtod`` is again given in relative units to ``dw_min``. """ up_down_dtod: float = 0.01 """See ``up_down``.""" w_max: float = 0.6 """See ``w_min``.""" w_max_dtod: float = 0.3 """See ``w_min_dtod``.""" w_min: float = -0.6 """Mean of hard bounds across device cross-point `ij`. The parameters ``w_min`` and ``w_max`` are used to set the min/max bounds independently. Note: For this abstract device, we assume that weights can have positive and negative values and are symmetrically around zero. In physical circuit terms, this might be implemented as a difference of two resistive elements. """ w_min_dtod: float = 0.3 """Device-to-device variation of the hard bounds. Device-to-device variation of the hard bounds, of min and max value, respectively. All are given in relative units to ``w_min``, or ``w_max``, respectively. """ def as_bindings(self) -> devices.PulsedResistiveDeviceParameter: """Return a representation of this instance as a simulator bindings object.""" return parameters_to_bindings(self) def requires_diffusion(self) -> bool: """Return whether device has diffusion enabled.""" return self.diffusion > 0.0 def requires_decay(self) -> bool: """Return whether device has decay enabled.""" return self.lifetime > 0.0