SymPy: разобрать строку как функцию на многообразии
Я пытаюсь определить уравнение на многообразии, используя SymPy и пакет SygePy diffgeom. Поскольку это уравнение вводится пользователем, оно отправляется в программу в виде строки и поэтому определяется до определения многообразия в коде. Чтобы выполнить осмысленные вычисления, я пытаюсь заменить "упрощенные" символы символами, определенными на коллекторе.
Вот функция, предоставленная пользователем.
H = sympify('m*a - f')
Координаты для коллектора также предоставляются пользователем в виде строк.
# Variables defined as symbols (non-diffgeom)
a = Symbol('a')
f = Symbol('f')
И все впоследствии автоматизировано.
from sympy.diffgeom import Manifold, Patch, CoordSystem
from sympy import sympify, Symbol
# Standard manifold definitions
M = Manifold(name='Temp', dim=2)
P = Patch('P', M)
R = CoordSystem('R', P, ['a','f'])
coords = R.coord_functions()
Dx = R.base_vectors()
print(H.diff(a)) # Returns 'm' as expected
print(Differential(H)(Dx[0])) # Returns '0' as expected
Первая замена отлично работает. Я могу взять производные, как и ожидалось, используя Дифференциал ().
H = H.subs(a,coords[0])
print(H.diff(a)) # Returns '0' as expected
print(Differential(H)(Dx[0])) # Returns 'm' as expected
print(Differential(H)(Dx[1])) # Returns '0' as expected
Вторая замена - то, где вещи становятся странными. Команда ().diff() работает нормально и возвращает 0, так как новые координаты определены на многообразии, а не как стандартные символы, но я больше не могу брать производные с помощью Differential().
H = H.subs(f,coords[1])
print(H.diff(f)) # Returns '0' as expected
print(Differential(H)(Dx[0])) # Crashes code
print(Differential(H)(Dx[1])) # Also crashes code
Похоже, что diffgeom пытается выполнить преобразование для вычисления производных, но на самом деле преобразование не должно происходить, поскольку все они находятся в одной и той же системе координат. Я что-то здесь упускаю? Или есть более простой способ разбирать строки как выражения на многообразиях?
Вот полная ошибка. Я действительно не могу извлечь из этого ничего, кроме того, что SymPy пытается преобразовать координаты, когда я этого не ожидаю.
Traceback (most recent call last):
File "/Users/msparapa/Documents/Python/gprops/examples/test.py", line 37, in <module>
print(Differential(H)(Dx[0])) # Crashes code
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/diffgeom/diffgeom.py", line 765, in __call__
return vector_fields[0].rcall(self._form_field)
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/core/basic.py", line 538, in rcall
return Basic._recursive_call(self, args)
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/core/basic.py", line 552, in _recursive_call
return expr_to_call(*on_args)
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/diffgeom/diffgeom.py", line 592, in __call__
jac = self._coord_sys.jacobian(b._coord_sys, coords)
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/diffgeom/diffgeom.py", line 277, in jacobian
to_sys, self._dummies).jacobian(self._dummies)
File "/Users/msparapa/anaconda/lib/python3.5/site-packages/sympy/diffgeom/diffgeom.py", line 270, in coord_tuple_transform_to
transf = self.transforms[to_sys]
KeyError: CoordSystem(R, Patch(P, Manifold(Temp, 2)), (a, f))
1 ответ
После дальнейшего расследования причиной были символы с тем же именем. Исправление заключается в том, чтобы по существу заменить с помощью методов, описанных здесь, или использовать различные соглашения об именах.
Чтобы выполнить замену, мне нужно было поменять местами все переменные одновременно. Это было сделано с помощью следующего блока кода.
set = dict(zip([a,f],coords))
H = H.subs(set, simultaneous=True)
Где "а" и "f" - основные символы, а "координаты" - это список символов на многообразии. Замены не выполняются одновременно, а скорее последовательно, такие как
set = dict(zip([a,f],coords))
H = H.subs(set)
кинь ту же ошибку. Я полагаю, что это связано с тем, что и "а", и "f" скрыты в каждой координате многообразия. Чтобы увидеть, где это происходит, мы можем посмотреть на вывод Repr для ords[0].
BaseScalarField(CoordSystem(Symbol('R'), Patch(Symbol('P'), Manifold(Symbol('M'), Integer(2))), Tuple(Symbol('f'), Symbol('a'))), Integer(0))
Символ ('f') и Символ ('a') отображаются в системе координат. Здесь происходит то, что, когда я подставлял вторую переменную f в своем выражении, SymPy просматривал переменную моего многообразия a и видел переменную с тем же именем. Таким образом, он попытался заменить не только базовый символ f, но и символ f, скрытый в моем определении CoordSystem, возможно, затем вызвав преобразование системы координат.