Desejo derivar uma função complexa. Infelizmente, ao construir a expressão a ser derivada, ela expande todas as subexpressões até os símbolos usados imediatamente. Assim, uma vez que diferencio a expressão final, ela infla para um tamanho incontrolável. Tentei substituir manualmente algumas subexpressões de volta à sua forma anterior no resultado final, mas devido à reestruturação durante a construção da expressão, isso perde muitas oportunidades de simplificação.
Aqui está apenas o primeiro estágio do que eu quero derivar e já está irremediavelmente inchado mesmo depois de tentar substituir algumas expressões usadas para construí-lo.
from sympy import *
aX, aY, aZ = symbols('aX aY aZ')
rotInc = Matrix(3,1,[aX, aY, aZ])
theta = sqrt((rotInc.T @ rotInc)[0,0])
incQuat = Quaternion.from_axis_angle(rotInc/theta, theta*2)
qX, qY, qZ, qW = symbols('qX qY qZ qW')
baseQuat = Quaternion(qW, qX, qY, qZ)
poseQuat = incQuat * baseQuat
d4 = diff(poseQuat, aX)
d4s = d4.subs({
incQuat.a: symbols('iW'),
incQuat.b: symbols('iX'),
incQuat.c: symbols('iY'),
incQuat.d: symbols('iZ'),
theta: symbols('theta')
})
Eu conheço cse
(a eliminação comum de subexpressões) e isso me mostra que existe algum tipo de sistema para manter subexpressões nomeadas. Eu preferiria que o Sympy construísse uma estrutura como " cse
returns" enquanto eu construísse a expressão, e apenas substituísse uma subexpressão por seus componentes quando necessário – por exemplo, durante a diferenciação. Isso manteria a maioria desses símbolos na diferenciação final, resultando em uma saída mais limpa e imediatamente utilizável.
Existe algum modo/maneira de construir expressões no SymPy ou algo que me ajude a manter a expressão final simples? Obrigado!
Isto não é uma resposta, porque não sei o que você quer dizer. No entanto, entendo o seu problema. Você sabe que
theta
é uma função deaX, aY, aZ
, assim como os componentes deincQuat
. E se trabalharmos com funções aplicadas indefinidas, como esta?Esta é a expressão do seu primeiro passo. Então, quando você se sentir pronto para realizar o cálculo propriamente dito, substitua nos dicionários:
e você acabará com expressões muito longas...
Achei que isso estivesse em algum lugar do SymPy, mas talvez o uso de cse na preparação de funções compiladas (ou algo assim) seja onde ele é usado. Mas, seguindo sua ideia (e provavelmente redundante em relação ao que você pensa nesta questão ):
Então, com a dica das funções do @Davide_sd, criei um método genérico que me permite controlar facilmente como as subetapas são divididas. Basicamente, estou derivando manualmente as funções que separo, mas, assim como o CSE, mantenho os resultados em um dicionário para compartilhar entre todas as ocorrências.
As expressões base que compõem o cálculo são inseridas e nunca modificadas, a lista de derivação é semeada com o que você deseja derivar (múltiplas expressões são aceitáveis) e ele as derivará recursivamente, usando a lista de expressões conforme necessário.
No final, ainda posso usar o CSE para a) trazê-lo para esse formato, caso você precise, e b) fatorar ocorrências ainda mais comuns.
Funciona razoavelmente bem com meu pequeno exemplo; posso atualizá-lo conforme eu adicionar mais complexidade à função que preciso derivar.