def test_check_sys_equal(): assert not sys_equal(np.zeros(2), np.zeros(3)) assert s != z assert not z == s assert LinearSystem(5, analog=True) != LinearSystem(5, analog=False) with pytest.raises(ValueError): sys_equal(s, z) with pytest.raises(ValueError): ss_equal(s, z)
def test_check_sys_equal(): assert not sys_equal(np.ones(2), np.ones(3)) assert s != z assert not z == s assert LinearSystem(5, analog=True) != LinearSystem(5, analog=False) with pytest.raises(ValueError): sys_equal(s, z) with pytest.raises(ValueError): ss_equal(s, z)
def test_similarity_transform(): sys = Alpha(0.1) TA, TB, TC, TD = sys.transform(np.eye(2), np.eye(2)).ss A, B, C, D = sys2ss(sys) assert np.allclose(A, TA) assert np.allclose(B, TB) assert np.allclose(C, TC) assert np.allclose(D, TD) T = [[1, 1], [-0.5, 0]] rsys = sys.transform(T) assert ss_equal(rsys, sys.transform(T, inv(T))) TA, TB, TC, TD = rsys.ss assert not np.allclose(A, TA) assert not np.allclose(B, TB) assert not np.allclose(C, TC) assert np.allclose(D, TD) assert sys_equal(sys, (TA, TB, TC, TD)) length = 1000 dt = 0.001 x_old = np.asarray( [sub.impulse(length=length, dt=dt) for sub in sys]) x_new = np.asarray( [sub.impulse(length=length, dt=dt) for sub in rsys]) # dot(T, x_new(t)) = x_old(t) assert np.allclose(np.dot(T, x_new), x_old)
def test_canonical(): sys = ([1], [1], [1], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [1, 0]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 1]], [[0], [1]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 1]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 0]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 0]], [[0], [1]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0, 1], [0, 1, 1], [1, 0, 0]], [[0], [1], [-1]], [[1, 1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = nengo.Alpha(0.1) csys = canonical(sys, controllable=True) osys = canonical(sys, controllable=False) assert ss_equal(csys, LinearSystem(sys).controllable) assert ss_equal(osys, LinearSystem(sys).observable) assert sys_equal(csys, osys) assert not ss_equal(csys, osys) # different state-space realizations A, B, C, D = csys.ss assert sys_equal(csys, sys) assert ss_equal(csys, ([[-20, -100], [1, 0]], [[1], [0]], [[0, 100]], [[0]])) assert sys_equal(osys, sys) assert ss_equal(osys, ([[-20, 1], [-100, 0]], [[0], [100]], [[1, 0]], [[0]]))
def test_canonical(): sys = ([1], [1], [1], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [1, 0]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 1]], [[0], [1]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 1]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 0]], [[1], [0]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0], [0, 0]], [[0], [1]], [[1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = ([[1, 0, 1], [0, 1, 1], [1, 0, 0]], [[0], [1], [-1]], [[1, 1, 1]], [0]) assert sys_equal(canonical(sys), sys) sys = nengo.Alpha(0.1) csys = canonical(sys, controllable=True) osys = canonical(sys, controllable=False) assert sys_equal(csys, osys) assert not ss_equal(csys, osys) # different state-space realizations A, B, C, D = csys.ss assert sys_equal(csys, sys) assert ss_equal(csys, ([[-20, -100], [1, 0]], [[1], [0]], [[0, 100]], [[0]])) assert sys_equal(osys, sys) assert ss_equal(osys, ([[-20, 1], [-100, 0]], [[0], [100]], [[1, 0]], [[0]]))
def test_linear_system(): tau = 0.05 sys = Lowpass(tau) dsys = (1 - np.exp(-1)) * z / (1 - np.exp(-1) * z) # Test attributes before state-space/zpk computed assert sys.is_tf assert not sys.is_ss assert not sys.is_zpk # Test representations assert sys == (1, [tau, 1]) assert sys_equal(sys.tf, sys) assert sys_equal(sys.ss, sys) assert sys_equal(sys.zpk, sys) # Test attributes after state-space/zpk computed assert sys.is_tf assert sys.is_ss assert sys.is_zpk # Test attributes assert np.allclose(sys.num, (1,)) assert np.allclose(sys.den, (tau, 1)) assert sys.causal assert sys.proper assert not sys.has_passthrough assert not (sys/s).has_passthrough assert (sys*s).has_passthrough assert (sys*s).causal assert not (sys*s).proper assert not (sys*s*s).has_passthrough and not (sys*s*s).causal assert (sys*s*s + sys*s).has_passthrough assert np.allclose(sys.A, -1/tau) assert np.allclose(sys.B, 1) assert np.allclose(sys.C, 1/tau) assert np.allclose(sys.D, 0) assert np.allclose(sys.zeros, [0]) assert np.allclose(sys.poles, [-1/tau]) assert np.allclose(sys.gain, 1/tau) assert sys.order_num == 0 assert sys.order_den == 1 assert len(sys) == 1 # order_den assert len(LinearSystem(sys.ss)) == 1 # uses state-space rep # Test dcgain and __call__ assert np.allclose(sys.dcgain, 1) assert np.allclose(dsys.dcgain, 1) assert np.allclose((s*sys)(1e12), 1.0 / tau) # initial value theorem assert np.allclose((s*sys)(0), 0) # final value theorem assert np.allclose(((1 - ~z)*dsys)(1), 0) # final value theorem # Test multiplication and squaring assert sys*2 == 2*sys assert (0.4*sys) + (0.6*sys) == sys assert sys + sys == 2*sys assert sys * sys == sys**2 assert sys_equal(sys + sys*sys, sys*sys + sys) # Test pow with pytest.raises(TypeError): sys**0.5 assert sys**0 == LinearSystem(1) # Test inversion inv = ~sys assert inv == ([tau, 1], 1) assert not inv.causal assert inv == 1 / sys assert inv == sys**(-1) # Test repr/str copy = eval( repr(sys), {}, {'LinearSystem': LinearSystem, 'array': np.array}) assert copy == sys assert str(copy) == str(sys) # Test addition/subtraction assert sys + 2 == ((2*tau, 3), (tau, 1)) assert 3 + sys == (-sys)*(-1) + 3 assert (4 - sys) + 2 == (-sys) + 6 assert np.allclose((sys - sys).num, 0) # Test division assert sys / 2 == sys * 0.5 assert 2 / sys == 2 * inv cancel = sys / sys assert np.allclose(cancel.num, cancel.den) # Test inequality assert sys != (sys*2) # Test usage of differential building block assert sys == 1 / (tau*s + 1)
def test_sys_conversions(): sys = Alpha(0.1) tf = sys2tf(sys) ss = sys2ss(sys) zpk = sys2zpk(sys) assert sys_equal(sys2ss(tf), ss) assert sys_equal(sys2ss(ss), ss) # unchanged assert sys_equal(sys2tf(tf), tf) # unchanged assert sys_equal(sys2tf(ss), tf) assert sys_equal(sys2zpk(zpk), zpk) # sanity check assert sys_equal(sys2zpk(tf), zpk) # sanity check assert sys_equal(sys2zpk(ss), zpk) assert sys_equal(sys2tf(zpk), tf) assert sys_equal(sys2ss(zpk), ss) # should also work with nengo's synapse types assert sys_equal(sys2zpk(nengo.Alpha(0.1)), zpk) assert sys_equal(sys2tf(nengo.Alpha(0.1)), tf) assert sys_equal(sys2ss(nengo.Alpha(0.1)), ss) # system can also be just a scalar assert sys_equal(sys2tf(2.0), (1, 0.5)) assert np.allclose(sys2ss(5)[3], 5) assert sys_equal(sys2zpk(5), 5) with pytest.raises(ValueError): sys2ss(np.zeros(5)) with pytest.raises(ValueError): sys2zpk(np.zeros(5)) with pytest.raises(ValueError): sys2tf(np.zeros(5)) with pytest.raises(ValueError): # _ss2tf(...): passthrough must be single element sys2tf(([], [], [], [1, 2]))
def test_linear_system(): tau = 0.05 sys = Lowpass(tau) dsys = (1 - np.exp(-1)) * z / (1 - np.exp(-1) * z) # Test attributes before state-space/zpk computed assert sys.is_tf assert not sys.is_ss assert not sys.is_zpk # Test representations assert sys == (1, [tau, 1]) assert sys_equal(sys.tf, sys) assert sys_equal(sys.ss, sys) assert sys_equal(sys.zpk, sys) # Test attributes after state-space/zpk computed assert sys.is_tf assert sys.is_ss assert sys.is_zpk # Size in/out-related properties assert sys.is_SISO assert dsys.is_SISO assert sys.size_in == sys.size_out == dsys.size_in == dsys.size_out == 1 # Test attributes assert np.allclose(sys.num, (1/tau,)) assert np.allclose(sys.den, (1, 1/tau)) assert sys.causal assert sys.strictly_proper assert not sys.has_passthrough assert not (sys/s).has_passthrough assert (sys*s).has_passthrough assert (sys*s).causal assert not (sys*s).strictly_proper assert not (sys*s*s).has_passthrough and not (sys*s*s).causal assert (sys*s*s + sys*s).has_passthrough assert np.allclose(sys.A, -1/tau) assert np.allclose(sys.B, 1) assert np.allclose(sys.C, 1/tau) assert np.allclose(sys.D, 0) assert np.allclose(sys.zeros, [0]) assert np.allclose(sys.poles, [-1/tau]) assert np.allclose(sys.gain, 1/tau) assert np.allclose(sys.zpk[0], np.array([])) assert np.allclose(sys.zpk[1], np.array([-1/tau])) assert np.allclose(sys.zpk[2], 1/tau) assert sys.order_num == 0 assert sys.order_den == 1 assert len(sys) == 1 # order_den assert len(LinearSystem(sys.ss)) == 1 # uses state-space rep # Test dcgain and __call__ assert np.allclose(sys.dcgain, 1) assert np.allclose(dsys.dcgain, 1) assert np.allclose((s*sys)(1e12), 1.0 / tau) # initial value theorem assert np.allclose((s*sys)(0), 0) # final value theorem assert np.allclose(((1 - ~z)*dsys)(1), 0) # final value theorem # Test multiplication and squaring assert sys*2 == 2*sys assert (0.4*sys) + (0.6*sys) == sys assert sys + sys == 2*sys assert sys * sys == sys**2 assert sys_equal(sys + sys*sys, sys*sys + sys) # Test pow with pytest.raises(TypeError): sys**0.5 assert sys**0 == LinearSystem(1) # Test inversion inv = ~sys assert inv == ([tau, 1], 1) assert not inv.causal assert inv == 1 / sys assert inv == sys**(-1) # Test repr/str copy = _eval(sys) assert copy == sys # Test addition/subtraction assert sys + 2 == ((2*tau, 3), (tau, 1)) assert 3 + sys == (-sys)*(-1) + 3 assert (4 - sys) + 2 == (-sys) + 6 assert np.allclose((sys - sys).num, 0) # Test division assert sys / 2 == sys * 0.5 assert 2 / sys == 2 * inv cancel = sys / sys assert np.allclose(cancel.num, cancel.den) # Test inequality assert sys != (sys*2) # Test usage of differential building block assert sys == 1 / (tau*s + 1)