La multiplicación entre impulso δ(t) o escalón unitario μ(t) aparece al desarrollar en integral de convolución cuando ambas señales son de tipo causal.
x(t) \circledast h(t) = \int_{-\infty}^{+\infty} x(\tau)h(t-\tau) \delta \tauLas expresiones resultantes pueden incluir algunas de éstas operaciones como se muestra en el ejemplo 3 de una convolución entre señales tipo rectangular y rampa de carácter causal.
x(t) = \mu (t) - \mu (t-1) h(t) = t\mu (t) - t\mu (t-2)Con respuestas al usar el algoritmo con Sympy que integran varias multiplicaciones de escalón unitario.
Como Sympy ‘1,11,1’ revisada en Enero del 2023, aún no incluye este tipo de operaciones, se realizan dos funciones: simplifica_impulso() y simplifica_escalon(). Se desarrolla como un ejercicio de análisis de expresiones con Sympy.
>>> sym.__version__ '1.11.1'
Simplificar multiplicación de impulso unitario δ(t)
Las operaciones encontradas en los ejercicios del curso dan una idea básica de por dónde empezar. También se probó las instrucciones doit(), evalf() sin cambios.
>>> sym.DiracDelta(t)*sym.DiracDelta(t-1) DiracDelta(t)*DiracDelta(t - 1) >>> sym.simplify(sym.DiracDelta(t)*sym.DiracDelta(t-1)) DiracDelta(t)*DiracDelta(t - 1) >>> sym.DiracDelta(t)**2 DiracDelta(t)**2 >>> sym.simplify(sym.DiracDelta(t)**2) DiracDelta(t)**2 >>>
Como punto de partida de plantea encontrar todos los puntos de la expresión donde intervienen los impulsos. La función busca_impulso() permite revisar si existiendo impulsos en diferentes tiempos, el resultado deberá ser cero.
x = d h = d.subs(t,t-1) xh = x*h
Para facilitar el análisis se realizan las gráficas de las dos funcines que se multiplican y la operación resultante del algoritmo:
otro caso a considerar es:
x = sym.sin(t) h = d.subs(t,t-2) xh = x*h
Instrucciones con Python
El algoritmo se desarrolla como funciones, para ser incorporadas a telg1001.py
# Simplificar multiplicacion de impulso unitario d(t)*d(t-1) # https://blog.espol.edu.ec/telg1001/simplificar-multiplicacion-impulso-o-escalon-unitario-sympy/ import numpy as np import matplotlib.pyplot as plt import sympy as sym equivalentes = [{'DiracDelta': lambda x: 1*(x==0)}, {'Heaviside': lambda x,y: np.heaviside(x, 1)}, 'numpy',] import telg1001 as fcnm # INGRESO t = sym.Symbol('t',real=True) tau = sym.Symbol('tau',real=True) u = sym.Heaviside(t) d = sym.DiracDelta(t) # entrada x(t), respuesta impulso h(t) # x = d # h = d.subs(t,t-1) # h = d # h= d**2 # x = 2 # h = d # h = sym.pi*d.subs(t,t-2) x = sym.sin(t) h = d.subs(t,t-2) # h = 5*d.subs(t,t-2)**2 # x = d.subs(t,t-1) # h = u.subs(t,t-1) # h = d*u.subs(t,t-2)+ u*u.subs(t,t-2) # h = d*d.subs(t,t-1)*u.subs(t,t+2)+3 # grafica intervalo [t_a,t_b] plano simétrico t_b = 4 ; t_a = -t_b muestras = 81 # PROCEDIMIENTO def simplifica_impulso(ft): ''' simplifica d**2, d(t-1)*d ''' def simplifica_d_d(ft): '''un termino de suma d**2, d(t+1)*d, ''' respuesta = ft if ft.has(sym.DiracDelta):# tiene impulsos impulso_en = fcnm.busca_impulso(ft) if len(impulso_en)==0: # anulado por d(t-a)*d(t-b) respuesta = 0*t elif len(impulso_en)>0: # tiene impulsos respuesta = 1 factor_mul = sym.Mul.make_args(ft) for factor_k in factor_mul: if not(factor_k.has(sym.DiracDelta)): if not(factor_k.has(sym.Heaviside)): termino = factor_k.subs(t,impulso_en[0]) else: # tiene escalón termino = factor_k.subs(t,impulso_en[0]) if termino == 1/2: #coinciden d,u termino = 1 respuesta = respuesta*termino else: # factor con impulso if factor_k.is_Pow: # tiene exponente respuesta = respuesta*factor_k.args[0] else: # termino sin exponente respuesta = respuesta*factor_k return(respuesta) # revisa terminos suma respuesta = 0*t ft = sym.expand(ft,t) term_suma = sym.Add.make_args(ft) for term_k in term_suma: respuesta = respuesta + simplifica_d_d(term_k) return(respuesta) xh = x*h ft = simplifica_impulso(xh) # SALIDA print('xh inicial:') sym.pprint(xh) print('h simplificado:') sym.pprint(ft) # grafica figura = fcnm.graficar_xh_y(x,h,ft,t_a,t_b,muestras,y_nombre='xh') plt.show()
Simplificar multiplicación de escalón unitario μ(t)
Las operaciones encontradas en los ejercicios del curso dan una idea básica de por dónde empezar
>>> sym.Heaviside(t)*sym.Heaviside(t-1) Heaviside(t)*Heaviside(t - 1) >>> sym.simplify(sym.Heaviside(t)*sym.Heaviside(t-1)) Heaviside(t)*Heaviside(t - 1) >>> sym.simplify(sym.Heaviside(-t+1)*sym.Heaviside(t-1)) Heaviside(1 - t)*Heaviside(t - 1) >>> sym.simplify(sym.Heaviside(t)**2) Heaviside(t)**2 >>> sym.simplify(sym.DiracDelta(t-1)*sym.Heaviside(t)) DiracDelta(t - 1)*Heaviside(t) >>>
Como punto de partida de plantea encontrar todos los puntos de la expresión donde intervienen el escalón unitario. La función busca_escalon() permite revisar la ubicación y el sentido de desarrollo de cada escalón unitario, con estos datos se puede determinar si la función se anula con la otra o la parte que permanece.
x = u h = u.subs(t,t-1) xh = x*h
Con una grafica se puede comprobar el escalón que se superpone en la multiplicación de x(t)h(t).
otro ejercicio a considerar es cuando los escalones unitarios se pueden complementar o anular. En el siguiente ejemplo x(t) h(t) se anulan entre si.
x = u.subs(t,t-1) h = u.subs(t,-t-1) xh = x*h
mientras en en otro caso, las señales tienen una región donde pueden coexistir
x = u.subs(t,-t+1) h = u.subs(t,t-0)
Instrucciones con Python
# Simplificar multiplicacion de escalon unitario u(t)*u(t-1) # https://blog.espol.edu.ec/telg1001/simplificar-multiplicacion-impulso-o-escalon-unitario-sympy/ import numpy as np import matplotlib.pyplot as plt import sympy as sym equivalentes = [{'DiracDelta': lambda x: 1*(x==0)}, {'Heaviside': lambda x,y: np.heaviside(x, 1)}, 'numpy',] import telg1001 as fcnm # INGRESO t = sym.Symbol('t',real=True) u = sym.Heaviside(t) d = sym.DiracDelta(t) # entrada x(t), respuesta impulso h(t) # x = u # h = u.subs(t,t-1) # x = u.subs(t,t-1) # h = u.subs(t,-t-1) x = u.subs(t,-t+1) h = u.subs(t,t-0) #x = 3*u.subs(t,-t+2) #h = 2*u.subs(t,-t+3) # x = u.subs(t,t+1)*u.subs(t,-t+2) # h = 1 # h = d.subs(t,-t+2)#*u.subs(t,t-3) # grafica intervalo [t_a,t_b] plano simétrico t_b = 4 ; t_a = -t_b muestras = 301 # PROCEDIMIENTO def simplifica_escalon(ft): ''' simplifica multiplicaciones Heaviside(t-a)*Heaviside(t-b) en f(t) ''' def simplifica_u_u(ft): '''solo dos pares de u(t-1)*u(t-2), sin coeficientes ''' donde_u = fcnm.busca_escalon(ft) donde_u = np.array(donde_u) # direccion donde_[:,1], # lugar donde[:,0] # analiza multiplicación resultado = ft # todo igual if donde_u[0,1]*donde_u[1,1] > 0: # direccion igual k = 0 if donde_u[0,1]>0: # hacia derecha k = np.argmax(donde_u[:,0]) k_signo = 1 else: # hacia izquierda k = np.argmin(donde_u[:,0]) k_signo = -1 ubica = donde_u[k,1]*t-k_signo*donde_u[k][0] resultado = sym.Heaviside(ubica) else: # direccion diferente if donde_u[0][1]>0 and (donde_u[0,0]>donde_u[1,0]): resultado = 0 if donde_u[0][1]<0 and (donde_u[0,0]<=donde_u[1,0]): resultado = 0 return(resultado) def simplifica_u_term(ft): ''' simplifica un termino de varios factores que multiplican 2*pi*u*u(t-1) ''' respuesta = ft if ft.has(sym.Heaviside): # tiene escalon escalon_en = fcnm.busca_escalon(ft) revisa = 1 ; otros = 1 ; cuenta = 0 factor_mul = sym.Mul.make_args(ft) for factor_k in factor_mul: if factor_k.has(sym.Heaviside): if factor_k.is_Pow: # con exponente revisa = revisa*factor_k.args[0] cuenta = cuenta + 1 else: # sin exponente revisa = revisa*factor_k cuenta = cuenta + 1 if cuenta>1: # simplificar revisa = simplifica_u_u(revisa) cuenta = len(fcnm.busca_escalon(revisa)) else: # factor sin Heaviside otros = otros*factor_k respuesta = otros*revisa return(respuesta) # revisa terminos suma respuesta = 0*t ft = sym.expand(ft,t) if ft.has(sym.DiracDelta): # tiene impulsos ft = fcnm.simplifica_impulso(ft) term_suma = sym.Add.make_args(ft) for term_k in term_suma: respuesta = respuesta + simplifica_u_term(term_k) return(respuesta) xh = x*h ft = simplifica_escalon(xh) # SALIDA print('busca_impulso(ft)', fcnm.busca_impulso(h)) print('busca_escalon(ft)', fcnm.busca_escalon(h)) print('x*h inicial:') sym.pprint(xh) print('simplificado:') sym.pprint(ft) # grafica figura = fcnm.graficar_xh_y(x,h,ft,t_a,t_b,y_nombre='xh') plt.show()
..