6.3 LTI DT – Respuesta entrada cero ZIRn con Python



1. Respuesta a entrada cero x[n] = 0

Referencia: Lathi 3.6 p270

En el sistema LTI-D de la forma,

sistema discreto x]n] y[n]
Respuesta
total
=respuesta a
entrada cero ZIR
+respuesta a
estado cero ZSR
Q(E) y[n] = P(E) x[n]

La entrada cero implica x[n] =0, lo que cambia la expresión anterior a,

Q(E) y_0 [n] = 0
Sistema Discreto ZIR x[n]=0

que lleva a resolver:

y_0[n+N] + a_1 y_0[n+N-1] + \text{...} + a_{N-1} y_0[n+1] + a_N y_0[n] = 0

en notación E,

(E^N + a_1 E^{N-1} + \text{...} + a_{N-1}E^{1} + a_N E^{0}) y_0[n] = 0 (E^N + a_1 E^{N-1} + \text{...} + a_{N-1}E + a_N) y_0[n] = 0

La ecuación muestra que es una combinación lineal de y0[n] y un avance de y0[n] también es cero, siempre y cuando ambas expresiones tengan la misma forma.

La función exponencial γn es la que tiene ésta propiedad,

\gamma^{k+n} = \gamma^k \gamma^n

2. Raíces reales no repetidas

Indica que γn avanzado por k unidades es varias veces una constante (γk). Por lo que la solución es de la forma y0[n] = cγn, de donde se deben encontrar los valores para c y γ.

Se reescribe la ecuación de diferencias con operadores E como y se busca una solución:

c(\gamma^N + a_1 \gamma^{N-1} + \text{...} + a_{N-1}\gamma + a_N) \gamma^n = 0 \gamma^N + a_1 \gamma^{N-1} + \text{...} + a_{N-1}\gamma + a_N = 0 (\gamma -\gamma_1)(\gamma -\gamma_2) \text{...}(\gamma -\gamma_N) = 0 y_0[n] = c_1 \gamma_1^n + c_2 \gamma_2^{n} + \text{...} + c_n \gamma_N^{n}

que se resuelve con las condiciones iniciales del problema, teniendo así la ecuación característica, con valores característicos.

2.1 Ejercicio.Raíces reales No repetidas

Referencia: Lathi Ejemplo 3.13 p271

Para un sistema LTID descrito por la ecuación de diferencias mostrada,

y[n+2] - 0.6 y[n+1] - 0.16 y[n] = 5x[n+2]

encuentre la respuesta a entrada cero y0[n] del sistema dadas las condiciones iniciales y[-1]=0, y[-2] =25/4, ante una entrada

x[n]= 4^{-n} \mu [n]

(El componente de estado cero se calcula en la sección correspondiente)


Para realizar el diagrama, se desplaza la ecuación en dos unidades

y[n] - 0.6 y[n-1] - 0.16 y[n-2] = 5x[n] y[n] = 0.6 y[n-1] + 0.16 y[n-2] + 5x[n]

Para respuesta a entrada cero se usa x[n] = 0

LTID Respuesta Entrada Cero Ej01

2.2 Desarrollo analítico

y[n+2] - 0.6 y[n+1] - 0.16 y[n] = 5x[n+2]

La ecuación del sistema en notación de operador E es:

E^2 y[n] - 0.6 E y[n] - 0.16 y[n] = 5 E^2 x[n] (E^2 - 0.6 E - 0.16) y[n] = 5 E^2 x[n]

que para entrada cero tiene x[n]=0,

(E^2 - 0.6 E - 0.16) y[n] = 0

tiene el polinomio característico,

\gamma^2 - 0.6 \gamma - 0.16 = 0 (\gamma+0.2) (\gamma - 0.8) = 0

con raíces características γ1=-0.2 y γ2=0.8, obtenidas con  instrucciones con Python:

raices:
[ 0.8 -0.2]
coeficientes:
[0.8 0.2] 

la repuesta a entrada cero tiene la forma

y_0[n] = c_1 (-0.2)^n + c_2 (0.8)^n

se usan las condiciones iniciales para determinar las constantes c1 y c2 aplicadas como:

