Я думаю, что смогу приблизить вас к тому, что вы хотите;Я не собираюсь делать все это, хотя это может быть сложно, но я укажу вам в правильном направлении.
Прежде всего, использование индексов для обозначения различных переменных является сложным в Mathematica, поскольку он интерпретирует E
0
как Subscript[E,0]
, и оба E
и Subscript
зарезервированы,(Как сказал Шёрд, E = 2.718...
.) Чтобы Mathematica распознала <anything>
<something>
как отдельный символ, вам необходимо загрузить пакет Notations через <<Notations`
.Затем с помощью палитры обозначений Symbolize
Subscript[E,0]
.(В качестве предостережения не пытайтесь делать это без использования палитры для правильной настройки кода, в противном случае он может не сработать.)
Как только все ваши переменные будут обозначены по мере необходимости, вынеобходимо настроить соответствующие правила преобразования.Первые два являются простыми, введите
E_0[a] = a
E_0[x_0] = x_0
Правило 3 и 4:
E_0[x_Plus]:=Distribute[E_0[x]]
E_0[x_Times]:=Distribute[E_0[x], Times]
Это были простые, следующие три требуют другого вида ассоциации, ни Set
или SetDelayed
будут работать здесь, поскольку оцениваемый внешний символ равен Dt
, и вы не можете связать с ним новые правила, так как он Protected
.Однако существует два способа связать такие выражения с внутренним символом: UpSet (^=)
(или UpSetDelayed (^:=)
) или TagSet (/:)
.Я предпочитаю использовать TagSet
, поскольку он более явный, но любой из них должен работать.
Правило 5 и 6:
E_0 /: Dt[ E_0[ x_ ], y_ ] := E_0[ Dt[x,y] ]
Это также приблизит вас к правилу 7, но добавляяэто наряду с правилами 3 и 4 вызывает ошибку предела рекурсии, когда он подпрыгивает, пытаясь понять, как его оценить.Вместо этого замените правило 3 и 4 на
E_0[x_ + y__]:= E_0[x] + Plus@@( E_0 /@ {y} )
E_0[x_ y__ ] := E_0[x] Times@@( E_0 /@ {y} )
, что накладывает определенные ограничения на рекурсию.Что касается правила 7, вы получаете это
E_0[D[x_1[t_1,q_0], t_1]] E_0[Dt[t_1, y_0]]
+ E_0[D[x_1[t_1,q_0], q_0]] E_0[Dt[q_0,y]]
, которое является следствием правила Dt
и правила 4. Чтобы получить E_0
, чтобы не распределять по D
и Dt
оставлено в качестве упражнения.
Редактировать : Я хотел бы сделать несколько комментариев по предоставленному вами коду решения.Во-первых, умное использование логического значения для остановки рекурсии, и оно хорошо работает с вашим Notation
.Я бы посоветовал несколько изменений в дистрибуции вашего продукта.Во-первых, я бы использовал x__Times
вместо условия (/; Head[x] == Times
), так как его легче читать, и я верю (но не проверял), что это может быть быстрее, то есть меньше накладных расходов на его обработку.Во-вторых, замените используемое вами Table
на List @@ x
, где @@
, называемое Apply
, заменяет Times
на List
, и его снова легче читать и писать.Для определения n
рассмотрите возможность использования Complement
;Я не знаю, быстрее ли это, но я предпочитаю теоретико-множественные конструкции для такого типа вещей.И, наконец, если вам не нужна переоценка переменной при ее использовании , не используйте SetDelayed
(:=
), используйте Set
(=
).Используя :=
, m оценивается дважды, а v оценивается 3 раза!
"за" и "против" : Главными причинами этого являются простота использования и удобочитаемость.Определяя свои собственные объекты и их поведение, вы даете себе большую гибкость и упрощаете свой код.Уже одно это стоит того.Тем не менее, у меня были трудности с этим в прошлом, и такая установка может быть привередливой, и я бы рекомендовал провести тщательное тестирование.Во-вторых, добавляя эти дополнительные слои, вы можете замедлить ваш код, поэтому будьте осторожны, если он будет использоваться в критически важных приложениях.Кроме того, вы должны включать Notation
каждый раз, когда вы используете его, и палитра станет раздражать в какой-то момент.Хотя с палитрой можно справиться, установив AutoLoadNotationPalette = False
перед загрузкой пакета Notation.