2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 [Wolfram Mathematica] Pattern Matching: Sequences and Flat
Сообщение26.03.2015, 00:15 
Аватара пользователя
Вступление.
Пишу обобщенную функцию H, которая весьма терпима ко входу, анализирует его, частично упрощает, и передаёт те же данные в неком унифицированном виде.
По смысле в качестве аргумента передаётся нечто примерно вида n1 a1 + n2 a2 + ..., где n1 и n2 — числовые (впрочем, не обязательно Numeric) коэффициенты, a1 и a2 — сложные объекты с известной структурой.
Нужно привести подобные члены, при необходимости пораскрывать скобки по дистрибутивности вроде n1 (a1 + a2) -> n1 a1 + n1 a2 и попереставлять члены вроде n1 a1 n2 -> (n1 n2) a1. Для этого я использую Plus и Times, потому что они сами всё это делают. Остаётся результат распарсить и представить, например, в виде таблицы {{n1, a1}, {n2, a2}, ...}.

Вопрос.
Код:
Clear[H];
SetAttributes[H, {Flat, Orderless}];
H[terms_List] := H[Simplify[Plus @@ terms]];
H[Plus[terms : PatternSequence[_, __]]] := H[terms];

В последней строке я хочу сложение на верхнем уровне поглотить. Если я напишу H[Plus[terms__]] := H[terms], возникнет бесконечная рекурсия. Поэтому я в правиле указываю, что количество слагаемых должно быть больше 1. Однако, приведённый код не работает. Почему? Как это исправить?

P.S. другие советы тоже приветствую.

 
 
 
 Re: [Wolfram Mathematica] Pattern Matching: Sequences and Flat
Сообщение26.03.2015, 02:13 
Левая часть SetDelayed, естественно, «не Delayed». Потому
Код:
H[Plus[terms__]] := H[terms]
эквивалентна
Код:
H[terms__] := H[terms]
Эта тавтология и приводит к рекурсии.

Есть вариант
Код:
H[terms_Plus] := H[List @@ terms]
, но тут рекурсия возникает из-за имеющегося
Код:
H[terms_List] := H[Simplify[Plus @@ terms]];
Собственно, вопрос, что ожидается в конце вычислений: H[{...}] либо H[...+...] ?

Если я правильно понял задачу, решением может быть
Код:
H[terms_Plus] := H[List @@ Simplify[terms]]


Хотя, возможно, в итоге интереснее будет поработать с UpValues по типу
Код:
Unprotect[Plus];
Plus /: H[terms_Plus] := H[List @@ Simplify[terms]]

 
 
 
 Re: [Wolfram Mathematica] Pattern Matching: Sequences and Flat
Сообщение26.03.2015, 02:42 
У меня нерабочесть чего-то подобного была из-за атрибута Flat: «[Mathematica 8.0] Странное вычисление». Причины так и не понял.

 
 
 
 Re: [Wolfram Mathematica] Pattern Matching: Sequences and Flat
Сообщение26.03.2015, 02:58 
Аватара пользователя
Спасибо, такое интересное открытие.
Действительно левая часть SetDelayed не холдится. Я нашел в справке такой код:
Код:
H[HoldPattern[Plus[terms___]]] := H[terms];


apex в сообщении #995749 писал(а):
Собственно, вопрос, что ожидается в конце вычислений: H[{...}] либо H[...+...]?

H[..., ...]
Эта функция не несёт логику глобальной задачи, она всего лишь прослойка между пользователем и программой, нужная для того, чтобы пользователь случайно не обнаружил непонятную ошибку, если вместо H[a + 2 b + 2 c] напишет H[a + 2 (b + c)] или H[{a + 2 b}, 2 c].

arseniiv, мне атрибут Flat нужен для того, чтобы упрощать запись правил, поскольку при Flat можно указывать, как ведёт себя функция на каком-то аргументе или группе аргументов, а она сама себя уже распространит на случай большего числа аргументов.

 
 
 
 Re: [Wolfram Mathematica] Pattern Matching: Sequences and Flat
Сообщение26.03.2015, 03:02 
О, увидел ответ apex и тоже вспомнил про HoldPattern, но вы быстрее.

Mysterious Light в сообщении #995752 писал(а):
мне атрибут Flat нужен для того, чтобы упрощать запись правил, поскольку при Flat можно указывать, как ведёт себя функция на каком-то аргументе или группе аргументов, а она сама себя уже распространит на случай большего числа аргументов.
Ну, если теперь всё будет хорошо — ура, но вообще это поведение можно ведь записать и без атрибутов вручную (да, это ужасный совет :mrgreen:).

 
 
 [ Сообщений: 5 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group