4

可換でないはずの記号がいくつかありますが、方程式を作成するときにどの式がこの動作をするかを覚えておく必要はありません。

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 に答える 4

4

これはあなたの質問に対する最も直接的な答えではありませんが、多くの目的で、ボックスを直接操作するのと同じくらい低レベルで作業するのはやり過ぎかもしれません。Mathematica パーサーにコードを解析させてから、変更を加えます。ここに可能性があります:

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

Timesこれは動的に に置き換えられNonCommutativeMultiply、あなたが言及した複雑さを回避します。を使用して 、内部で実行されるコードをローカルにInternal`InheritedBlock変更します。TimeswithNoncommutativeMultiply

この関数の適用を自動化できるようになりました$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特殊なケースを特殊化/追加する能力がかなり制限されているの代わりに、同様のセマンティクスを持つ置換ルールを使用できます。

于 2011-12-03T16:26:52.177 に答える
1

私が正しく理解していれば、abとa * bを入力し、MMAにTimesが実際には非可換演算子(独自の-separate-可換規則がある)であることを自動的に理解させたいと思います。さて、私の提案は、Notationパッケージを使用することです。それは非常に強力で(比較的)使いやすいです(特にあなたのような洗練されたユーザーにとって)。プログラムで使用でき、Timesなどの事前定義されたシンボルを再解釈できます。基本的に、Timesをインターセプトして、MyTimesに変更できます。次に、MyTimesのコードを記述して、たとえば、どのシンボルが通勤していないかを判断します。その後、出力を時間など、必要に応じてきれいにフォーマットし直すことができます。入力と出力の処理は2行のコードです。それでおしまい!ドキュメントを注意深く読み、実験を行う必要があります。必要なのが入出力ジョブの多かれ少なかれ「標準的なハッキング」ではない場合。あなたのケースは私にはかなり標準的なように思えます(繰り返しますが、あなたが達成したいことをよく理解していれば)、Notationパッケージの「高度な」ページを読むと役立つはずです。パッケージがどれほど強力で柔軟性があるかを理解するために、私はそれを使用して、非可換操作が豊富な圏論のかなり大きなパッケージの入出力フォーマットを記述しています。ちょっと待って!私は1つの非可換操作を定義しているだけでなく、無制限の数の非可換操作を定義しています。私がしたもう1つのことは、引数がカテゴリの場合にPowerをオーバーロードせずに、Powerを再解釈することでした。これにより、標準的な数学表記を使用してファンクトリアルカテゴリを処理できます。今、私の「無限の」操作と「超大国」

于 2011-12-04T17:10:02.330 に答える
1

したがって、これは質問に直接答えるものではありませんが、私が考えていたような実装を提供します。

それで、少し調査して@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

もちろん、$Pre = withCommutativeSensitivityこの動作をデフォルトにするために使用することは可能です(Wolframに来てください!すでにデフォルトにします;))。ただし、より基本的な動作をするのは良いことです。私は本当にモジュールを作りたいのですNeeds[NonCommutativeQuantities]が、それを必要とするノートブックの冒頭に、$ Preを使用するすべての機能がありません(トレースはそれを使用しませんか?)。

直感的には、ボックス解析のレベルでこの機能を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]]
于 2011-12-12T19:09:12.660 に答える
0

この回答はあなたの質問に対処するものではなく、むしろその質問をするように導く問題に対処します. Mathematica は移動しないオブジェクトを扱う場合にはほとんど役に立ちませんが、そのようなオブジェクトは素粒子物理学などに豊富にあるため、この状況に対処するための便利なパッケージがいくつかあります。

grassmanOpsパッケージを見てください。これらには、交換シンボルまたは非交換シンボルとしてシンボルを定義し、標準の NonCommutativeMultiply をオーバーロードして交換シンボルを処理する、つまりパススルーするメソッドがあります。また、Derivative などの他のいくつかの演算子を定義して、アンチコミューティング シンボルを処理します。おそらく、任意の交換規則をカバーするように簡単に適応させることができます。また、独自のものを展開したい場合は、少なくとも何を変更する必要があるかについてのヒントが得られるはずです。

于 2011-12-03T20:48:33.307 に答える