1. Transformada z Inversa
Referencia: Lathi 5.1-1 p495, Oppenheim 10.3 p757
Muchas de las transformadas X[z] de interés práctico son fracciones de polinomios en z, que pueden ser expresadas como una suma de fracciones parciales cuya inversa puede ser revisada en una tabla de transformadas z.
El método de fracciones parciales funciona dado que para cada x[n] transformable con n≥0 le corresponde una X[z] única definida para |z|>a y viceversa. Para lo mostrado, se supone que se usa la fracción parcial mas simple.
2. Ejemplo - Transformada z inversa de una fracción X[1/z]
Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490
Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:
X[z] = \frac{1}{1-a z^{-1}}\text{ , } |z|>|a|la expresión se puede expandir en series se potencias y obtener los primeros términos de la secuencia de x[n]. Los términos son útiles si se se requieren los m primeros términos de la secuencia, es decir n se encuentra en [0,m-1]
X[z]:
z
------
-a + z
F[z]:
2 3 4 5 6
a a a a a a /1 \
1 + - + -- + -- + -- + -- + -- + O|--; z -> oo|
z 2 3 4 5 6 | 7 |
z z z z z \z /
Términos x[n] entre[0,7]
[1, a, a**2, a**3, a**4, a**5, a**6]
x[n] con a= 1/2
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625]
Al final de la serie F[z] se muestra un término con el orden del error.
De los términos mostrados, se observa que X[n] = an
Usando por ejemplo a=1/2, se obtiene como resultado de x[n],