y_0[-1] = c_1 (-0.2)^{-1} + c_2 (0.8)^{-1} 0 = -5 c_1 + 1.25 c_2 y_0[-2] = c_1 (-0.2)^{-2} + c_2 (0.8)^{-2} \frac{25}{4} = 25 c_1 + 1.5625 c_2

se tiene el sistema de ecuaciones

0 = -5 c_1 + 1.25 c_2 \frac{25}{4} = 25 c_1 + 1.5625 c_2

resolviendo se encuentra que: c1 = 0.2 c2 = 0.8

con lo que la solución tiene la expresión basado en la sumatoria de ci ϒn, para n≥0

y_0 [n] = \frac{1}{5} (-0.2)^n + \frac{4}{5} (0.8)^n

2.3 Algoritmo en Python para raíces no repetidas

El algoritmo requiere los coeficientes de la ecuación de diferencias Q(E) y P(E) junto a las condiciones iniciales.

QE = [1., -0.6, -0.16]
PE = [5., 0., 0.]
inicial = [25/4, 0.] 

que da como resultado:

respuesta entrada cero: 
raices:  [ 0.8 -0.2]
Matriz: 
[[ 1.5625 25.    ]
 [ 1.25   -5.    ]]
Ci:      [0.8 0.2]
y0:
        n          n
0.2*-0.2  + 0.8*0.8 

Algoritmo en Python

# Sistema LTID. Respuesta entrada cero
# resultado con raices Reales
# ejercicio Lathi ejemplo 3.13 p271
import numpy as np
import sympy as sym
import matplotlib.pyplot as plt
 
# INGRESO
# coeficientes E con grado descendente
QE = [1., -0.6, -0.16]
PE = [5., 0., 0.]
# condiciones iniciales ascendente ...,y[-2],y[-1]
inicial = [25/4, 0.] 
 
# PROCEDIMIENTO
# Respuesta a ENTRADA CERO
# raices, revisa numeros complejos
gamma = np.roots(QE)
revisaImag = np.iscomplex(gamma)
escomplejo = np.sum(revisaImag)
 
# coeficientes de ecuacion
m_q = len(QE)-1
Ac = np.zeros(shape=(m_q,m_q),dtype=float)
 
if escomplejo == 0: # coeficientes Reales
    for i in range(0,m_q,1):
        for j in range(0,m_q,1):
            Ac[i,j] = gamma[j]**(-m_q+i)
    ci = np.linalg.solve(Ac,inicial)
 
# ecuacion y0
n = sym.Symbol('n')
y_0 = 0*n # vacio
if escomplejo == 0: # coeficientes Reales
    for i in range(0,m_q,1):
        y_0 = y_0 + ci[i]*(gamma[i]**n)
     
# SALIDA
print('respuesta entrada cero: ')
print('raices: ', gamma)
if escomplejo == 0: # coeficientes Reales
    print('Matriz: ')
    print(Ac)
    print('Ci:     ', ci)
    print('y_0:')
    sym.pprint(y_0)
else:
    print(' existen raices con números complejos.')
    print(' usar algoritmo de la sección correspondiente.')



3. Raíces reales repetidas

Si no todas las raíces son diferentes, es decir algunas se repiten, la forma de los modos característicos se modifican. Por sustitución directa, siendo r el número de raíces repetidas, se tiene:

Q[\gamma] =(\gamma -\gamma_1)^r (\gamma -\gamma_{r+1}) (\gamma -\gamma_{r+2}) \text{...}(\gamma -\gamma_N) y_0[n] = (c_1+c_2 n +c_3 n^2 + \text{...} +c_r n^{r-1}) \gamma_1^n + c_{r+1} \gamma_{r+1}^{n} + + c_{r+2} \gamma_{r+2}^{n} + \text{...} + c_n \gamma_N^{n}

3.1. Ejercicio. Raíces reales repetidas

Referencia: Lathi Ejemplo 3.15 p274

y[n+2] +6 y[n+1] + 9 y[n] = 2 x[n+2] + 6 x[n+1]

con las condiciones iniciales y0[-1] = -1/3 y y0[-2] = -2/9

