Variable#

@Xiaoyu Chen @Chaoming Wang

In this section, we will briefly introduce brainpy.math.Variable. It is the foundation for mathematical operations of brain dynamics programming (BDP) in BrainPy.

import brainpy as bp
import brainpy.math as bm

# bm.set_platform('cpu')
bp.__version__
'2.3.0'

We have talked about the definition, operations, and application of arrays in BrainPy. There are some situations, however, where arrays are not applicable. Due to JIT compilation, static arrays will be compiled as the static values. If you want to change the value of an array, you should name it as a brainpy.math.Variable. Variable tells the JIT compiler that this array should not a static value.

brainpy.math.Variable#

brainpy.math.Variable is a pointer referring to an array. The array is stored as its value. The data in a Variable can be changed during JIT compilation. If an array is labeled as a Variable, it means that it is a dynamical variable that changes during the function call.

To create or change a array into a variable, users just need to wrap the array into brainpy.math.Variable:

v = bm.Variable(t2)
v
Variable([0, 1, 2, 3], dtype=int32)

Note that the array is contained in a “Variable” instead of a “Array”.

Note

Arrays that are not marked as Variables will be JIT compiled as static data. This will cause errors and wrong results.

Users can access the value in the Variable through its attribute .value:

v.value
DeviceArray([0, 1, 2, 3], dtype=int32)

Since the data inside a Variable is a array, common operations on arrays can be directly grafted to Variables.

In-place updating#

Though the operations are the same, there are some requirements for updating a Variable. If we directly change a Variable, The returning data will become a array but not a Variable.

v2 = v + 2
v2
DeviceArray([2, 3, 4, 5], dtype=int32)

To update the Variable, users are required to use in-place updating, which only modifies the value inside the Variable but does not change the reference pointing to the Variable. In-place updating operations include:

1. Indexing and slicing

  • Indexing: v[i] = a

  • Slicing: v[i:j] = b

  • Slicing the specific values: v[[1, 3]] = c

  • Slicing all values, v[:] = d, v[...] = e

for more details, please refer to Array Objects Indexing.

v[0] = 10
v[1:3] = 9
v
Variable([10,  9,  9,  3], dtype=int32)

2. Augmented assignment

  • += (add)

  • -= (subtract)

  • /= (divide)

  • *= (multiply)

  • //= (floor divide)

  • %= (modulo)

  • **= (power)

  • &= (and)

  • |= (or)

  • ^= (xor)

  • <<= (left shift)

  • >>= (right shift)

v -= 3
v <<= 1
v
Variable([14, 12, 12,  0], dtype=int32)

3. .value assignment

v.value = bm.arange(4)
v
Variable([0, 1, 2, 3], dtype=int32)

.value assignment directly accesses the data stored in the Array. When using .value, the new data should be of the same type and shape as the original ones.

try:
    v.value = bm.array([1., 1., 1., 0.])
except Exception as e:
    print(type(e), e)
<class 'brainpy.errors.MathError'> The dtype of the original data is int32, while we got float32.

4. .update() method

This method will also check if the new data is of the same type and shape as the original ones.

v.update(bm.array([3, 4, 5, 6]))
v
Variable([3, 4, 5, 6], dtype=int32)