>>> xi
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625]
2.1 Algoritmo en Python
# transformada z inversa de X[z]
import sympy as sym
# INGRESO
z = sym.symbols('z',)
n = sym.symbols('n', nonnegative=True)
a = sym.symbols('a')
u = sym.Heaviside(n)
Xz = 1/(1-a*z**(-1))
# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)
m = 7 # Términos a graficar
# PROCEDIMIENTO
# Series de potencia z**(-1)
Fz = sym.series(Xz,z**(-1), n=m)
# Terminos de X[n]
xn = []
termino = Fz.args
for i in range(0,m,1):
xn.append(termino[i]*(z**i))
# SALIDA
print('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('\n Términos x[n] entre [0,'+str(m)+']')
print(xn)
# GRAFICA valores ---------------
import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i in range(0,m,1):
valor = xn[i].subs({z:1,a:a_k})
xi.append(float(valor))
ki.append(i)
print('\n x[n] con a=',a_k)
print(xi)
# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()
plt.show()
3. Ejemplo. Transformada z inversa de una fracción dada con X[z]
Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490
Si la expresión se usa de la forma simplificada, que es la más común para tratar las expresiones con Sympy, el algoritmo anterior para las series no realiza la misma respuesta.
X[z] = \frac{z}{z-a}\text{ , } \Big|z|>|a| X[z] = \frac{1}{1-a z^{-1}}\text{ , } \Big|z|>|a|Para este caso se multiplica el numerador y denominador por 1/z, obteniendo la expresión del ejemplo anterior. Para generar la serie se realiza el, cambio de variable Z=1/z para generar la serie sobre Z. Luego se restablece en la expresión antes de mostrar los términos, y se obtiene el mismo resultado.
De los términos mostrados, se observa que X[n] = an
3.1 Algoritmo en Python
# transformada z inversa de X[z]
# supone que la expresión son fracciones parciales
import sympy as sym
# INGRESO
z = sym.symbols('z')
n = sym.symbols('n', integer=True, positive=True)
a = sym.symbols('a')
Xz = z/(z-a)
# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)
m = 7 # Términos a graficar
# PROCEDIMIENTO
# expresión Xz con z para aplicar serie
# separa numerador y denominador
[Pz,Qz] = Xz.as_numer_denom()
Pz = (Pz*(1/z)).expand(1/z)
Qz = (Qz*(1/z)).expand(1/z)
# cambia Z por 1/z
Z = sym.symbols('Z')
PZ = Pz.subs(1/z,Z)
QZ = Qz.subs(1/z,Z)
XZ = PZ/QZ
# Series de potencia de Z
FZ = sym.series(XZ,Z, n=m)
Fz = FZ.subs(Z,1/z) # restituye 1/z
# Terminos de X[n]
xn = []
termino = Fz.args
for i in range(0,m,1):
xn.append(termino[i]*(z**i))
# SALIDA
print('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('Términos x[n] entre[0,'+str(m)+']')
print(xn)
# GRAFICA valores ---------------
import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i in range(0,m,1):
valor = xn[i].subs({z:1,a:a_k})
xi.append(float(valor))
ki.append(i)
print('\n x[n] con a=',a_k)
print(xi)
# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()
plt.show()
El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.
4. Ejemplo. Transformada z inversa de una fracción X[1/z]
Referencia: Oppenheim Ejemplo 10.13 p761, Lathi Ejemplo 5.1 p490
Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:
X[z] = \frac{1}{1-a z^{-1}}\text{ , } |z|>|a| X[z] = \frac{z}{z-a}\text{ , } \Big|z|>|a|siendo la expresión de ingreso al algoritmo:
F = z/(z - 2)
el resultado es:
f[n] : 2**n*Heaviside(n)
>>>
4.1 Algoritmo Python para z/(z - 2) con telg1001.py
# transformada z propiedades con Sympy
# aplicar luego de buscar en tabla de pares
import sympy as sym
import telg1001 as fcnm
# INGRESO
n = sym.Symbol('n', real=True)
z = sym.Symbol('z')
u = sym.Heaviside(n)
# (a**n)*f[n] <--> F(z/a)
F = z/(z - 2) #f = (2**n)*u
# PROCEDIMIENTO
fn = fcnm.inverse_z_transform(F,z,n)
# SALIDA
print('f[n] :',fn)
El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.
5. Ejemplo. Transformada z inversa usando expansión en fracciones parciales
Referencia: Lathi 5.3 a
Encuentre la transformada z inversa para:
F[z] = \frac{8z-19}{(z-2)(z-3)}el ingreso para el algoritmo del ejercicio anterior es:
F = (8*z-19)/((z-2)*(z-3))
con el resultado siguiente:
f[n] : (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6
activando la variable sym.SYMPY_DEBUG=True, se observa el proceso de fracción parcial modificada, la búsqueda en la tabla, y aplicación de una propiedad de la transformada z.
inverse_z_transform(F,z,n): (8*z - 19)/((z - 3)*(z - 2))
apart_z(F) : (8*z - 19)/((z - 3)*(z - 2))
z**a, ma_za: None ; a ,ma_ka: None
z**a, ma_za: None ; a ,ma_ka: None
z**a, ma_za: None ; a ,ma_ka: None
_simplify_z: (8*z - 19)/(z*(z - 3)*(z - 2))
P: 8*z - 19
Q: z*(z - 3)*(z - 2)
P match (a*z-b)**c: {a_: 8, b_: 19, c_: 1}
P_leadcoef: 8 : P: z - 19/8
Q match (a*z-b)**c: None
Q_leadcoef: 1 Q: z*(z - 3)*(z - 2)
k: 8 ; Fz: (z - 19/8)/(z*(z - 3)*(z - 2))
simplify_z F: (8*z - 19)/(z*(z - 3)*(z - 2))
simplify(F/z): (8*z - 19)/(z*(z - 3)*(z - 2))
P: z - 19/8
P_degree: 1 ; P_zeros : [19/8]
Q: z*(z - 3)*(z - 2)
Q_degree: 3 ; Q_unique: [0, 2, 3]
apart(F/z): 3/(2*(z - 2)) + 5/(3*(z - 3)) - 19/(6*z)
ma_Qk: {a_: 6, b_: 0, c_: 1} ; ma_Qk2: {b_: 6, a_: 0, c_: 0}
_simplify_z: -19/(6*z)
P: -19
Q: 6*z
P match (a*z-b)**c: {b_: 19, a_: 0, c_: 1}
P_leadcoef: -19 : P: 1
Q match (a*z-b)**c: {a_: 6, b_: 0, c_: 1}
Q_leadcoef: 6 Q: z
k: -19/6 ; Fz: 1/z
simplify_z F: -19/(6*z)
ma_Qk: {a_: 2, b_: -4, c_: 1} ; ma_Qk2: {b_: 2, c_: -4, a_: 0}
_simplify_z: 3/(2*(z - 2))
P: 3
Q: 2*z - 4
P match (a*z-b)**c: {b_: -3, a_: 0, c_: 1}
P_leadcoef: 3 : P: 1
Q match (a*z-b)**c: {a_: 2, b_: 4, c_: 1}
Q_leadcoef: 2 Q: z - 2
k: 3/2 ; Fz: 1/(z - 2)
simplify_z F: 3/(2*(z - 2))
ma_Qk: {a_: 3, b_: -9, c_: 1} ; ma_Qk2: {b_: 3, c_: -9, a_: 0}
_simplify_z: 5/(3*(z - 3))
P: 5
Q: 3*z - 9
P match (a*z-b)**c: {b_: -5, a_: 0, c_: 1}
P_leadcoef: 5 : P: 1
Q match (a*z-b)**c: {a_: 3, b_: 9, c_: 1}
Q_leadcoef: 3 Q: z - 3
k: 5/3 ; Fz: 1/(z - 3)
simplify_z F: 5/(3*(z - 3))
apart z*(Fz/z) : 3*z/(2*(z - 2)) + 5*z/(3*(z - 3)) - 19/6
apart_z(F) as Add: (-19/6, 3*z/(2*(z - 2)), 5*z/(3*(z - 3)))
term_k[z]: -19/6
_simplify_z: 1
P: 1
Q: 1
P match (a*z-b)**c: {c_: 0}
P_leadcoef: 1 : P: 1
Q match (a*z-b)**c: {c_: 0}
Q_leadcoef: 1 Q: 1
k: 1 ; Fz: 1
simplify_z F: 1
_z_pairs_table match:
k: -19/6 ; Fz: 1
z_pair F[z]: 1 ; ma_z: {}
z_pair f[n]: DiracDelta(n)
try,check : True -> True
pair f[n]: (-19*DiracDelta(n)/6, 0, True)
term_k[n]: (-19*DiracDelta(n)/6, 0, True)
term_k[z]: 3*z/(2*(z - 2))
_simplify_z: z/(z - 2)
P: z
Q: z - 2
P match (a*z-b)**c: {a_: 1, b_: 0, c_: 1}
P_leadcoef: 1 : P: z
Q match (a*z-b)**c: {a_: 1, b_: 2, c_: 1}
Q_leadcoef: 1 Q: z - 2
k: 1 ; Fz: z/(z - 2)
simplify_z F: z/(z - 2)
z_properties_inverse_z_transform
_simplify_z: 3*z/(2*(z - 2))
P: 3*z
Q: 2*z - 4
P match (a*z-b)**c: {a_: 3, b_: 0, c_: 1}
P_leadcoef: 3 : P: z
Q match (a*z-b)**c: {a_: 2, b_: 4, c_: 1}
Q_leadcoef: 2 Q: z - 2
k: 3/2 ; Fz: z/(z - 2)
simplify_z F: 3*z/(2*(z - 2))
P: z
Q: z - 2
k: 3/2 ; P_signo: 1 ; P_degree: 1 ; P_zeros: [0]
Q_degree: 1 ; Q_poles (real): [2]
ma_Q1 (c*z-a)**b : {c_: 1, a_: 2, b_: 1}
F[z]: z/(z - 2)
_z_property multiply (a**n)*f[n] <--> F(z/a)
P_sign: 1 ; k: 3/2 ; k_a: 2 <class 'sympy.core.numbers.Integer'>
Fz: z/(z - 1)
_simplify_z: z/(z - 1)
P: z
Q: z - 1
P match (a*z-b)**c: {a_: 1, b_: 0, c_: 1}
P_leadcoef: 1 : P: z
Q match (a*z-b)**c: {a_: 1, b_: 1, c_: 1}
Q_leadcoef: 1 Q: z - 1
k: 1 ; Fz: z/(z - 1)
simplify_z F: z/(z - 1)
_z_pairs_table match:
k: 1 ; Fz: z/(z - 1)
z_pair F[z]: z/(z - 1) ; ma_z: {}
z_pair f[n]: Heaviside(n)
try,check : True -> True
pair f[n]: (Heaviside(n), Abs(z) > 1, True)
_z_property multiply (a**n)*f[n]:
(3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
f[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
prop f[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
term_k[n]: (3*2**n*Heaviside(n)/2, Abs(z) > 2, True)
term_k[z]: 5*z/(3*(z - 3))
_simplify_z: z/(z - 3)
P: z
Q: z - 3
P match (a*z-b)**c: {a_: 1, b_: 0, c_: 1}
P_leadcoef: 1 : P: z
Q match (a*z-b)**c: {a_: 1, b_: 3, c_: 1}
Q_leadcoef: 1 Q: z - 3
k: 1 ; Fz: z/(z - 3)
simplify_z F: z/(z - 3)
z_properties_inverse_z_transform
_simplify_z: 5*z/(3*(z - 3))
P: 5*z
Q: 3*z - 9
P match (a*z-b)**c: {a_: 5, b_: 0, c_: 1}
P_leadcoef: 5 : P: z
Q match (a*z-b)**c: {a_: 3, b_: 9, c_: 1}
Q_leadcoef: 3 Q: z - 3
k: 5/3 ; Fz: z/(z - 3)
simplify_z F: 5*z/(3*(z - 3))
P: z
Q: z - 3
k: 5/3 ; P_signo: 1 ; P_degree: 1 ; P_zeros: [0]
Q_degree: 1 ; Q_poles (real): [3]
ma_Q1 (c*z-a)**b : {c_: 1, a_: 3, b_: 1}
F[z]: z/(z - 3)
_z_property multiply (a**n)*f[n] <--> F(z/a)
P_sign: 1 ; k: 5/3 ; k_a: 3 <class 'sympy.core.numbers.Integer'>
Fz: z/(z - 1)
_simplify_z: z/(z - 1)
P: z
Q: z - 1
P match (a*z-b)**c: {a_: 1, b_: 0, c_: 1}
P_leadcoef: 1 : P: z
Q match (a*z-b)**c: {a_: 1, b_: 1, c_: 1}
Q_leadcoef: 1 Q: z - 1
k: 1 ; Fz: z/(z - 1)
simplify_z F: z/(z - 1)
_z_pairs_table match:
k: 1 ; Fz: z/(z - 1)
z_pair F[z]: z/(z - 1) ; ma_z: {}
z_pair f[n]: Heaviside(n)
try,check : True -> True
pair f[n]: (Heaviside(n), Abs(z) > 1, True)
_z_property multiply (a**n)*f[n]:
(5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
f[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
prop f[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
term_k[n]: (5*3**n*Heaviside(n)/3, Abs(z) > 3, True)
f[n]: 3*2**n*Heaviside(n)/2 + 5*3**n*Heaviside(n)/3 - 19*DiracDelta(n)/6
f[n]: (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6
f[n] : (9*2**n + 10*3**n)*Heaviside(n)/6 - 19*DiracDelta(n)/6