NonCommutativeMultiply¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
a ** b ** c or NonCommutativeMultiply[a, b, c] is a general associative, but non-commutative, form of multiplication. Instances are automatically flattened (it has attribute Flat), but no other simplification is performed: a**b is not reordered to b**a, 0**a and 1**a stay as given, and Expand / Simplify do not operate on it. Use it as a generalization of ordinary multiplication for special mathematical objects (e.g. composition in an algebra of differential operators).
Examples (14)¶
Every input below was run against the current Mathilda build and its output recorded.
Basic examples (4)¶
In[1]:= a ** b ** c
Out[1]= a ** b ** c
In[2]:= a ** (b ** c) == (a ** b) ** c
Out[2]= True
In[3]:= {a*b == b*a, a**b == b**a}
Out[3]= {True, a ** b == b ** a}
In[4]:= {0 ** a, 1 ** a}
Out[4]= {0 ** a, 1 ** a}
Applications (10)¶
Associative: nested products are flattened
Into one flat call
Not commutative
No other simplification: zeros, ones, numbers and a single argument are all kept
In[8]:= {0 ** a, 1 ** a, 2 ** 3, NonCommutativeMultiply[a]}
Out[8]= {0 ** a, 1 ** a, 2 ** 3, NonCommutativeMultiply[a]}
Binds tighter than Times and looser than Power
A rule for two operands rewrites a leading pair inside a longer product
The product is Protected, so new rules go on the operands as UpValues; this one folds the whole product
The leading pair is merged and x is kept
Limitation: a matching pair that is not at the start is not rewritten
Replace the head to get an ordinary product
Implementation notes¶
Semantics. NonCommutativeMultiply is a purely structural head with no C builtin. Its behaviour comes from its attributes, Flat, OneIdentity and Protected, set in the static table in src/attr.c. Flat makes the evaluator splice nested ** calls into one flat call. No other rewriting is done: arguments are not reordered (it is not Orderless), numbers are not combined, and identities such as 0 ** a or 1 ** a are not applied. A one-argument NonCommutativeMultiply[a] stays as it is, because OneIdentity only affects pattern matching.
Parsing and printing. src/parse.c lexes ** as OP_NONCOMMULT at precedence 5900. That is tighter than . (Dot) and * (Times) and looser than ^, so a b ** c^2 is Times[a, NonCommutativeMultiply[b, Power[c, 2]]]. Runs of ** are flattened when the expression is parsed. print_standard prints two or more arguments as infix a ** b ** c, and other arities in FullForm style.
Rules and limits. Since the head is Flat, match_flat_leftover (src/match.c) lets a rule written for two operands rewrite part of a longer product and keep the rest. The head is not Orderless, so the matched operands must form a leading run (op[1] ** op[2] ** x is rewritten, x ** op[1] ** op[2] is not). Its Protected bit comes from the static attribute table, which Unprotect does not override, so new behaviour is attached through UpValues on the operands (op /: op[i_] ** op[j_] := ...) rather than DownValues on **. It has no packed-array, NDArray or Compile[] path; ** is symbolic only.
- Attributes
Flat,OneIdentity,Protected. - Instances are automatically flattened (
a ** (b ** c)and(a ** b) ** cboth becomeNonCommutativeMultiply[a, b, c]), but no other simplification is performed: arguments are not reordered (a ** bstays distinct fromb ** a),0 ** aand1 ** aare left as given, andExpand/Simplify/FullSimplifydo not operate on expressions containing it. NonCommutativeMultiply[a](one argument) stays unevaluated ā unlikeTimes[a], which reduces toa.- Precedence binds tighter than
*(Times) and.(Dot), and looser than^(Power):a ** b ^ cisa ** (b^c),a b ** cisa (b ** c). - No new numeric fast path:
**is a purely symbolic/structural head, so it has no packed/NDArray orCompile[]lowering.
Attributes: Flat, OneIdentity, Protected.
References¶
See also: Flat, OneIdentity, Expand, Simplify, Times, Dot, Power
- Source:
src/parse.c - Specification:
docs/spec/builtins/arithmetic.md - Tests:
tests/test_noncommutativemultiply.c
Notes & additional examples¶
Notes¶
- A general associative, non-commutative product with no built-in rules. Attributes
{Flat, OneIdentity, Protected}: only flattening happens automatically, andNonCommutativeMultiply[a]is not reduced toa(unlikeTimes[a]). Expand,SimplifyandDdo not distribute over it.Expand[(a + b) ** c]is unchanged. Write the algebra's rules (linearity, commutation relations) yourself.- Differences from Mathematica:
Unprotect[NonCommutativeMultiply]has no effect, because the Protected bit comes from the static attribute table, so DownValues on**are refused withSetDelayed::wrsym. Attach rules to the operands with/:or^:=instead. Also, because the head is notOrderless, a rule matches only a leading run of operands, so an interior pair is not rewritten. - Precedence:
^>**>.>*. Soa ** b^cisa ** (b^c)anda b ** cisa (b ** c). - It is symbolic only, with no packed-array, NDArray or
Compile[]path. - See also:
Times,Dot,Flat,OneIdentity,TagSetDelayed.