def test_for_constant_signal(): size = 1000 Ts = 0.1 coef = np.ones(size) * 0.7 vector = np.array([1., 0, 0]) inp = system.Input(Ts, coefficients=coef, steeringVector=vector) A = np.eye(3, k=-1) c = np.eye(3) sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(3) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(3)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) plt.figure() plt.plot(t, coef, label="u") plt.plot(t, u_hat, label="u_hat") plt.legend()
def test_postFiltering(): size = 10000 order = 4 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., Ts * (size - 1), size) res = sim.simulate(t, [inp]) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) bandwith = 2 * np.pi * frequency * 1e-2 print("Bandwith = %s" % bandwith) postFilterTF = filters.TransferFunction() postFilterTF.butterWorth(2, (bandwith, )) print(postFilterTF.a, postFilterTF.b) postFilter = filters.Filter() postFilter.tf2lssObservableForm(postFilterTF.b, postFilterTF.a) print("Filter A = \n%s" % postFilter.A) print(postFilter.b) print(postFilter.c) recon = reconstruction.WienerFilterWithPostFiltering( t, sys, (inp, ), postFilter) u_hat, log = recon.filter(ctrl) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.legend()
def testSystem(): A = np.array([[1., 0], [2., 1.]]) c = np.array([[1., 0], [0, 1]]) sys = system.System(A, c) # Test str function print(sys) f = sys.frequencyResponse(0.) state = np.array([3, 2]) output = sys.output(state) np.testing.assert_array_equal(state, output)
def test_lowering_order(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) u_hats = [] for index in range(1, order + 1): newSystem, newControl, newInput = system.LowerOrderSystem( sys, ctrl, inp, index) recon = reconstruction.WienerFilter(t, newSystem, (newInput, )) u_hat, log = recon.filter(newControl) u_hats.append(u_hat) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") for index in range(order): plt.plot(t, u_hats[index], label="u_hat_%i" % (index + 1)) plt.legend()
def test_evaluate_PlotTransferFunctions(): size = 10000 order = 7 Ts = 0.1 beta = 5. coef = np.random.rand(size) * 2. - 1. vector = np.zeros(order) vector[0] = 2. inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) T = 40 t = 10 ** (T/10.) rho = np.power(t, 1./order)/beta * np.sqrt(2) A = beta * np.eye(order, k=-1) - rho * np.eye(order, k=0) c = np.eye(order) sys = system.System(A, c) mixingMatrix = - 1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp,)) u_hat, log = recon.filter(ctrl) ev = evaluation.Evaluation(sys, u_hat, (inp,)) freqsLim = [1e-2, 1e2] figure1 = ev.PlotTransferFunctions(freqsLim) figure2 = ev.PlotPowerSpectralDensity(t)
def test_for_sinusodial_signal(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.legend()
def test_integratorChain(): size = 1000 Ts = 0.1 coef = np.ones(size) vector = np.array([1., 0, 0]) inp = system.Input(Ts, coefficients=coef, steeringVector=vector) A = np.eye(3, k=-1) c = np.eye(3) sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(3) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(3)])
def testSystemSetup(): size = 1000 Ts = 0.1 coef = np.random.rand(size) vector = np.array([1., 0, 0]) inp = system.Input(Ts, coefficients=coef, steeringVector=vector) A = np.random.rand(3, 3) c = np.eye(3) sys = system.System(A, c) mixingMatrix = -np.eye(3) ctrl = system.Control(mixingMatrix, size) return { 'size': size, 'Ts': Ts, 'inp': inp, 'sys': sys, 'ctrl': ctrl, }
def test_for_first_order_filter_signal(): size = 10000 order = 7 Ts = 0.1 coef = np.random.rand(size) * 2. - 1. vector = np.zeros(order) vector[0] = 1. inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) reconP = reconstruction.ParallelWienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) u_hatP = reconP.filter(ctrl) plt.figure() plt.plot(t, coef, label="coef") plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.plot(t, u_hatP, label="u_hatP") plt.legend()
def test_noisy_integratorChain(): size = 1000 Ts = 0.1 order = 3 coef = np.ones(size) vector = np.array([1., 0, 0]) inp = system.Input(Ts, coefficients=coef, steeringVector=vector) A = np.eye(3, k=-1) c = np.eye(3) noiseVariance = np.ones(3) * 1e-4 noiseSources = [] for index in range(order): if noiseVariance[index] > 0: vector = np.zeros(order) vector[index] = 1 noiseSources.append({ "std": np.sqrt(noiseVariance[index]), "steeringVector": vector, "name": "Noise Source %s" % index }) options = {'noise': noiseSources} sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(3) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl, options=options) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(3)])
def test_for_noise_simulation(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) noiseVariance = np.ones(order) * 1e-4 noiseSources = [] for index in range(order): if noiseVariance[index] > 0: vector = np.zeros(order) vector[index] = 1 noiseSources.append({ "std": np.sqrt(noiseVariance[index]), "steeringVector": vector, "name": "Noise Source %s" % index }) options = {'noise': noiseSources} sim = simulator.Simulator(sys, ctrl, options=options) t = np.linspace(0., 99., size) res = sim.simulate(t, [inp]) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) recon_with_noise = reconstruction.WienerFilter(t, sys, [inp], options=options) recon_with_noise_Parallel = reconstruction.ParallelWienerFilter( t, sys, [inp], options=options) u_hat, log = recon.filter(ctrl) u_hat_with_noise, log_with_noise = recon_with_noise.filter(ctrl) u_hat_with_noise_Parallel = recon_with_noise_Parallel.filter(ctrl) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.plot(t, u_hat_with_noise, label="u_hat_with_noise") plt.plot(t, u_hat_with_noise_Parallel, label="u_hat_with_noise_Parallel") plt.legend()
def piBlockSystem1(): start_time = time.time() size = 20000 # Number of samples in the simulation M = (1 << 0) # Number of parallel controlnverters N = 2 # Number of PI mixing submatrices Ts = 8e-5 # Sampling period num_inputs = 1 t = np.linspace(0, (size - 1) * Ts, size) # Time grid for control updates beta = 6250 kappa = 1 stability = Ts * beta * (1 / np.sqrt(M) + kappa) <= 1 print("Stability margin: {}".format(1. - Ts * beta * (1 / np.sqrt(M) + kappa))) print("Stability criterion: {}".format(stability)) H = hadamardMatrix(M) L = 1 A = np.zeros(((N + 1) * M, (N + 1) * M)) MixingPi = np.empty((N, M, M)) for k in range(N): MixingPi[k] = beta * np.outer(H[:, 0], H[:, 0]) # (beta)*(0.2*np.outer(H[:,0],H[:,0]) # + 0.1*np.outer(H[:,1],H[:,1]) # + 0.3*np.outer(H[:,2],H[:,2]) # + 0.4*np.outer(H[:,3],H[:,3])) # Index set = {0,0} A[(k + 1) * M:(k + 2) * M, (k) * M:(k + 1) * M] = MixingPi[k] nperseg = (1 << 16) selected_FFT_bin = 250. input_signals = [] frequencies = [] # sins = np.empty((M,size)) for i in range(num_inputs): amplitude = 1 frequency = (i + 1) * (selected_FFT_bin / (nperseg * Ts)) print("{} Hz".format(frequency)) # size = frequencies.append(frequency) phase = 0 vector = np.zeros((N + 1) * M) vector[0:M] = beta * (H[:, i]) input_signals.append( system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector)) input_signals = tuple(input_signals) print("A = \n%s\nb = \n%s" % (A, vector)) checkCovarianceMatrixConvergence(A, vector) checkCovarianceMatrixConvergence(-A, vector) c = np.eye((N + 1) * M) sys = system.System(A, c) mixingMatrix = -kappa * beta * np.eye((N + 1) * M) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl, options={ 'stateBound': (Ts * beta * kappa) / (1. - Ts * beta) + 1., 'noise': [{ 'std': 1e-6, 'steeringVector': beta * np.eye((N + 1) * M)[:, i], 'name': 'Bastard' } for i in range((N + 1) * M)] }) res = sim.simulate(t, input_signals) # plt.figure() # plt.plot(res['t'], res['output']) # plt.legend(["%s" % x for x in range(res['output'].shape[0])]) # plt.show() eta2 = np.ones((N + 1) * M) * 1e5 options = { 'eta2': eta2, 'sigmaU2': [1.], 'noise': [{ 'std': 1e-6, 'steeringVector': beta * np.eye((N + 1) * M)[:, i], 'name': 'Bastard' } for i in range((N + 1) * M)] } recon = reconstruction.WienerFilter(t, sys, input_signals, options) input_estimates, recon_log = recon.filter(ctrl) print("Run Time: {} seconds".format(time.time() - start_time)) nfft = (1 << 16) spectrums = np.empty((num_inputs, nfft // 2 + 1)) for i in range(num_inputs): freq, spec = signal.welch(input_estimates[:, i], 1. / Ts, axis=0, nperseg=nperseg, nfft=nfft, scaling='density') spectrums[i, :] = spec plt.figure() [ plt.semilogx(freq, 10 * np.log10(np.abs(spec)), label="") for spec in spectrums ] plt.grid() plt.title("Block diagonal Pi System")
def test_evaluate_PlotTransferFunctions_For_PostFiltering(): size = 10000 order = 2 postFilterOrder = 2 Ts = 0.1 eta2 = 1e-6 filterEta2 = 1e-0 amplitude = 1. frequency = 1e-1 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) # coef = np.random.rand(size) * 2. - 1. # vector = np.zeros(order) # vector[0] = 2. # inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) A = 2 * np.eye(order, k=-1, dtype=np.float) # make causal filter A += 0. * np.eye(order, k=0) c = np.eye(order, dtype=np.float) sys = system.System(A, c) mixingMatrix = - 1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) # System 1 recon = reconstruction.WienerFilter(t, sys, (inp,), {"eta2":eta2*np.ones(order)}) u_hat, log = recon.filter(ctrl) ev = evaluation.Evaluation(sys, u_hat, (inp,)) # Post Filtering bandwith = 2 * np.pi * 1e-1 print("Bandwith = %s" % bandwith) postFilterTF = filters.TransferFunction() postFilterTF.butterWorth(postFilterOrder, (bandwith)) postFilterElliptic = filters.TransferFunction() postFilterElliptic.iirFilter(postFilterOrder, (bandwith,), 'ellip') postFilterCheby1 = filters.TransferFunction() postFilterCheby1.iirFilter(postFilterOrder, (bandwith,), 'cheby1') postFilterCheby2 = filters.TransferFunction() postFilterCheby2.iirFilter(postFilterOrder, (bandwith,), 'cheby2') postFilterBessel = filters.TransferFunction() postFilterBessel.iirFilter(postFilterOrder, (bandwith,), 'bessel') plt.figure() w1, h1 = postFilterTF.frequencyResponse() w2, h2 = postFilterElliptic.frequencyResponse() w3, h3 = postFilterCheby1.frequencyResponse() w4, h4 = postFilterCheby2.frequencyResponse() w5, h5 = postFilterBessel.frequencyResponse() plt.semilogx(w1/np.pi/2., 20 * np.log10(abs(h1)), label="Butterworth") plt.semilogx(w2/np.pi/2., 20 * np.log10(abs(h2)), label="Elliptic") plt.semilogx(w3/np.pi/2., 20 * np.log10(abs(h3)), label="Cheby 1") plt.semilogx(w4/np.pi/2., 20 * np.log10(abs(h4)), label="Cheby 2") plt.semilogx(w5/np.pi/2., 20 * np.log10(abs(h5)), label="Bessel") plt.legend() plt.xlabel('Frequency [Hz]') plt.ylabel('Amplitude response [dB]') plt.grid() # plt.show() # print(postFilterTF.a, postFilterTF.b) postFilter1 = filters.Filter() postFilter2 = filters.Filter() postFilter3 = filters.Filter() postFilter4 = filters.Filter() postFilter5 = filters.Filter() postFilter1.tf2lssObservableForm(postFilterTF.b, postFilterTF.a) postFilter2.tf2lssObservableForm(postFilterElliptic.b, postFilterElliptic.a) postFilter3.tf2lssObservableForm(postFilterCheby1.b, postFilterCheby1.a) postFilter4.tf2lssObservableForm(postFilterCheby2.b, postFilterCheby2.a) postFilter5.tf2lssObservableForm(postFilterBessel.b, postFilterBessel.a) # eta2PostFilter = np.concatenate((eta2 * np.ones(order), filterEta2 * np.ones(postFilter.c.shape[1]))) eta2PostFilter = eta2 * np.ones(order) reconstructionFiltered1 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter1, {"eta2":eta2PostFilter}) reconstructionFiltered2 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter2, {"eta2":eta2PostFilter}) reconstructionFiltered3 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter3, {"eta2":eta2PostFilter}) reconstructionFiltered4 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter4, {"eta2":eta2PostFilter}) reconstructionFiltered5 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter5, {"eta2":eta2PostFilter}) print(ctrl.mixingMatrix) u_hatP_1, log_1 = reconstructionFiltered1.filter(ctrl) print(ctrl.mixingMatrix) print(postFilter2) u_hatP_2, log_2 = reconstructionFiltered2.filter(ctrl) u_hatP_3, log_3 = reconstructionFiltered3.filter(ctrl) u_hatP_4, log_4 = reconstructionFiltered4.filter(ctrl) u_hatP_5, log_5 = reconstructionFiltered5.filter(ctrl) evP1 = evaluation.Evaluation(sys, u_hatP_1, (inp,)) evP2 = evaluation.Evaluation(sys, u_hatP_2, (inp,)) evP3 = evaluation.Evaluation(sys, u_hatP_3, (inp,)) evP4 = evaluation.Evaluation(sys, u_hatP_4, (inp,)) evP5 = evaluation.Evaluation(sys, u_hatP_5, (inp,)) freqsLim = [1e-2, 1e2] # figure1 = ev.PlotTransferFunctions(freqsLim) figure2 = ev.PlotPowerSpectralDensity(t) # figure3 = ev2.PlotTransferFunctions(freqsLim) figure4 = evP1.PlotPowerSpectralDensity(t) figure5 = evP2.PlotPowerSpectralDensity(t) figure6 = evP3.PlotPowerSpectralDensity(t) figure7 = evP4.PlotPowerSpectralDensity(t) figure8 = evP5.PlotPowerSpectralDensity(t) plt.figure() plt.plot(u_hat, label="u_hat") # plt.plot(u_hatP_1, label="Butter") # plt.plot(u_hatP_2, label="Elliptic") plt.plot(u_hatP_3, label="Chebyshev 1") # plt.plot(u_hatP_4, label="Chebychev 2") plt.plot(u_hatP_5, label="Bessel") # plt.plot(u_hat - u_hat2, label="diff") plt.legend()
def test_evaluate_WithNoise(): size = 10000 order = 5 Ts = 0.0001 eta2 = 1e-4 beta = 1000. noiseVariance = np.ones(order) * 1e-12 noiseSources = [] for index in range(order): if noiseVariance[index]>0: vector = np.zeros(order) vector[index] = beta noiseSources.append( { "std": np.sqrt(noiseVariance[index]), "steeringVector": vector, "name": "Noise Source %s" % index } ) options = { 'noise': noiseSources, 'eta2': eta2 * np.ones(order) } # options = {} # options2 = { # # 'noise': {"standardDeviation": np.sqrt(noiseVariance) * np.array([1./(order - x)**3 for x in range(order)])}, # 'noise': {"standardDeviation": 1e-4 * np.array([1. for x in range(order)])}, # 'eta2': eta2 * np.ones(order) # } # options['noise']['standardDeviation'][5] = 1e-1 amplitude = 1. * 1e-6 frequency = 1e2 / (2. * np.pi) phase = np.pi * 7. / 8. vector = np.ones(order) * beta / 2. # vector = np.zeros(order) vector[0] = beta inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) # coef = np.random.rand(size) * 2. - 1. # vector = np.zeros(order) # vector[0] = beta # inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) # T = 120 # t = 10 ** (T/10.) # rho = np.power(t, 1./order)/beta * np.sqrt(2) rho = 0. A = beta/2. * np.eye(order, k=-1) - rho * np.eye(order, k=0) # A[0, :] =-np.ones(order) * beta/2. print(A) # A = 1e-2 * np.eye(order, k=-1) - rho * np.eye(order, k=0) # A = np.zeros((order, order)) # A = np.random.randn(order, order) # A = np.dot(A, np.linalg.inv(np.diag(np.sum(np.abs(A), axis=1)))) # print(A) # A = 9. * np.eye(order, k=-1, dtype=np.float) # make causal filter # A += 0. * np.eye(order, k=0) c0 = np.zeros(order, dtype=np.float).reshape((order,1)) c0[-1] = 1. c = np.eye(order, dtype=np.float) sys0 = system.System(A, c0) sys = system.System(A, c) mixingMatrix = - 10.5 * np.eye(order) ctrl = system.Control(mixingMatrix, size) ctrl0 = system.Control(mixingMatrix, size) sim0 = simulator.Simulator(sys0, ctrl0, options=options) sim = simulator.Simulator(sys, ctrl, options=options) t = np.linspace(0., Ts * (size - 1) , size) u = inp.scalarFunction(t) # res2 = sim0.simulate(t, (inp,)) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) # System 1 reconSISO = reconstruction.WienerFilter(t, sys0, (inp,), {"eta2":np.array(eta2)}) reconSIMO = reconstruction.WienerFilter(t, sys, (inp,), {"eta2":eta2 * np.ones(order)}) reconMIMO = reconstruction.WienerFilter(t, sys, [inp], options) u_hatSISO, log_SISO = reconSISO.filter(ctrl) u_hatSIMO, log_SIMO = reconSIMO.filter(ctrl) u_hatMIMO, log_MIMO = reconMIMO.filter(ctrl) print(reconSISO) ev_SISO = evaluation.Evaluation(sys, u_hatSISO, (inp,)) ev_SIMO = evaluation.Evaluation(sys, u_hatSIMO, (inp,)) ev_MIMO = evaluation.Evaluation(sys, u_hatMIMO, (inp,)) freqsLim = [1e-2, 1e2] freq, SISOSPECTRUM, SIGNALSPECTRUM = ev_SISO.PowerSpectralDensity(t) _, SIMOSPECTRUM, _ = ev_SIMO.PowerSpectralDensity(t) _, MIMOSPECTRUM, _ = ev_MIMO.PowerSpectralDensity(t) plt.figure() plt.semilogx(freq, 10 * np.log10(np.abs(SIGNALSPECTRUM[0].flatten())), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(SISOSPECTRUM.flatten())), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(SIMOSPECTRUM.flatten())), label="u_hatSIMO") plt.semilogx(freq, 10 * np.log10(np.abs(MIMOSPECTRUM[:, 0].flatten())), label="u_hatMIMO") plt.legend() plt.figure() plt.plot(u, label="u") plt.plot(u_hatSISO, label="u_hatSISO") plt.plot(u_hatSIMO, label="u_hatSIMO") plt.plot(u_hatMIMO, label="u_hatMIMO") plt.legend() plt.figure() plt.plot(u_hatSISO.flatten() - u.flatten(), label="u_hatSISO") plt.plot(u_hatSIMO.flatten() - u.flatten(), label="u_hatSIMO") plt.plot(u_hatMIMO[:,0] - u.flatten(), label="u_hatMIMO") plt.legend() plt.figure() freq, u_hatSISOSP = signal.welch(u_hatSISO.flatten() - u.flatten(), 1./Ts) _, u_hatSIMOSP = signal.welch(u_hatSIMO.flatten() - u.flatten(), 1./Ts) _, u_hatMIMOSP = signal.welch(u_hatMIMO[:,0] - u.flatten(), 1./Ts) plt.semilogx(freq, 10 * np.log10(np.abs(u_hatSISOSP)), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(u_hatSIMOSP)), label="u_hatSIMO") plt.semilogx(freq, 10 * np.log10(np.abs(u_hatMIMOSP)), label="u_hatMIMO") plt.legend() figure1 = ev_SISO.PlotTransferFunctions(freqsLim)
def __init__(self, experiment_id, data_dir, M, N, L, input_phase, input_amplitude, input_frequency=None, beta=6250, sampling_period=8e-5, primary_signal_dimension=0, systemtype='ParallelIntegratorChain', OSR=16, eta2_magnitude=1, kappa=1, sigma2_thermal=1e-6, sigma2_reconst=1e-6, num_periods_in_simulation=100, controller='subspaceController', bitsPerControl=1): print("Initializing Experiment | ID: %s" % experiment_id) self.experiment_id = experiment_id self.data_dir = Path(data_dir) self.M = M self.N = N self.L = L self.input_phase = input_phase self.input_amplitude = input_amplitude self.input_frequency = input_frequency self.beta = beta self.sampling_period = sampling_period self.primary_signal_dimension = primary_signal_dimension self.systemtype = systemtype self.OSR = OSR self.kappa = kappa self.sigma2_thermal = sigma2_thermal self.sigma2_reconst = sigma2_reconst self.num_periods_in_simulation = num_periods_in_simulation self.size = round(num_periods_in_simulation / sampling_period) self.controller = controller self.bitsPerControl = bitsPerControl self.border = np.int(self.size // 100) self.all_input_signal_amplitudes = np.zeros(L) self.all_input_signal_amplitudes[ primary_signal_dimension] = input_amplitude self.logstr = ("{0}: EXPERIMENT LOG\n{0}: Experiment ID: {1}\n".format( time.strftime("%d/%m/%Y %H:%M:%S"), experiment_id)) self.finished_simulation = False self.finished_reconstruction = False if not self.data_dir.exists(): self.data_dir.mkdir(parents=True) ################################################# # System and input signal specifications # ################################################# if self.primary_signal_dimension > self.M: self.log( "Primary Signal Dimension cannot be larger than M, setting to 0 (first dim)" ) self.primary_signal_dimension = 0 if self.input_frequency == None: self.input_frequency = 1. / (self.sampling_period * 2 * self.OSR) self.log(f'Setting f_sig = f_s/(2*OSR) = {self.input_frequency}') if self.systemtype == "ParallelIntegratorChain": self.A = np.zeros((self.N * self.M, self.N * self.M)) mixingPi = np.zeros((self.N - 1, self.M, self.M)) H = hadamardMatrix(self.M) if N > 1: # L=1 means just one of M dimensions is used and there is # only one input signal => We scale up the input vector by sqrt(M) if L == 1: for k in range(N - 1): mixingPi[k] = beta * np.sqrt(M) * ( np.outer(H[:, 0], H[:, 0]) ) # + beta * np.sqrt(M) * sum(np.outer(H[:,i],H[:,i]) for i in range(1,self.M)) * 1e-3 self.A[(k + 1) * self.M:(k + 2) * self.M, (k) * self.M:(k + 1) * self.M] = mixingPi[k] # L=M means M input signals elif L == M: for k in range(N - 1): mixingPi[k] = self.beta * np.sqrt(M) * np.eye( M ) #(sum(np.outer(H[:,i],H[:,i]) for i in range(self.M))) self.A[(k + 1) * self.M:(k + 2) * self.M, (k) * self.M:(k + 1) * self.M] = mixingPi[k] else: for k in range(N - 1): mixingPi[k] = self.beta * np.sqrt(M / L) * (sum( np.outer(H[:, i], H[:, i]) for i in range(self.L))) self.A[(k + 1) * self.M:(k + 2) * self.M, (k) * self.M:(k + 1) * self.M] = mixingPi[k] # raise NotImplemented print("A = {}".format(self.A)) else: mixingPi = [np.zeros((M, M))] # Limit the low frequency gain of the filter # at approximately the thermal noise level LeakyIntegrators = True if LeakyIntegrators == True: self.rho = beta / ((sigma2_thermal)**(-1 / N)) self.A -= np.eye(N * M) * self.rho # Define input signals: self.input_signals = [] self.all_input_signal_frequencies = np.zeros(L) self.all_input_signal_frequencies[ self.primary_signal_dimension] = self.input_frequency allowed_signal_frequencies = self.input_frequency * ( 0.5**np.arange(1, 3 * M)) for i in range(self.L): if i == self.primary_signal_dimension: continue k = np.random.randint(0, L - 1) self.all_input_signal_frequencies[ i] = allowed_signal_frequencies[i] self.all_input_signal_amplitudes[i] = input_amplitude # Define input steeringVectors if L == 1: inputVectorMatrix = beta * np.sqrt(M) * H elif L == 2: # The outer product sum results in a checkerboard matrix with 1/0 entries. # We pick input vectors from there and scale up by M (undoing the attenuation from the outer products) inputVectorMatrix = beta * (M / 2) * (np.outer( H[:, 0], H[:, 0]) + np.outer(H[:, 1], H[:, 1])) * 2 elif L == M: inputVectorMatrix = beta * np.sqrt(M) * (np.hstack( (np.outer(H[:, i], H[:, i])[:, 0].reshape(-1, 1) for i in range(L)))) else: inputVectorMatrix = beta * np.sqrt(M / L) * H for i in range(self.L): vector = np.zeros(self.M * self.N) vector[0:self.M] = inputVectorMatrix[:, i] self.input_signals.append( system.Sin( self.sampling_period, amplitude=self.all_input_signal_amplitudes[i], frequency=self.all_input_signal_frequencies[i], phase=self.input_phase, #+ (np.pi/2)*i, steeringVector=vector)) print(f'b_{i} = {self.input_signals[i].steeringVector}') self.input_signals = tuple(self.input_signals) elif self.systemtype == "CyclicIntegratorChain": self.A = np.zeros((self.N * self.M, self.N * self.M)) mixingPi = np.zeros((self.N, self.M, self.M)) H = hadamardMatrix(self.M) self.all_input_signal_frequencies = np.zeros(L) self.all_input_signal_frequencies[ self.primary_signal_dimension] = self.input_frequency self.all_input_signal_amplitudes[ self.primary_signal_dimension] = self.input_amplitude if N > 1: if L == 1: # Start with the Pi_N, in the top right corner mixingPi[-1] = beta * np.sqrt(M) * sum( np.outer(H[:, i], H[:, i]) for i in range(self.N - 1)) self.A[0:self.M, -self.M:self.M * self.N] = mixingPi[-1] # Iterate just like before, down the first sub-diagonal, always summing over all but the k'th pi vector for k in range(N - 1): mixingPi[k] = beta * np.sqrt(M) * sum( np.outer(H[:, i], H[:, i]) for i in range(self.N) if i != k) self.A[(k + 1) * self.M:(k + 2) * self.M, (k) * self.M:(k + 1) * self.M] = mixingPi[k] else: raise NotImplemented else: mixingPi = [np.zeros((M, M))] # Define input signals: self.input_signals = [] if self.L == 1: selector = np.zeros(self.M) selector[0] = 1 vector = np.zeros(self.M * self.N) vector[0:self.M * self.N] = beta * np.sqrt(M) * np.dot( np.vstack( (np.outer(H[:, i], H[:, i]) for i in range(self.N))), selector.reshape(-1, 1)).flatten() self.input_signals.append( system.Sin(self.sampling_period, amplitude=self.input_amplitude, frequency=self.input_frequency, phase=self.input_phase, steeringVector=vector)) else: raise NotImplemented else: raise NotImplemented # pd.DataFrame(self.A).to_csv('A_matrix.csv') # print("A = \n%s\nb = \n%s" % (self.A, self.input_signals[self.primary_signal_dimension].steeringVector)) self.c = np.eye(self.N * self.M) self.sys = system.System( A=self.A, c=self.c, b=self.input_signals[primary_signal_dimension].steeringVector) systemResponse = lambda f: np.dot(self.sys.frequencyResponse(f), self. sys.b) self.eta2_magnitude = np.max( np.abs(systemResponse(1. / (2. * sampling_period * OSR)))**2) self.log("eta2_magnitude set to max(|G(s)b|^2) = {:.5e}".format( self.eta2_magnitude)) print("eta2_magnitude set to max(|G(s)b|^2) = {:.5e}".format( self.eta2_magnitude)) ################################################# # Controller specification # ################################################# dither = True """ The subspace controller is only implemented for L=1 signal right now. """ if controller == 'subspaceController': self.ctrlMixingMatrix = np.zeros((self.N * self.M, self.N)) # if L>1: # raise "Multi-Bit controller not implemented for L>1 input signals" if dither: self.ctrlMixingMatrix = ( np.random.randint(2, size=(N * M, N)) * 2 - 1) * beta * 1e-3 if L == 1: for i in range(N): self.ctrlMixingMatrix[ i * M:(i + 1) * M, i] = -np.sqrt(self.M) * self.beta * H[:, 0] else: raise NotImplemented # self.ctrlMixingMatrix = np.zeros((N*M,N*M)) # for i in range(N): # self.ctrlMixingMatrix[i*M:(i+1)*M,i*M:(i+1)*M] = -np.sqrt(self.M) * self.beta * H # elif controller == 'diagonalController': self.ctrlMixingMatrix = np.zeros((N * M, N * M)) if dither: self.ctrlMixingMatrix = (np.random.randint( 2, size=(self.N * self.M, self.N * self.M)) * 2 - 1) * beta * 0.05 / (self.M * self.N) self.ctrlMixingMatrix += -self.kappa * self.beta * np.sqrt( M) * np.eye(self.N * self.M) # elif controller == 'blockDiagonalController: # for k in range(N): # self.ctrlMixingMatrix[k * self.M: (k+1) * self.M, # k * self.M:(k+1) * self.M] = (-self.beta # * np.outer(H[:,0],H[:,0])) self.ctrlOptions = { 'bitsPerControl': bitsPerControl, 'bound': 1, } self.ctrl = system.Control(self.ctrlMixingMatrix, self.size, options=self.ctrlOptions) print("ctrlMixingMatrix: %s\n" % (self.ctrlMixingMatrix, ))
'std': sigma2_thermal, 'steeringVector': beta * np.eye(N)[:, i] } for i in range(N)] } mixingMatrix = -kappa * beta * np.eye(N) ctrl = system.Control(mixingMatrix, size) input_signal = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=input_vector) all_inputs = [input_signal] order = N sys = system.System(A=A, c=c, b=input_vector) systemResponse = lambda f: np.dot(sys.frequencyResponse(f), sys.b) eta2_magnitude = np.max( np.abs(systemResponse(1. / (2. * Ts * osr)))**2) print("Eta2 = %d" % eta2_magnitude) eta2 = np.ones(order) * eta2_magnitude ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl, options=simulationOptions) res = sim.simulate(t, (input_signal, )) reconstructionOptions = { 'eta2': eta2, 'sigmaU2': sigmaU2,