Нижеследующее работает только в том случае, если вы удалите атрибут Flat из NonCommulativeMultiply
(Что я и сделал по ошибке во время тестирования ... ошибка новичка!)
Самое простое, что нужно сделать, это
Unprotect[NonCommutativeMultiply];
NonCommutativeMultiply[a___, 1, b___] := a ** b
NonCommutativeMultiply[___, 0, ___] := 0
NonCommutativeMultiply[a_] := a
Protect[NonCommutativeMultiply];
Требуется окончательное выражение, чтобы a**1
упрощалось до a
вместо NonCommutativeMultiply[a]
. Вам также может понадобиться NonCommutativeMultiply[]:=1
, чтобы такие выражения, как 1**1
, упростились должным образом (*).
Единственная проблема со всем этим, для больших выражений, шаблон проверяется на все, и это становится очень медленным.
Приведенные выше два определения для 0 и 1 можно объединить и обобщить до
NonCommutativeMultiply[a___, n_?NumericQ, b___] := n a ** b
, который исключает любые числовые термины внутри выражения.
Но это еще больше замедляет работу в больших выражениях, поскольку каждый член проверяется на предмет числовости.
Чтобы упростить a**a
до a^2
, вам нужно что-то вроде
NonCommutativeMultiply[a___, b_, b_, c___] := a ** b^2 ** c
или более обычно
NonCommutativeMultiply[a___, b_^n_., b_^m_., c___] := a ** b^(n + m) ** c
(*) Обратите внимание, что это только потому, что порядок по умолчанию, в который Mathematica помещает DownValues
, не обязательно является лучшим в этом случае. Измените порядок так, чтобы NonCommutativeMultiply[a_]
предшествовал a___ ** n_?NumericQ ** b___
, тогда правила NonCommutativeMultiply[]
не были сгенерированы правилами, и вам не понадобится этот последний шаблон (если вы не создадите NonCommutativeMultiply[]
другим способом).