6.2.1 LTI DT – Respuesta entrada cero. Ejercicios con Python

Los siguientes ejercicios de LTI Discretos muestran los desarrollos  cuando el denominador de la función de transferencia tiene:

1. raíces reales diferentes (No repetidas)
2. raíces reales repetidas
3. raíces con números complejos


Ejercicio 1. Raíces reales diferentes

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

1.1 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

Instrucciones en Python

import numpy as np

coeficientes = [1.,-0.6,-0.16]
raiz = np.roots(coeficientes)
print('raices:')
print(raiz)

A = np.array([[raiz[0]**(-1) , raiz[1]**(-1)],
     [raiz[0]**(-2) , raiz[1]**(-2)]])
B = np.array([0., 25/4])
ci = np.linalg.solve(A,B)
print('coeficientes:')
print(ci)

1.2 Desarrollo con Python

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 

Instrucciones 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:
    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')
y0 = 0
if escomplejo == 0:
    for i in range(0,m_q,1):
        y0 = y0 + ci[i]*(gamma[i]**n)
    
# SALIDA
print('respuesta entrada cero: ')
print('raices: ', gamma)
if escomplejo == 0:
    print('Matriz: ')
    print(Ac)
    print('Ci:     ', ci)
    print('y0:')
    sym.pprint(y0)
else:
    print(' existen raices con números complejos.')
    print(' usar algoritmo de la sección correspondiente.')

Raíces: [reales No repetidas] [reales repetidas] [números complejos]


2. Raíces 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]

2.1 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 raiz 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.]
y0:
    n              
-3.0 *(3.0*n + 4.0)
>>>

2.2 Instrucciones en Python, integrando raices reales únicas 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
# blog.espol.edu.ec/telg1001
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]

tolera = 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 <tolera o casi_cero 
if escomplejo>0:
    for i in range(0,m_q,1):
        if np.imag(gamma[i]) < tolera:
            gamma[i] = float(np.real(gamma[i]))
    sumaj = np.sum(np.imag(gamma))
    if sumaj <tolera:
        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')
y0 = 0*n

if escomplejo == 0 and repetidas==0:
    for i in range(0,m_q,1):
        y0 = y0 + ci[i]*(gamma[i]**n)
        
if escomplejo == 0 and repetidas > 0:
    for i in range(0,m_q,1):
        y0 = y0 + ci[i]*(n**i)*(gamma[i]**n)
    y0 = y0.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('y0:')
    sym.pprint(y0)
else:
    print(' existen raices con números complejos.')
    print(' usar algoritmo de la sección correspondiente.')

Raíces: [reales No repetidas] [reales repetidas] [números complejos]


Ejercicio 3. Raices 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]

3.1 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 oas 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 [c cos(θ)] y [c sin(θ)]

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

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

al dividir  [c sin(θ)]/[c cos(θ)] = 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

Instrucciones de cálculo

import numpy as np

coeficientes = [1.,-1.56,0.81]
raiz = np.roots(coeficientes)
print('raices:')
print(raiz)

g_magnitud = np.absolute(raiz)
g_angulo = np.angle(raiz)

print('magnitud: ',g_magnitud)
print('angulo: ',g_angulo)

3.2 Algoritmo en Python, integrando raices 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
y0: 
                    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
# blog.espol.edu.ec/telg1001
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.]

tolera = 1e-6  # casi_cero
muestras = 10  # para grafica

# 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 <tolera o casi_cero 
if escomplejo>0:
    for i in range(0,m_q,1):
        valorimag = np.imag(gamma[i])
        if np.abs(valorimag)<tolera:
            gamma[i] = float(np.real(gamma[i]))
    sumaj = np.sum(np.abs(np.imag(gamma)))
    if sumaj <tolera:
        print(sumaj)
        gamma = np.real(gamma)
        escomplejo = 0

# revisa repetidos
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')
y0 = 0*n

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

if escomplejo > 0:
    y0 = 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('y0:')
    sym.pprint(y0)
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('y0: ')
    sym.pprint(y0)

# 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,y0)
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(y0))
plt.grid()
plt.show()

Raíces: [reales No repetidas] [reales repetidas] [números complejos]