def test_zero_matrices(Simulator, zero, seed): dt = 1e-3 A = np.diag(np.ones(2) * dt) B = np.zeros((2, 1)) B[0] = 1 C = np.ones((1, 2)) D = np.ones((1, )) if zero == "C": C[...] = 0 elif zero == "D": D[...] = 0 num, den = ss2tf(A, B, C, D) num = num.flatten() synapse = LinearFilter(num, den, analog=False) t, x, yhat = run_synapse(Simulator, seed, synapse, dt=dt) y = synapse.filt(x, dt=dt, y0=0) assert allclose(t, y, yhat, delay=dt * 2 if zero == "D" else dt, atol=5e-5)
def test_zero_matrices(Simulator, zero, seed): dt = 1e-3 A = np.diag(np.ones(2) * dt) B = np.zeros((2, 1)) B[0] = 1 C = np.ones((1, 2)) D = np.ones((1,)) if zero == "C": C[...] = 0 elif zero == "D": D[...] = 0 num, den = ss2tf(A, B, C, D) num = num.flatten() synapse = LinearFilter(num, den, analog=False) t, x, yhat = run_synapse(Simulator, seed, synapse, dt=dt) y = synapse.filt(x, dt=dt, y0=0) assert allclose(t, y, yhat, delay=dt * 2 if zero == "D" else dt, atol=5e-5)
def test_ss2tf(): """test the function ss2tf""" with pytest.raises(ValueError): ss2tf(None, None, None, None, 5)
def __init__(self, ops, signals, config): super(LinearFilterBuilder, self).__init__(ops, signals, config) self.input_data = signals.combine([op.input for op in ops]) self.output_data = signals.combine([op.output for op in ops]) self.n_ops = len(ops) self.signal_d = ops[0].input.shape[0] As = [] Cs = [] Ds = [] # compute the A/C/D matrices for each operator for op in ops: A, B, C, D = tf2ss(op.process.num, op.process.den) if op.process.analog: # convert to discrete system A, B, C, D, _ = cont2discrete((A, B, C, D), signals.dt_val, method="zoh") # convert to controllable form num, den = ss2tf(A, B, C, D) if op.process.analog: # add shift num = np.concatenate((num, [[0]]), axis=1) with warnings.catch_warnings(): # ignore the warning about B, since we aren't using it anyway warnings.simplefilter("ignore", BadCoefficients) A, _, C, D = tf2ss(num, den) As.append(A) Cs.append(C[0]) Ds.append(D.item()) self.state_d = sum(x.shape[0] for x in Cs) # build a sparse matrix containing the A matrices as blocks # along the diagonal sparse_indices = [] corner = np.zeros(2, dtype=np.int64) for A in As: idxs = np.reshape( np.dstack( np.meshgrid(np.arange(A.shape[0]), np.arange(A.shape[1]), indexing="ij")), (-1, 2)) idxs += corner corner += A.shape sparse_indices += [idxs] sparse_indices = np.concatenate(sparse_indices, axis=0) self.A = signals.constant(np.concatenate(As, axis=0).flatten(), dtype=signals.dtype) self.A_indices = signals.constant( sparse_indices, dtype=(tf.int32 if np.all( sparse_indices < np.iinfo(np.int32).max) else tf.int64)) self.A_shape = tf.constant(corner, dtype=tf.int64) if np.allclose(Cs, 0): self.C = None else: # add empty dimension for broadcasting self.C = signals.constant(np.concatenate(Cs)[:, None], dtype=signals.dtype) if np.allclose(Ds, 0): self.D = None else: # add empty dimension for broadcasting self.D = signals.constant(np.asarray(Ds)[:, None], dtype=signals.dtype) self.offsets = tf.expand_dims(tf.range(0, len(ops) * As[0].shape[0], As[0].shape[0]), axis=1) # create a variable to represent the internal state of the filter self.state_sig = signals.make_internal( "state", (self.state_d, signals.minibatch_size * self.signal_d), minibatched=False)
def test_linearfilter(ctx, n_per_kind, rng): kinds = ( nengo.synapses.LinearFilter((2.0, ), (1.0, ), analog=False), nengo.synapses.Lowpass(0.005), nengo.synapses.Alpha(0.005), ) assert len(n_per_kind) == len(kinds) kinds_n = [(kind, n) for kind, n in zip(kinds, n_per_kind) if n > 0] dt = 0.001 steps = list() for kind, n in kinds_n: state = kind.make_state((n, ), (n, ), dt, dtype=np.float32) step = kind.make_step((n, ), (n, ), dt, rng=None, state=state) steps.append(step) # Nengo 3 uses state space filters. For now, convert back to transfer function. # Getting rid of this conversion would require a new plan_linearfilter. dens = list() nums = list() for f in steps: if type(f).__name__ == "NoX": # special case for a feedthrough den = np.array([1.0]) num = f.D else: num, den = ss2tf(f.A, f.B, f.C, f.D) # This preprocessing copied out of nengo2.8/synapses.LinearFilter.make_step num = num.flatten() assert den[0] == 1.0 num = num[1:] if num[0] == 0 else num den = den[1:] # drop first element (equal to 1) num, den = num.astype(np.float32), den.astype(np.float32) dens.append(den) nums.append(num) A = RA(dens) B = RA(nums) X = RA([rng.normal(size=n) for kind, n in kinds_n]) Y = RA([np.zeros(n) for kind, n in kinds_n]) Xbuf = RA([np.zeros(shape) for shape in zip(B.sizes, X.sizes)]) Ybuf = RA([np.zeros(shape) for shape in zip(A.sizes, Y.sizes)]) queue = cl.CommandQueue(ctx) clA = CLRA(queue, A) clB = CLRA(queue, B) clX = CLRA(queue, X) clY = CLRA(queue, Y) clXbuf = CLRA(queue, Xbuf) clYbuf = CLRA(queue, Ybuf) n_calls = 3 plans = plan_linearfilter(queue, clX, clY, clA, clB, clXbuf, clYbuf) with Timer() as timer: for _ in range(n_calls): for plan in plans: plan() print(timer.duration) for i, [kind, n] in enumerate(kinds_n): n = min(n, 100) state = kind.make_state((n, ), (n, ), dt, dtype=np.float32) step = kind.make_step((n, ), (n, ), dt, rng=None, state=state) x = X[i][:n].T y = np.zeros_like(x) for _ in range(n_calls): y[:] = step(0, x) z = clY[i][:n].T assert np.allclose(z, y, atol=1e-7, rtol=1e-5), kind
def __init__(self, ops, signals, config): super(LinearFilterBuilder, self).__init__(ops, signals, config) self.input_data = signals.combine([op.input for op in ops]) self.output_data = signals.combine([op.output for op in ops]) self.n_ops = len(ops) self.signal_d = ops[0].input.shape[0] As = [] Cs = [] Ds = [] # compute the A/C/D matrices for each operator for op in ops: A, B, C, D = tf2ss(op.process.num, op.process.den) if op.process.analog: # convert to discrete system A, B, C, D, _ = cont2discrete((A, B, C, D), signals.dt_val, method="zoh") # convert to controllable form num, den = ss2tf(A, B, C, D) if op.process.analog: # add shift num = np.concatenate((num, [[0]]), axis=1) with warnings.catch_warnings(): # ignore the warning about B, since we aren't using it anyway warnings.simplefilter("ignore", BadCoefficients) A, _, C, D = tf2ss(num, den) As.append(A) Cs.append(C[0]) Ds.append(D.item()) self.state_d = sum(x.shape[0] for x in Cs) # build a sparse matrix containing the A matrices as blocks # along the diagonal sparse_indices = [] corner = np.zeros(2, dtype=np.int64) for A in As: idxs = np.reshape(np.dstack(np.meshgrid( np.arange(A.shape[0]), np.arange(A.shape[1]), indexing="ij")), (-1, 2)) idxs += corner corner += A.shape sparse_indices += [idxs] sparse_indices = np.concatenate(sparse_indices, axis=0) self.A = signals.constant(np.concatenate(As, axis=0).flatten(), dtype=signals.dtype) self.A_indices = signals.constant(sparse_indices, dtype=( tf.int32 if np.all(sparse_indices < np.iinfo(np.int32).max) else tf.int64)) self.A_shape = tf.constant(corner, dtype=tf.int64) if np.allclose(Cs, 0): self.C = None else: # add empty dimension for broadcasting self.C = signals.constant(np.concatenate(Cs)[:, None], dtype=signals.dtype) if np.allclose(Ds, 0): self.D = None else: # add empty dimension for broadcasting self.D = signals.constant(np.asarray(Ds)[:, None], dtype=signals.dtype) self.offsets = tf.expand_dims( tf.range(0, len(ops) * As[0].shape[0], As[0].shape[0]), axis=1) # create a variable to represent the internal state of the filter self.state_sig = signals.make_internal( "state", (self.state_d, signals.minibatch_size * self.signal_d), minibatched=False)