예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
def test_ss2tf():
    """test the function ss2tf"""
    with pytest.raises(ValueError):
        ss2tf(None, None, None, None, 5)
예제 #4
0
    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
예제 #6
0
    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)