Para realizar el diagrama de bloques, se desplaza ambos lados de la ecuación en 2 unidades. Luego se despeja y[n]

y[n] +6 y[n-1] + 9 y[n-2] = 2 x[n] + 6 x[n-1] y[n] = -6 y[n-1] - 9 y[n-2] + 2 x[n] + 6 x[n-1]
ZIR discreto Respuesta Estado Cero Ej03

3.2 Desarrollo analítico

siguiendo los mismos pasos que en los ejercicios anteriores

E^2 y[n] +6 E y[n] + 9 y[n] = 2 E^2 x[n] + 6 E x[n] (E^2 +6 E + 9) y[n] = (2 E^2 + 6 E) x[n]

Para entrada cero se tiene x[n] = 0

(E^2 +6 E + 9) y[n] = (2 E^2 + 6 E) (0) \gamma^2 +6 \gamma + 9 = 0 (\gamma + 3)( \gamma + 3) = 0

de donde se muestra una raíz repetida γ=3, donde los modos característicos hacen que la expresión sea:

y_0[n] = (c_1 + c_2 n) (\gamma)^n

siguiendo el procedimiento realizado para raíces reales se puede determinar los valores de c1=4 y c2=3, con lo que se obtiene la solución:

y_0[n] = (4 + 3n) (-3)^n

los resultados obtenidos con el algoritmo en Python son

respuesta entrada cero: 
raices:  [-3. -3.]
Raices repetidas:  1
Matriz: 
[[ 0.11111111 -0.22222222]
 [-0.33333333  0.33333333]]
Ci:      [4. 3.]
y_0:
    n              
-3.0 *(3.0*n + 4.0)
>>>

La parte de la gráfica se incorpora al algoritmo final

Respuesta Estado Cero Ej02 gráfica

3.3 Algoritmo en Python, integrando raíces reales no repetida y repetidas

# Sistema LTID. Respuesta entrada cero
# QE con raices Reales NO repetidas Lathi ejemplo 3.13 pdf271
# QE con raices Reales Repetidas Lathi ejemplo 3.15 p274
import numpy as np
import sympy as sym
import matplotlib.pyplot as plt

# INGRESO
# coeficientes E con grado descendente
QE = [1., 6., 9.]
PE = [2., 6., 0.]
# condiciones iniciales ascendente ...,y[-2],y[-1]
inicial = [-2/9, -1/3]

casicero = 1e-6  # casi_cero

# PROCEDIMIENTO
# Respuesta a ENTRADA CERO
# raices, revisa numeros complejos
gamma = np.roots(QE)
revisaImag = np.iscomplex(gamma)
escomplejo = np.sum(revisaImag)

# coeficientes de ecuacion
m_q = len(QE)-1
Ac = np.zeros(shape=(m_q,m_q),dtype=float)

# revisa si parte compleja<casicero
if escomplejo>0:
    for i in range(0,m_q,1):
        if np.imag(gamma[i]) < casicero:
            gamma[i] = float(np.real(gamma[i]))
    sumaj = np.sum(np.imag(gamma))
    if sumaj <casicero:
        gamma = np.real(gamma)
        escomplejo = 0

# revisa repetidos
unicoscuenta = np.unique(gamma,return_counts=True)
repetidas = np.sum(unicoscuenta[1]-1)

# raices Reales no repetidas
if escomplejo == 0 and repetidas==0:
    for i in range(0,m_q,1):
        for j in range(0,m_q,1):
            Ac[i,j] = gamma[j]**(-m_q+i)
    ci = np.linalg.solve(Ac,inicial)
    
# raices Reales repetidas
if escomplejo == 0 and repetidas > 0:
    for i in range(0,m_q,1):
        for j in range(0,m_q,1):
            Ac[i,j] = ((-m_q+i)**j)*gamma[j]**(-m_q+i)
    ci = np.linalg.solve(Ac,inicial)

# ecuacion y0 entrada cero
n = sym.Symbol('n')
y_0 = 0*n

if escomplejo == 0 and repetidas==0:
    for i in range(0,m_q,1):
        y_0 = y_0 + ci[i]*(gamma[i]**n)
        
