Times и NonCommulativeMultiply, передавая разницу автоматически - PullRequest
4 голосов
/ 03 декабря 2011

У меня есть некоторые символы, которые должны быть некоммутативными, но я не хочу помнить, какие выражения имеют такое поведение при построении уравнений.

У меня была мысль использовать MakeExpression, чтобы воздействовать на необработанные блоки, и автоматически повышать множитель до некоммутативного умножения, когда это необходимо (например, когда некоторые символы являются некоммутативными объектами).

Мне было интересно, имел ли кто-нибудь опыт работы с такого рода конфигурацией.

Вот что у меня так далеко:

(* Detect whether a set of row boxes represents a multiplication *)

Clear[isRowBoxMultiply];
isRowBoxMultiply[x_RowBox] := (Print["rowbox: ", x]; 
  Head[ToExpression[x]] === Times)
isRowBoxMultiply[x___] := (Print["non-rowbox: ", x]; False)

(* Hook into the expression maker, so that we can capture any \
expression of the form F[x___], to see how it is composed of boxes, \
and return true or false on that basis *)

MakeExpression[
  RowBox[List["F", "[", x___, "]"]], _] := (HoldComplete[
   isRowBoxMultiply[x]])

(* Test a number of expressions to see whether they are automatically \
detected as multiplies or not. *)
F[a]
F[a b]
F[a*b]
F[a - b]
F[3 x]
F[x^2]
F[e f*g ** h*i j]

Clear[MakeExpression]

Это, кажется, правильно идентифицирует выражения, которые являются операторами умножения:

During evaluation of In[561]:= non-rowbox: a
Out[565]= False

During evaluation of In[561]:= rowbox: RowBox[{a,b}]
Out[566]= True

During evaluation of In[561]:= rowbox: RowBox[{a,*,b}]
Out[567]= True

During evaluation of In[561]:= rowbox: RowBox[{a,-,b}]
Out[568]= False

During evaluation of In[561]:= rowbox: RowBox[{3,x}]
Out[569]= True

During evaluation of In[561]:= non-rowbox: SuperscriptBox[x,2]
Out[570]= False

During evaluation of In[561]:= rowbox: RowBox[{e,f,*,RowBox[{g,**,h}],*,i,j}]
Out[571]= True

Итак, похоже, что это не из тех вопросов, которые я мог бы условно переписать в ячейки базового выражения; но как это сделать надежно?

Возьмите выражение RowBox[{"e","f","*",RowBox[{"g","**","h"}],"*","i","j"}], его нужно переписать как RowBox[{"e","**","f","**",RowBox[{"g","**","h"}],"**","i","**","j"}], что выглядит как нетривиальная операция, связанная с сопоставителем шаблонов и набором правил.

Буду благодарен за любые предложения от более опытных со мной.

Я пытаюсь найти способ сделать это без изменения поведения по умолчанию и порядка умножения.

Спасибо! :)

Джо

Ответы [ 4 ]

4 голосов
/ 03 декабря 2011

Это не самый прямой ответ на ваш вопрос, но для многих целей работа на низком уровне, так как непосредственно с коробками может быть излишним.Вот альтернатива: позвольте парсеру Mathematica проанализировать ваш код и затем внести изменения.Вот возможность:

ClearAll[withNoncommutativeMultiply];
SetAttributes[withNoncommutativeMultiply, HoldAll];
withNoncommutativeMultiply[code_] :=
  Internal`InheritedBlock[{Times},
     Unprotect[Times];
     Times = NonCommutativeMultiply;
     Protect[Times];
     code];

Это динамически заменяет Times на NonCommutativeMultiply и позволяет избежать сложностей, которые вы упомянули.Используя Internal`InheritedBlock, я делаю изменения в Times локально для кода, выполняемого внутри withNoncommutativeMultiply.

Теперь вы можете автоматизировать применение этой функции с помощью $Pre:

$Pre  = withNoncommutativeMultiply;

Теперь, например:

In[36]:= 
F[a]
F[a b]
F[a*b]
F[a-b]
F[3 x]
F[x^2]
F[e f*g**h*i j]

Out[36]= F[a]
Out[37]= F[a**b]
Out[38]= F[a**b]
Out[39]= F[a+(-1)**b]
Out[40]= F[3**x]
Out[41]= F[x^2]
Out[42]= F[e**f**g**h**i**j]

Конечно, использование $Pre таким способом вряд ли уместно, поскольку во всем вашем коде умножение будет заменено некоммутативным умножением - я использовалэто как иллюстрация.Вы можете сделать более сложное переопределение Times, чтобы это работало только для определенных символов.

Вот более безопасная альтернатива, основанная на лексической, а не динамической области видимости:

ClearAll[withNoncommutativeMultiplyLex];
SetAttributes[withNoncommutativeMultiplyLex, HoldAll];
withNoncommutativeMultiplyLex[code_] :=
  With @@ Append[
      Hold[{Times = NonCommutativeMultiply}], 
      Unevaluated[code]]

Вы можете использовать это таким же образом, но только те экземпляры Times, которые явноприсутствующий в коде будет заменен.Опять же, это просто иллюстрация принципов, можно расширить или специализировать это по мере необходимости.Вместо With, который довольно ограничен в своей возможности специализировать / добавлять специальные случаи, можно использовать правила замены, которые имеют похожую семантику.

1 голос
/ 12 декабря 2011

Итак, это не дает прямого ответа на вопрос, но обеспечивает реализацию, о которой я думал.

