Referencia: Lathi 5.1-1 p495, Oppenheim 10.3 p757, Hsu 4.5.D p174
Muchas de las transformadas X(z) de interés en la práctica son funciones racionales, que pueden ser expresadas como la suma de fracciones parciales, cuyas transformadas inversas pueden ser encontradas rapidamente en la tabla de transformadas.
Se busca evitar realizar el integral en el plano complejo requerido para encontrar la transformada inversa de z.
El método de las fracciones parciales es práctico porque cada x[n] transformable se define para n≥0, existe su correspondiente X[z] definida para |z|>r0 y viceversa. (r0 es constante)
Para desarrollar y probar el algoritmo con Sympy-Python, se usará el desarrollo de los tres ejercicios siguientes, con polos únicos, repetidos y complejos. El algoritmo final del literal c integra las soluciones anteriores.
Ejercicio 1. Polos diferentes
Referencia: Lathi Ejercicio 5.3a p495. Hsu. ejercicio 4.29 p198
Realice la expansión en fracciones parciales de,
X[z] = \frac{8z-19}{(z-2)(z-3)}
Se puede encontrar que,
X[z] = \frac{3}{(z-2)}+\frac{5}{(z-3)}
de la tabla de transformadas z se tiene,
x[n] = [3(2)^{n-1} +5(3)^{n-1}] \mu [n-1]
Que tiene una entrada con términos multiplicadas por μ[n-1], que es un inconveniente y no deseable. Se prefieren las transformadas respecto a μ[n].
Observando la tabla de transformadas z entre los items 6a y 7, se tiene que si la señal X[n] es multiplicada por u[n], el numerador tiene un factor z. Esto se consigue expandiendo en fracciones parciales X[z]/z que son fracciones parciales modificadas cuando se tiene un factor z en el numeradory luego se restauran multiplicando el todo el resultado por z.
\frac{X[z]}{z} = \frac{8z-19}{z(z-2)(z-3)}
=\frac{-19/6}{z} + \frac{3/2}{z-2} + \frac{5/3}{z-3}
que al multiplicar ambos lados por z, se obtiene,
X[z] =\frac{-19}{6} + \frac{3}{2}\frac{z}{z-2} + \frac{5}{3}\frac{z}{z-3}
y usando la tabla de transformadas z se obtiene:
x[n] = \frac{-19}{6} \delta [n] + \Big[ \frac{3}{2}(2)^n + \frac{5}{3}(3)^n \Big] \mu[n]
que es el resultado esperado y con respuesta equivalente al resolver con algoritmo iterativo para n=0,1,2,3,…
Por este motivo, es recomendable siempre expandir en fracciones parciales X[z]/z en lugar de solo X[z], pues tiene un factor z en el numerador.
Algoritmo en Python
Para realizar el ejercicio, debemos considerar usar Sympy. Las operaciones se realizan al dividir X[x]/z y simplificar la nueva expresión Xzz, luego una expansión Xzp. El resultado se multiplica término a término por z y de añaden a la expresión total Xzfp.
El bloque de ingreso que se modifica para cada caso es:
Pz = 8*z-19
Qz = (z-2)*(z-3)
El resultado obtenido es:
Xz:
8*z - 19
---------------
(z - 3)*(z - 2)
Xz/z:
8*z - 19
----------------
/ 2 \
z*\z - 5*z + 6/
Xz/z.apart:
3 5 19
--------- + --------- - ---
2*(z - 2) 3*(z - 3) 6*z
Xz = (Xz/z)*z
3*z 5*z 19
--------- + --------- - --
2*(z - 2) 3*(z - 3) 6
{polos:veces}: {3: 1, 2: 1}
>>>
Instrucciones en Python
# Transformada z- Fracciones parciales
# Polos únicos, repetidos y complejos
# Lathi Ejercicio 5.3a pdf495
# blog.espol.edu.ec/telg1001
import numpy as np
import sympy as sym
# INGRESO
z = sym.Symbol('z')
Pz = 8*z-19
Qz = (z-2)*(z-3)
# PROCEDIMIENTO
P = Pz.as_poly(z)
Q = Qz.as_poly(z)
Xz = Pz/Qz
# Raices Denominador
Q_raiz = sym.roots(Q)
Q_raizRe = sym.real_roots(Q)
rcompleja = len(Q_raiz)-len(Q_raizRe)
# Raices reales, únicas y repetidas
if (rcompleja<=0 and len(Q_raizRe)>0):
# fracciones parciales modificadas
Xzz = (P/Q)/z
Xzm = Xzz.apart()
# fracciones parciales restaurada
terminos = Xzm.args
Xzp = 0*z
for untermino in terminos:
Xzp = Xzp + untermino*z
# SALIDA
print('\n Xz:')
sym.pprint(Xz)
if (len(Q_raizRe)>0):
print('\n Xz/z:')
sym.pprint(Xzz)
print('\n Xz/z.apart:')
sym.pprint(Xzm)
print('\n Xz = (Xz/z)*z')
sym.pprint(Xzp)
print('\n {polos:veces}: ', Q_raiz)
print('\n polos Re: ', Q_raizRe)
if (rcompleja>0):
print( ' Existen raíces complejas en denominador')
print( ' Revisar la sección correspondiente')
Ejercicio 2. Polos repetidos
Referencia: Lathi Ejercicio 5.3b p495
Realice la expansión en fracciones parciales de,
X[z] = \frac{z(2z^2-11z+12)}{(z-1)(z-2)^{3}}
Antes de realizar la expansión en fracciones parciales, se divide ambos lados de la expresión para z. Es decir se usa fracciones parciales modificadas
\frac{X[z]}{z} = \frac{1}{z}\frac{z(2z^2-11z+12)}{(z-1)(z-2)^{3}}
\frac{X[z]}{z} = \frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}}
donde el modelo de las fracciones parciales a aplicar es:
\frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}} = \frac{k}{z-1} + \frac{a_0}{(z-2)^3} + \frac{a_1}{(z-2)^2} + \frac{a_2}{(z-2)}
Para encontrar las constantes, se evalúa la expresión de la izquierda con los valores de cada raiz del denominador, en cada caso se obvia el término de la raiz en el denominador,
k = \frac{(2z^2-11z+12)}{\cancel{z-1}(z-2)^{3}} \Bigg|_{z=1} = \frac{(2(1)^2-11(1)+12)}{((1)-2)^{3}} = -3
a_0 = \frac{(2z^2-11z+12)}{(z-1)\cancel{(z-2)^{3}}}\Bigg|_{z=2} = \frac{(2(2)^2-11(2)+12)}{((2)-1)} = -2
con lo que la expresión modelo se convierte en:
\frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}} = \frac{-3}{z-1} + \frac{-2}{(z-2)^3} + \frac{a_1}{(z-2)^2} + \frac{a_2}{(z-2)}
Una forma de resolver es por ejemplo para a2, multiplicar ambos lados por z y hacer que z→∞
\frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}} z = z \Big[\frac{-3}{z-1} + \frac{-2}{(z-2)^3} + \frac{a_1}{(z-2)^2} + \frac{a_2}{(z-2)}\Big]
\frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}} z = \frac{-3z}{z-1} + \frac{-2z}{(z-2)^3} + \frac{a_1z}{(z-2)^2} + \frac{a_2z}{(z-2)}\Big]
0 = \frac{-3}{1-1/z} + \frac{-2z}{(z-2)^3} + \frac{a_1z}{(z-2)^2} + \frac{a_2}{(1-2/z)}\Big]
0 = -3 + (0) + (0) + a_2
a_2 =3
quedando solamente una incógnita a1 por resolver,
\frac{(2z^2-11z+12)}{(z-1)(z-2)^{3}} = \frac{-3}{z-1} + \frac{-2}{(z-2)^3} + \frac{a_1}{(z-2)^2} + \frac{3}{(z-2)}
El valor de a1 se puede determinar haciendo z tomar un valor conveniente, es decir z=0 en ambos lados de la ecuación
\frac{(2(0)^2-11(0)+12)}{((0)-1)((0)-2)^{3}} = \frac{-3}{(0)-1} + \frac{-2}{((0)-2)^3} + \frac{a_1}{((0)-2)^2} + \frac{3}{((0)-2)}
\frac{12}{(-1)(-8)} = \frac{-3}{-1} + \frac{-2}{-8} + \frac{a_1}{4} + \frac{-3}{-2}
\frac{3}{2} = 3 + \frac{1}{4} + \frac{a_1}{4} - \frac{3}{2}
\frac{6}{2} - \frac{13}{4}= \frac{a_1}{4}
-\frac{1}{4}= \frac{a_1}{4}
a_1 = -1
completando la expresión:
\frac{X[z]}{z} = \frac{-3}{z-1} + \frac{-2}{(z-2)^3} + \frac{-1}{(z-2)^2} + \frac{3}{(z-2)}
teniendo finalmente X[z] al multiplicar ambos lados por z,
X[z] = \frac{-3z}{z-1} + \frac{-2z}{(z-2)^3} + \frac{-1z}{(z-2)^2} + \frac{3z}{(z-2)}
y usando la tabla de transformadas z se obtiene:
x[n] = \Big[-3 -2 \frac{n(n-1)}{8}(2)^n - \frac{n}{2}(2)^n + 3(2)^n \Big] \mu [n]
simplificando un poco:
x[n] = \Big[-3 -\Big(\frac{n(n-1)}{4} + \frac{n}{2} - 3\Big)(2)^n \Big] \mu [n]
x[n] = -\Big[3 +\frac{1}{4}(n^2 + n-12)(2)^n \Big] \mu [n]
Usando el algoritmo en Python anterior, el bloque de ingreso cambia a:
Pz = z*(2*z**2-11*z+12)
Qz = (z-1)*(z-2)**3
con el resultado:
Xz:
/ 2 \
z*\2*z - 11*z + 12/
--------------------
3
(z - 2) *(z - 1)
Xz/z:
3 2
2*z - 11*z + 12*z
--------------------------------
/ 4 3 2 \
z*\z - 7*z + 18*z - 20*z + 8/
Xz/z.apart:
3 3 1 2
- ----- + ----- - -------- - --------
z - 1 z - 2 2 3
(z - 2) (z - 2)
Xz = (Xz/z)*z
3*z 3*z z 2*z
- ----- + ----- - -------- - --------
z - 1 z - 2 2 3
(z - 2) (z - 2)
{polos:veces}: {1: 1, 2: 3}
>>>
comparando con el resultado analítico es el mismo.
Ejercicio 3. Polos complejos
Referencia: Lathi Ejercicio 5.3c p495
Realice la expansión en fracciones parciales de,
X[z] = \frac{2 z(3z+17)}{(z-1)(z^2 - 6z+25)}
Se realiza la separación en fracciones parciales modificadas
\frac{X[z]}{z} = \frac{2(3z+17)}{(z-1)(z^2 - 6z+25)}
usando el método «cubrir» de Heaviside se tiene que :
k = \frac{2(3z+17)}{\cancel{(z-1)}(z^2 - 6z+25)} \Big|_{z=1}=2
queda por resolver la segunda parte de la fracción.
\frac{X[z]}{z} = \frac{2}{(z-1)}+\frac{Az+B}{z^2 - 6z+25}
Usando el método de los factores cuadráticos, se multiplica ambos lados por z y z→∞
\frac{X[z]}{z}z= z\frac{2}{(z-1)}+z\frac{Az+B}{z^2 - 6z+25}
0 = \frac{2}{(1-1/z)}+\frac{Az^2+Bz}{(z^2 - 6z+25)}
0 = \frac{2}{(1-1/z)}+\frac{A+B\frac{1}{z}}{\frac{1}{z^2}(z^2 - 6z+25)}
0 = \frac{2}{(1-1/z)}+\frac{A+B\frac{1}{z}}{1 - 6\frac{1}{z}+25\frac{1}{z^2}}
0 = 2+A
con lo que A = -2 , para encontrar B se usa un valor conveniente de z=0
\frac{2 z(3z+17)}{(z-1)(z^2 - 6z+25)} = \frac{2}{(z-1)}+\frac{Az+B}{z^2 - 6z+25}
\frac{2 (0+17)}{(0-1)(0^2 - 6(0)+25)} = \frac{2}{((0)-1)}+\frac{-2(0)+B}{(0^2 - 6(0)+25)}
\frac{34}{-25} = +\frac{2}{-1}+\frac{B}{25}
-\frac{34}{25} + 2=\frac{B}{25}
-34+ 2(25) = B
con lo que B=16
\frac{X[z]}{z}= \frac{2}{(z-1)}+\frac{-2z+16}{z^2 - 6z+25}
X[z]= \frac{2}{(z-1)}+\frac{z(-2z+16)}{z^2 - 6z+25}
con lo que es posible usar la tabla de transformadas z usando los items 2a y 12c. Para 12c los valores de A = -2, B = 16, |γ| =5 y a=-3.
r = \sqrt{\frac{(-2)^2 (5)^2+(16)^2-2(-2)(-3)(16)}{(5^2 -(-3)^2}} = \sqrt{\frac{100+256-192}{25-9}} =3.2
\beta = \cos^{-1} \Big(\frac{-(-3)}{5} \Big) = 0.927
\theta = \tan^{-1} \Bigg(\frac{(-2)(-3)-16}{(-2)\sqrt{(5^2 -(-3)^2}}\Bigg) = \tan^{-1}\Big( \frac{-10}{-8}\Big) = -2.246
reemplazando en la transformada, se encuentra x[n].
x[n] = [2+3.2(5)^n \cos(0.927n-2.246)] \mu [n]
pasamos a probar el algoritmo, donde se encuentra que para el denominador hay raíces complejas. Otra forma de observar es que las funciones parciales aún entregan resultados con términos que tienen el denominador con grado 2. Donde hay que usar expresiones de la tabla de transformadas.
Xz:
2*z*(3*z + 17)
-----------------------
/ 2 \
(z - 1)*\z - 6*z + 25/
Xz/z:
2
6*z + 34*z
-------------------------
/ 3 2 \
z*\z - 7*z + 31*z - 25/
Xz/z.apart:
2*(z - 8) 2
- ------------- + -----
2 z - 1
z - 6*z + 25
Xz = (Xz/z)*z
2*z*(z - 8) 2*z
- ------------- + -----
2 z - 1
z - 6*z + 25
{polos:veces}: {1: 1, 3 - 4*I: 1, 3 + 4*I: 1}
polos Re: [1]
parametros cuadraticos:
r 3.2015621187164243
gamma 5.0
beta 0.9272952180016123
theta 0.8960553845713439
>>>
Instrucciones en Python
El algoritmo inicia de la misma forma que en la sección anterior. Ahora hay que revisar el grado del denominador en cada término. Si es de grado 2, se calculan los valores de r, β y θ para armar las transformada a partir de la tabla.
# Transformada z- Fracciones parciales
# Polos únicos, repetidos y complejos
# Lathi Ejercicio 5.3c pdf495
# blog.espol.edu.ec/telg1001
import numpy as np
import sympy as sym
# INGRESO
z = sym.Symbol('z')
Pz = 2*z*(3*z+17) #z*(2*z**2-11*z+12) #8*z-19
Qz = (z-1)*(z**2-6*z+25) #(z-1)*(z-2)**3 #(z-2)*(z-3)
# PROCEDIMIENTO
P = Pz.as_poly(z)
Q = Qz.as_poly(z)
Xz = Pz/Qz
# Raices Denominador
Q_raiz = sym.roots(Q)
Q_raizRe = sym.real_roots(Q)
rcompleja = len(Q_raiz)-len(Q_raizRe)
# Raices reales, únicas y repetidas
if (rcompleja<=0 and len(Q_raizRe)>0):
# fracciones parciales modificadas
Xzz = (P/Q)/z
Xzm = Xzz.apart()
# fracciones parciales restaurada
terminos = Xzm.args
Xzp = 0*z
for untermino in terminos:
Xzp = Xzp + untermino*z
def parametro_cuadratico(untermino):
unparametro ={}
# revisa denominador cuadratico
[numerador,denominador] = (untermino).as_numer_denom()
gradoD = 0
coeficientesD = denominador
gradoN = 0
coeficientesN = numerador
if not(denominador.is_constant()):
denominador = denominador.as_poly()
gradoD = denominador.degree()
coeficientesD = denominador.coeffs()
if not(numerador.is_constant()):
numerador = numerador.as_poly()
gradoN = numerador.degree()
coeficientesN = numerador.coeffs()
if gradoD == 2 and gradoN==2:
a = float(coeficientesD[1])/2
gamma2 = float(coeficientesD[2])
gamma = np.sqrt(gamma2)
A = float(coeficientesN[0])
B = float(coeficientesN[1])
rN = (A**2)*gamma2 + B**2 - 2*A*a*B
rD = gamma2 - a**2
r = np.sqrt(rN/rD)
beta = np.arccos(-a/gamma)
thetaN = A*a-B
thetaD = A*np.sqrt(gamma2-a**2)
theta = np.arctan(thetaN/thetaD)
unparametro = {'r':r,
'gamma':gamma,
'beta':beta,
'theta':theta}
return (unparametro)
# Terminos cuadraticos
parametros = [] # denominador cuadratico
if (rcompleja>0 and len(Q_raizRe)>0):
# fracciones parciales modificadas
Xzz = (P/Q)/z
Xzm = Xzz.apart()
# fracciones parciales restaurada
terminos = Xzm.args
Xzp = 0*z
for untermino in terminos:
Xzp = Xzp + untermino*z
unparam = parametro_cuadratico(untermino*z)
if len(unparam)>0:
parametros.append(unparam)
if (rcompleja>0 and len(Q_raizRe)==0):
Xzp = P/Q
parametros.append(parametro_cuadratico(P/Q))
# SALIDA
print('\n Xz:')
sym.pprint(Xz)
if (len(Q_raizRe)>0):
print('\n Xz/z:')
sym.pprint(Xzz)
print('\n Xz/z.apart:')
sym.pprint(Xzm)
print('\n Xz = (Xz/z)*z')
sym.pprint(Xzp)
print('\n {polos:veces}: ', Q_raiz)
print('\n polos Re: ', Q_raizRe)
if len(parametros)>0:
for unparam in parametros:
print('parametros cuadraticos: ')
for cadauno in unparam.keys():
print(cadauno,'\t',unparam[cadauno])