if escomplejo == 0 and repetidas > 0:
    for i in range(0,m_q,1):
        y_0 = y_0 + ci[i]*(n**i)*(gamma[i]**n)
    y_0 = y_0.simplify()
    
# SALIDA
print('respuesta entrada cero: ')
print('raices: ', gamma)
if escomplejo == 0:
    if repetidas>0:
        print('Raices repetidas: ', repetidas)
    print('Matriz: ')
    print(Ac)
    print('Ci:     ', ci)
    print('y_0:')
    sym.pprint(y_0)
else:
    print(' existen raices con números complejos.')
    print(' usar algoritmo de la sección correspondiente.')


4. Raíces complejas

Pueden darse el caso en forma de pares de conjugadas, si los coeficientes en la ecuación del sistema con números reales.

Una alternativa es usar la forma real de la solución, tal como se hace en sistemas contínuos.

Se expresan las raíces conjugadas complejas en su forma polar. Si la magnitud es |γ| y el ángulo es β, se tiene,

\gamma = |\gamma | e^{j \beta} \gamma^* = |\gamma | e^{-j \beta} y_0[n] = c_1 \gamma ^{n} + c_2 (\gamma^*)^n =c_1 |\gamma| ^{n} e^{j \beta n} + c_2 | \gamma |^n e^{-j \beta n} c_1 = \frac{c}{2} e^{j \theta} c_2 = \frac{c}{2} e^{-j \theta} y_0[n] = \frac{c}{2} |\gamma| ^{n} \Big[ e^{j (\beta n + \theta)}+ e^{-j (\beta n + \theta)} \Big] y_0[n] = c |\gamma| ^{n} \cos (\beta n + \theta)

donde c y θ son constantes determinadas con las condiciones iniciales. Esta solución es numérica real, evitando trabajar con números complejos

4.1. Ejercicio. Raíces con números complejos

Referencia: Lathi Ejemplo 3.16 p275

Para el caso de tener raíces con números complejos se muestra el siguiente ejemplo:

y[n+2] - 1.56 y[n+1] + 0.81 y[n] = x[n+1] + 3x[n]

con condiciones iniciales y0[-1]=2 y y0[-2]=1

Para realizar el diagrama de bloques, se desplaza ambos lados de la ecuación en 2 unidades. Luego se despeja y[n]

y[n] - 1.56 y[n-1] + 0.81 y[n-2] = x[n-1] + 3x[n-2] y[n] = 1.56 y[n-1] - 0.81 y[n-2] + x[n-1] + 3x[n-2]
ZIR discreto Respuesta Estado Cero Ej02

4.2 Desarrollo analítico

y[n+2] - 1.56 y[n+1] + 0.81 y[n] = x[n+1] + 3x[n]

La expresión usando operador E:

E^2 y[n] - 1.56 E y[n] + 0.81 y[n] = E x[n] + 3x[n] (E^2 - 1.56 E + 0.81) y[n] = (E+ 3)x[n]

para entrada cero se hace x[n] = 0

(E^2 - 1.56 E + 0.81) y[n] = (E+ 3)(0)

por lo que, el polinomio característico es,}

(\gamma^2 - 1.56 \gamma + 0.81) = 0

con raíces de números complejos

(\gamma - (0.78 + j 0.45))(\gamma - (0.78-j 0.45)) = 0

la raíz también se puede escribir como:

\gamma = 0.9 e^{\pm j\frac{\pi}{6}}

obtenida mediante:

raices:
[0.78+0.44899889j 0.78-0.44899889j]
magnitud:  [0.9 0.9]
angulo:  [ 0.52231482 -0.52231482]
>>>  

Se puede escribir la solución como:

y_0[n] = c(0.9)n e^{j\frac{\pi}{6} } + c^{*} (0.9)n e^{-j\frac{\pi}{6}}

Luego aplicando las condiciones iniciales  se encuentra que

c = 2.34 e^{-j0.17} c^{*} = 2.34 e^{j0.17}

Otra manera de desarrollo permite encontrar la solución usando la forma real de la solución, conociendo que la solución esta dada por la expresión:

