aluno_exatas/aluno_exatas/fis_exp/classe_principal.py

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))