Итак, после небольшого исследования и принятия некоторых предложений @ LeonidShifrinМне удалось реализовать большую часть того, о чем я думал.Идея состоит в том, что можно определить шаблоны, которые следует считать некоммутирующими величинами, используя commutingQ[form] := False.Тогда любое мультипликативное выражение (фактически любое выражение) может быть заключено в withCommutativeSensitivity[expr], и выражение будет манипулироваться для разделения величин на подвыражения Times[] и NonCommutativeMultiply[], в зависимости от ситуации,

In[1]:= commutingQ[b] ^:= False;
In[2]:= withCommutativeSensitivity[ a (a + b + 4) b (3 + a) b ]
Out[1]:= a (3 + a) (a + b + 4) ** b ** b

OfКонечно, можно использовать $Pre = withCommutativeSensitivity, чтобы это поведение стало стандартным (давай, Вольфрам! Сделай его уже стандартным;)).Однако было бы неплохо иметь более фундаментальное поведение.Я действительно хотел бы сделать модуль и Needs[NonCommutativeQuantities] в начале любой записной книжки, которая ему нужна, и не иметь всех возможностей, которые используют $ Pre break на мне (разве не трассировка его использует?).

Интуитивно я чувствую, что должен быть естественный способ подключить эту функциональность к Mathematica на уровне разбора блока и подключить его, используя MakeExpression[].Я слишком растягиваюсь здесь?Буду признателен за любые мысли о том, преследую ли я тупик.(У меня было несколько экспериментов в этом направлении, но меня всегда ловит рекурсивное определение, которое я не могу понять, как сломаться).

Любые мысли будут с радостью приняты, Джо.

Код

Unprotect[NonCommutativeMultiply];
ClearAll[NonCommutativeMultiply]
NonCommutativeMultiply[a_] := a
Protect[NonCommutativeMultiply];

ClearAll[commutingQ]
commutingQ::usage = "commutingQ[\!\(\*
    StyleBox[\"expr\", \"InlineFormula\",\nFontSlant->\"Italic\"]\)] \
    returns True if expr doesn't contain any constituent parts that fail \
    the commutingQ test. By default all objects return True to \
    commutingQ.";
commutingQ[x_] :=  If[Length[x] == 0, True, And @@ (commutingQ /@ List @@ x)]

ClearAll[times2, withCommutativeSensitivity] 
SetAttributes[times2, {Flat, OneIdentity, HoldAll}]
SetAttributes[withCommutativeSensitivity, HoldAll];

gatherByCriteria[list_List, crit_] := 
 With[{gathered = 
    Gather[{#, crit[#1]} & /@ list, #1[[2]] == #2[[2]] &]},
        (Identity @@ Union[#[[2]]] -> #[[1]] &)[Transpose[#]] & /@ gathered]

times2[x__] := Module[{a, b, y = List[x]}, 
    Times @@ (gatherByCriteria[y, commutingQ] //.
      {True -> Times, False -> NonCommutativeMultiply, 
       HoldPattern[a_ -> b_] :> a @@ b})]

withCommutativeSensitivity[code_] := With @@ Append[
    Hold[{Times = times2, NonCommutativeMultiply = times2}], 
    Unevaluated[code]]
1 голос
/ 04 декабря 2011

Если я правильно понимаю, вы хотите ввести а б и а * б и пусть MMA автоматически поймет, что Times на самом деле некоммутативный оператор (у которого есть свои -разделенные - правила коммутации). Ну, я предлагаю вам использовать пакет обозначений. Он очень мощный и (относительно) простой в использовании (особенно для такого искушенного пользователя, как вы, кажется). Он может использоваться программно и может интерпретировать предопределенные символы, такие как Times. По сути, он может перехватывать Times и изменять его на MyTimes. Затем вы пишете код для MyTimes, решая, например, какие символы не коммутируют, и затем вывод может быть снова довольно отформатирован как раз или как угодно. Обработка ввода и вывода состоит из 2 строк кода. Это оно! Вы должны внимательно прочитать документацию и поэкспериментировать, если вы не хотите более или менее «стандартного взлома» заданий ввода-вывода. Ваш случай кажется мне довольно стандартным (опять же: если я хорошо понял, чего вы хотите достичь), и вам должно быть полезно прочитать «продвинутые» страницы пакета Notation. Чтобы дать вам представление о том, насколько мощным и гибким является пакет, я использую его для записи форматирования ввода-вывода значительного пакета теории категорий, в котором имеется множество некоммутативных операций. Но ждать! Я не просто определяю ОДНУ некоммутативную операцию, я определяю неограниченное количество некоммутативных операций. Еще одна вещь, которую я сделал, - это переосмысление Power, когда аргументы являются категориями, без перегрузки Power. Это позволяет мне рассматривать функторные категории, используя стандартные математические обозначения. Теперь мои «бесконечные» операции и «сверхдержава» выглядят одинаково со стандартными символами ММА, включая функции копирования и вставки.

0 голосов
/ 04 декабря 2011

Этот ответ не относится к вашему вопросу, а скорее к проблеме, которая заставляет вас задать этот вопрос.Mathematica довольно бесполезна, когда имеешь дело с некоммутирующими объектами, но поскольку таких объектов, например, в физике элементарных частиц, предостаточно, есть несколько полезных пакетов для решения этой ситуации.

Посмотрите на grassmanOps пакет.У них есть метод для определения символов как коммутирующих или антикоммутирующих, так и перегрузки стандартного NonCommulativeMultiply для обработки, т. Е. Прохождения, коммутирующих символов.Они также определяют несколько других операторов, таких как Derivative, для обработки антикоммутирующих символов.Вероятно, его легко адаптировать к произвольным правилам коммутации, и он должен, по крайней мере, дать вам представление о том, какие вещи нужно изменить, если вы хотите свернуть свои собственные.

...