问题
With the help of some very gracious stackoverflow contributors in this post, I have the following new definition for NonCommutativeMultiply (**)
in Mathematica:
Unprotect[NonCommutativeMultiply];
ClearAll[NonCommutativeMultiply]
NonCommutativeMultiply[] := 1
NonCommutativeMultiply[___, 0, ___] := 0
NonCommutativeMultiply[a___, 1, b___] := a ** b
NonCommutativeMultiply[a___, i_Integer, b___] := i*a ** b
NonCommutativeMultiply[a_] := a
c___ ** Subscript[a_, i_] ** Subscript[b_, j_] ** d___ /; i > j :=
c ** Subscript[b, j] ** Subscript[a, i] ** d
SetAttributes[NonCommutativeMultiply, {OneIdentity, Flat}]
Protect[NonCommutativeMultiply];
This multiplication is great, however, it does not deal with negative values at the beginning of an expression, i.e.,a**b**c + (-q)**c**a
should simplify toa**b**c - q**c**a
and it will not.
In my multiplication, the variable q
(and any integer scaler) is commutative; I am still trying to write a SetCommutative
function, without success. I am not in desperate need of SetCommutative
, it would just be nice.
It would also be helpful if I were able to pull all of the q's
to the beginning of each expression, i.e.,:a**b**c + a**b**q**c**a
should simplify to:a**b**c + q**a**b**c**a
and similarly, combining these two issues:a**b**c + a**c**(-q)**b
should simplify to:a**b**c - q**a**c**b
At the current time, I would like to figure out how to deal with these negative variables at the beginning of an expression and how to pull the q's
and (-q)'s
to the front as above. I have tried to deal with the two issues mentioned here using ReplaceRepeated (\\.)
, but so far I have had no success.
All ideas are welcome, thanks...
回答1:
The key to doing this is to realize that Mathematica represents a-b
as a+((-1)*b)
, as you can see from
In[1]= FullForm[a-b]
Out[2]= Plus[a,Times[-1,b]]
For the first part of your question, all you have to do is add this rule:
NonCommutativeMultiply[Times[-1, a_], b__] := - a ** b
or you can even catch the sign from any position:
NonCommutativeMultiply[a___, Times[-1, b_], c___] := - a ** b ** c
Update -- part 2. The general problem with getting scalars to front is that the pattern _Integer
in your current rule will only spot things that are manifestly integers. It wont even spot that q
is an integer in a construction like Assuming[{Element[q, Integers]}, a**q**b]
.
To achieve this, you need to examine assumptions, a process that is probably to expensive to be put in the global transformation table. Instead I would write a transformation function that I could apply manually (and maybe remove the current rule form the global table). Something like this might work:
NCMScalarReduce[e_] := e //. {
NonCommutativeMultiply[a___, i_ /; Simplify@Element[i, Reals],b___]
:> i a ** b
}
The rule used above uses Simplify
to explicitly query assumptions, which you can set globally by assigning to $Assumptions
or locally by using Assuming
:
Assuming[{q \[Element] Reals},
NCMScalarReduce[c ** (-q) ** c]]
returns -q c**c
.
HTH
回答2:
Just a quick answer that repeats some of the comments from the previous question.
You can remove a couple of the definitions and solve all of the parts of this question using the rule that acts on Times[i,c]
where i
is commutative and c
has the default of Sequence[]
Unprotect[NonCommutativeMultiply];
ClearAll[NonCommutativeMultiply]
NonCommutativeMultiply[] := 1
NonCommutativeMultiply[a___, (i:(_Integer|q))(c_:Sequence[]), b___] := i a**Switch[c, 1, Unevaluated[Sequence[]], _, c]**b
NonCommutativeMultiply[a_] := a
c___**Subscript[a_, i_]**Subscript[b_, j_] ** d___ /; i > j := c**Subscript[b, j]**Subscript[a, i]**d
SetAttributes[NonCommutativeMultiply, {OneIdentity, Flat}]
Protect[NonCommutativeMultiply];
This then works as expected
In[]:= a**b**q**(-c)**3**(2 a)**q
Out[]= -6 q^2 a**b**c**a
Note that you can generalize (_Integer|q)
to work on more general commutative objects.
来源:https://stackoverflow.com/questions/5038338/noncommutative-multiplication-and-negative-coeffcients-at-the-beginning-of-an-ex