y_0[n] = c(0.9)^n \cos \Big( \frac{\pi}{6}n + \theta \Big)

con lo que se puede crear el sistema de ecuaciones aplicando las condiciones iniciales, ademas de considerar que:

\cos(a \pm b) = \cos(a) \cos(b) \mp \sin(a) \sin(b)

Para y0[-2] = 1

1 = c(0.9)^{-2} \cos \Big( \frac{\pi}{6}(-2) + \theta \Big) 1 = c\frac{1}{(0.9)^2} \Big[ \cos \big(-2\frac{\pi}{6} \big) \cos ( \theta ) - \sin \big(-2\frac{\pi}{6}\big) \sin (\theta) \Big] 1 = c\frac{1}{0.81} \Big[ \frac{1}{2} \cos ( \theta ) - \frac{-\sqrt{3}}{2} \sin (\theta) \Big] 1 = c \Big[ \frac{1}{1.62} \cos ( \theta ) + \frac{\sqrt{3}}{1.62} \sin (\theta) \Big]

Para y0[-1] = 2

2 = c(0.9)^{-1} \cos \Big( \frac{\pi}{6}(-1) + \theta \Big) 2 = c\frac{1}{0.9} \Big[ \cos \big(-\frac{\pi}{6} \big) \cos ( \theta ) - \sin \big(-\frac{\pi}{6}\big) \sin (\theta) \Big] 2 = c\frac{1}{0.9} \Big[ \frac{\sqrt{3}}{2} \cos ( \theta ) - \frac{-1}{2} \sin (\theta) \Big] 2 = c\Big[ \frac{\sqrt{3}}{1.8} \cos ( \theta ) + \frac{1}{1.8} \sin (\theta) \Big]

con lo que se puede determinar los valores para

y

usando una matriz A y vector B a partir de las ecuaciones

c \cos ( \theta ) = 2.31 c \sin ( \theta ) = -0.4049

al dividir  / = tan (θ), con lo que se obtiene el ángulo en radianes.

\frac{ c \sin ( \theta )} {c \cos ( \theta )} = \frac{-0.4049}{2.31} = -0.17528 \theta = \tan ^{-1} (-0.17528) = -0.1735

al sustituir el valor en c cos(θ) = 2.31 se tiene,

c = \frac{2.31}{ \cos (-0.1735)} = 2.3452

con lo que la solución se puede escribir mediante:

y_0[n] = 2.3452 (0.9)^n \cos \Big( \frac{\pi}{6}n - 0.1735 \Big)

para n≥0

ZIR discreta Respuesta Estado Cero Ej03 Graf


4.3 Algoritmo en Python, integrando raíces reales y complejas

usando el algoritmo se obtienen los siguientes resultados:

Respuesta entrada cero: 
raices :  [0.78+0.44899889j 0.78-0.44899889j]
raices complejas:  2
magnitud: [0.9 0.9]
theta: [ 0.52231482 -0.52231482]
Matriz: 
[[0.62002743 1.06757851]
 [0.96296296 0.55431961]]
Cj:      [ 2.31       -0.40490078] 
Ci:  2.345217397781524
y_0: 
                    n                                             
2.34521739778152*0.9 *cos(0.522314821806049*n + 0.173519005551295)
>>> 

Para el caso de raíces complejas, se añade al algoritmo anterior las instrucciones en Python:

# Sistema LTID. Respuesta entrada cero
# QE con raices Reales NO repetidas Lathi ejemplo 3.13 pdf271
# QE con raices Reales Repetidas Lathi ejemplo 3.15 p274
# QE con raices Complejas Lathi ejemplo 3.16 p275
# https://blog.espol.edu.ec/algoritmos101/senales/ss-unidades/ss-unidad-6/
import numpy as np
import sympy as sym
import matplotlib.pyplot as plt

# INGRESO
# coeficientes E con grado descendente
QE = [1.0, -1.56, 0.81]
PE = [0., 1., 3.]
# condiciones iniciales ascendente ...,y[-2],y[-1]
inicial = [1.,2.]

muestras = 10  # para grafica
casicero = 1e-6  # casicero

