220 lines
7.6 KiB
Python
220 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import sympy as sp
|
|
|
|
class FisExp:
|
|
|
|
def __init__ (self, funcao, valores_conhecidos=dict(), incertezas_conhecidas=dict()):
|
|
'''Inicializacao da funcao, em que configura a funcao principal, armazena os dicionarios e
|
|
configura valores.
|
|
'''
|
|
if type(funcao) is str:
|
|
self.__funcao = sp.sympify(funcao)
|
|
else:
|
|
self.__funcao = funcao
|
|
|
|
self.__variaveis = self.__funcao.atoms(sp.Symbol)
|
|
self.__incertezas = {}
|
|
for simbolo in self.__variaveis:
|
|
incerteza = sp.symbols('u_' + str(simbolo))
|
|
self.__incertezas[simbolo] = incerteza
|
|
|
|
self.__funcao_substituida = self.__funcao
|
|
self.__valores_conhecidos = dict()
|
|
self.valores_conhecidos = valores_conhecidos
|
|
|
|
self._propagacao()
|
|
self.__incertezas_conhecidas = dict()
|
|
self.incertezas_conhecidas = incertezas_conhecidas
|
|
|
|
@property
|
|
def funcao (self):
|
|
return self.__funcao
|
|
@funcao.setter
|
|
def funcao (self, nova_funcao):
|
|
self.__init__(nova_funcao)
|
|
|
|
@property
|
|
def variaveis (self):
|
|
return self.__variaveis
|
|
@variaveis.setter
|
|
def variaveis(self, a):
|
|
pass
|
|
|
|
@property
|
|
def incertezas (self):
|
|
return self.__incertezas
|
|
@incertezas.setter
|
|
def incertezas (self, a):
|
|
pass
|
|
|
|
@property
|
|
def valores_conhecidos (self):
|
|
return self.__valores_conhecidos
|
|
@valores_conhecidos.setter
|
|
def valores_conhecidos (self, valores_conhecidos):
|
|
'''Gera o atributo "funcao_substituida", que é a função com os valores conhecidos para algumas variáveis
|
|
É chamado por self.valores_conhecidos = dict com valores
|
|
Para apagar os valores substituídos, é necessário usar self.valores_conhecidos = {}
|
|
'''
|
|
#for var in valores_conhecidos.keys():
|
|
# self.__valores_conhecidos[var] = valores_conhecidos[var]
|
|
self.__valores_conhecidos = valores_conhecidos
|
|
|
|
if not valores_conhecidos:
|
|
self.__valores_conhecidos = dict()
|
|
self.__funcao_substituida = self.__funcao
|
|
else:
|
|
self.__funcao_substituida = self.__funcao.subs(self.__valores_conhecidos)
|
|
|
|
@property
|
|
def funcao_substituida (self):
|
|
return self.__funcao_substituida
|
|
@funcao_substituida.setter
|
|
def funcao_substituida (self, a):
|
|
pass
|
|
|
|
@property
|
|
def incertezas_conhecidas (self):
|
|
return self.__incertezas_conhecidas
|
|
@incertezas_conhecidas.setter
|
|
def incertezas_conhecidas (self, incertezas_conhecidas):
|
|
'''Gera o atributo "propagacao_substituida", que é a função de propagação com os valores
|
|
conhecidos para algumas variáveis.
|
|
É chamado por self.incertezas_conhecidas = dict com valores
|
|
'''
|
|
#for inc in incertezas_conhecidas.keys():
|
|
# self.__incertezas_conhecidas[inc] = incertezas_conhecidas[inc]
|
|
self.__incertezas_conhecidas = incertezas_conhecidas
|
|
|
|
incertezas_chaves_corretas = dict()
|
|
for chave_variavel in self.__variaveis:
|
|
if str(chave_variavel) in self.__incertezas_conhecidas.keys():
|
|
incertezas_chaves_corretas[str(self.__incertezas[chave_variavel])] = self.__incertezas_conhecidas[str(chave_variavel)]
|
|
|
|
propagacao_substituida = self.__propagacao.subs(incertezas_chaves_corretas)
|
|
propagacao_substituida = propagacao_substituida.subs(self.__valores_conhecidos)
|
|
|
|
self.__propagacao_substituida = propagacao_substituida
|
|
|
|
@property
|
|
def propagacao (self):
|
|
return self.__propagacao
|
|
@propagacao.setter
|
|
def propagacao (self, a):
|
|
pass
|
|
|
|
@property
|
|
def propagacao_substituida (self):
|
|
return self.__propagacao_substituida
|
|
@propagacao_substituida.setter
|
|
def propagacao_substituida (self, a):
|
|
pass
|
|
|
|
def _propagacao (self):
|
|
'''Calcula a propagação de incertezas da instância do objeto. A propagação utilizada é do tipo
|
|
"raiz quadrada da soma do produto dos quadrados das derivadas parciais e dos quadrados das incertezas
|
|
e utiliza como nome para cada incerteza "u_VARIAVEL".
|
|
'''
|
|
propagacao = sp.sympify('0')
|
|
for var in self.__variaveis:
|
|
propagacao += self.derivar(str(var))**2*self.__incertezas[var]**2
|
|
|
|
self.__propagacao = sp.sqrt(propagacao)
|
|
|
|
def gerar_funcao (self, variaveis_mantidas):
|
|
'''Gera uma funcao que tem como argumentos as variaveis em variaveis_mantidas, e permite
|
|
avaliar a funcao principal nos pontos escolhidos.
|
|
'''
|
|
variaveis = list()
|
|
for var in variaveis_mantidas:
|
|
variaveis.append(self._gerar_simbolo(var))
|
|
|
|
self.funcao_gerada = sp.lambdify(variaveis, self.__funcao_substituida)
|
|
|
|
def gerar_propagacao (self, variaveis_mantidas):
|
|
'''Gera uma funcao que tem como argumentos as variaveis em variaveis_mantidas, e permite
|
|
avaliar a propagacao nos pontos escolhidos.
|
|
'''
|
|
variaveis = list()
|
|
for var in variaveis_mantidas:
|
|
variaveis.append(self._gerar_simbolo(var))
|
|
|
|
self.propagacao_gerada = sp.lambdify(variaveis, self.__propagacao_substituida)
|
|
|
|
def integrar (self, var, limites=None, substituir=False):
|
|
'''Permite integrar facilmente a função na variável "var" (que deve vir como string), e
|
|
se o parâmetro "limites" for utilizado, retorna a integral avaliada nesses pontos.
|
|
'''
|
|
self._gerar_simbolo(var)
|
|
if limites is None:
|
|
if substituir:
|
|
return self.__funcao.integrate(self._ultimo_simbolo).subs(self.valores_conhecidos)
|
|
else:
|
|
return self.__funcao.integrate(self._ultimo_simbolo)
|
|
else:
|
|
if substituir:
|
|
return self.__funcao.integrate((self._ultimo_simbolo, limites[0], limites[1])).subs(self.valores_conhecidos)
|
|
else:
|
|
return self.__funcao.integrate((self._ultimo_simbolo, limites[0], limites[1]))
|
|
|
|
def derivar (self, var, ponto_avaliado=None, indice=1, substituir=False):
|
|
'''Permite derivar facilmente a função na variável "var" (que deve vir como string), e
|
|
se o parâmetro "ponto_avaliado" for configurado, avalia a função derivada naquele ponto.
|
|
Se o parâmetro "indice" for utilizado, será calculada a derivada daquele grau
|
|
'''
|
|
if var is not str:
|
|
self._ultimo_simbolo = var
|
|
else:
|
|
self._gerar_simbolo(var)
|
|
|
|
if ponto_avaliado is None:
|
|
if substituir:
|
|
return self.__funcao.diff(self._ultimo_simbolo, indice).subs(self.valores_conhecidos)
|
|
else:
|
|
return self.__funcao.diff(self._ultimo_simbolo, indice)
|
|
else:
|
|
if substituir:
|
|
return self.__funcao.diff(self._ultimo_simbolo, indice).subs(self._ultimo_simbolo, ponto_avaliado).subs(self.valores_conhecidos)
|
|
else:
|
|
return self.__funcao.diff(self._ultimo_simbolo, indice).subs(self._ultimo_simbolo, ponto_avaliado)
|
|
|
|
def _gerar_simbolo (self, var):
|
|
'''Para permitir a interação com os símbolos internos do programa, é gerado um símbolo
|
|
referente à "var" (que deve vir como string). Esse símbolo é guardado em "_ultimo_simbolo"
|
|
para permitir que seja utilizado de maneira fácil
|
|
'''
|
|
self._ultimo_simbolo = sp.symbols(str(var))
|
|
return self._ultimo_simbolo
|
|
|
|
def __str__ (self):
|
|
return str(self.__funcao)
|
|
|
|
def __repr__ (self):
|
|
return ('FisExp(\'' + str(self) + '\', ' + str(self.__valores_conhecidos) + ', ' + str(self.__incertezas_conhecidas) + ')')
|
|
|
|
|
|
if __name__ == "__main__":
|
|
f = sp.sympify('x*a+b+c')
|
|
f_a = FisExp(f)
|
|
print ("Funcao: ", str(f_a))
|
|
print ("Propagacao: ", f_a.propagacao)
|
|
variaveis = {'a':4, 'b':3, 'x':2}
|
|
asd = {'a':1, 'b':3, 'c':1, 'x':3}
|
|
f_a.valores_conhecidos = variaveis
|
|
f_a.incertezas_conhecidas = asd
|
|
print ("Substituicao: ", f_a.funcao_substituida)
|
|
f_a.funcao_substituida = 'bla'
|
|
print("Teste de substituicao: ", f_a.funcao_substituida)
|
|
variaveis1 = dict()
|
|
f_a.valores_conhecidos = variaveis1
|
|
f_a.valores_conhecidos = variaveis
|
|
print("Teste de substituicao 2: ", f_a.funcao_substituida)
|
|
print ('Propagacao substituida: ', f_a.propagacao_substituida)
|
|
print ('Integral em x: ', f_a.integrar('x'))
|
|
print ('Derivada em x: ', f_a.derivar('x'))
|
|
f_a.gerar_funcao(['c'])
|
|
f_a.gerar_propagacao(['c'])
|
|
print ('Funcao gerada avaliada em c=5: ', f_a.funcao_gerada(5))
|
|
print ('Propagacao gerada avaliada em c=5: ', f_a.propagacao_gerada(5)) |