# PROCEDIMIENTO
# Respuesta a ENTRADA CERO
# raices, revisa numeros complejos
gamma = np.roots(QE)
revisaImag = np.iscomplex(gamma)
escomplejo = np.sum(revisaImag)

# coeficientes de ecuacion
m_q = len(QE)-1
Ac = np.zeros(shape=(m_q,m_q),dtype=float)

# revisa si parte compleja <casicero 
if escomplejo>0:
    for i in range(0,m_q,1):
        valorimag = np.imag(gamma[i])
        if np.abs(valorimag)<casicero:
            gamma[i] = float(np.real(gamma[i]))
    sumaj = np.sum(np.abs(np.imag(gamma)))
    if sumaj <casicero:
        print(sumaj)
        gamma = np.real(gamma)
        escomplejo = 0

# revisa raíces repetidas
unicoscuenta = np.unique(gamma,return_counts=True)
repetidas = np.sum(unicoscuenta[1]-1)

# Determina coeficientes ci de Y[n]
# raices Reales no repetidas
if escomplejo == 0 and repetidas==0:
    for i in range(0,m_q,1):
        for j in range(0,m_q,1):
            Ac[i,j] = gamma[j]**(-m_q+i)
    ci = np.linalg.solve(Ac,inicial)
    
# raices Reales repetidas
if escomplejo == 0 and repetidas > 0:
    for i in range(0,m_q,1):
        for j in range(0,m_q,1):
            Ac[i,j] = ((-m_q+i)**j)*gamma[j]**(-m_q+i)
    ci = np.linalg.solve(Ac,inicial)

# raices Complejas
if escomplejo > 0:
    g_magnitud = np.absolute(gamma)
    g_angulo = np.angle(gamma)

    for i in range(0,m_q,1):
        k = -(m_q-i)
        a = np.cos(np.abs(g_angulo[i])*(k))*(g_magnitud[i]**(k))
        b = -np.sin(np.abs(g_angulo[i])*(k))*(g_magnitud[i]**(k))
        Ac[i] = [a,b]
    Ac = np.array(Ac)
    cj = np.linalg.solve(Ac,inicial)

    theta = np.arctan(cj[1]/cj[0])
    ci = cj[0]/np.cos(theta)

# ecuacion y0 entrada cero
n = sym.Symbol('n')
y_0 = 0*n

if escomplejo == 0 and repetidas==0:
    for i in range(0,m_q,1):
        y_0 = y_0 + ci[i]*(gamma[i]**n)
        
if escomplejo == 0 and repetidas > 0:
    for i in range(0,m_q,1):
        y_0 = y_0 + ci[i]*(n**i)*(gamma[i]**n)
    y_0 = y_0.simplify()

if escomplejo > 0:
    y_0 = ci*(g_magnitud[0]**n)*sym.cos(np.abs(g_angulo[i])*n - theta)
    
# SALIDA
print('respuesta entrada cero: ')
print('raices: ', gamma)
if escomplejo == 0:
    if repetidas>0:
        print('Raices repetidas: ', repetidas)
    print('Matriz: ')
    print(Ac)
    print('Ci:     ', ci)
    print('y_0:')
    sym.pprint(y_0)
if escomplejo > 0:
    print('raices complejas: ', escomplejo)
    print('magnitud:',g_magnitud)
    print('theta:',g_angulo)
    print('Matriz: ')
    print(Ac)
    print('Cj: ', cj)
    print('Ci: ',ci)
    print('y_0: ')
    sym.pprint(y_0)

4.4 Gráfica para y0[n]

Se añaden las instrucciones al algoritmo anterior

# grafica datos
ki = np.arange(-m_q,muestras,1)
y0i = np.zeros(muestras+m_q)
# valores iniciales
y0i[0:m_q] = inicial[0:m_q]
# evaluación de y0[n]
y0n = sym.lambdify(n,y_0)
y0i[m_q:] = y0n(ki[m_q:])

# grafica y[n] ante x[n]=0
plt.stem(ki,y0i)
plt.xlabel('ki')
plt.ylabel('y0[n]')
plt.title('y0[n]='+str(y_0))
plt.grid()
plt.tight_layout()
plt.show()



Unidades SS