2011-02-17 12 views
7

NonCommutativeMultiply (**) no simplifica términos comoRedefinir no conmutativa multiplicación en Mathematica Mathematica

a**0=0**a=0 
a**1=1**a=a 

o

a**a=a^2. 

me gustaría redefinir ** para hacer esto. Estaba usando NCAlgebra para hacer esto, pero necesito ReplaceRepeated (//.) Y NCAlgebra, como dice su documentación, rompe específicamente esta funcionalidad en mathematica.

¿Puede alguien mostrarme cómo borrar los atributos de ** y redefinir esta multiplicación hacer las mismas cosas que haría normal más más tratar con 1 y 0. Realmente no necesito la multiplicación para tratar con a**a, pero sería agradable si es lo suficientemente simple. Lo principal que necesito ** tratar con 1 y 0.

+0

tenga en cuenta que "\ *" se utiliza como un [metacarácter de marcado] (http://stackoverflow.com/editing-help) en SO. Puede tener un literal "\ *" escapándolo con una barra diagonal inversa ("\") o (si corresponde) marcando el texto como código con un backtick ("\" ") para el código en línea o sangría líneas con cuatro espacios. Si hace clic en el enlace "editar" para su pregunta, puede examinar el origen de la pregunta para ver cómo se hace. Puede leer más sobre el lenguaje de marcado (llamado Markdown) haciendo clic en el signo de interrogación naranja en la barra de herramientas del editor. – outis

Respuesta

6

la continuación sólo funciona si se quita el atributo plana de NonCommutativeMultiply (Lo cual es algo que hice por error durante la prueba ... un error de novato!)

lo más sencillo que hacer es

Unprotect[NonCommutativeMultiply]; 
NonCommutativeMultiply[a___, 1, b___] := a ** b 
NonCommutativeMultiply[___, 0, ___] := 0 
NonCommutativeMultiply[a_] := a 
Protect[NonCommutativeMultiply]; 

se necesita la expresión final de manera que se simplifica a a**1a en lugar de NonCommutativeMultiply[a]. Es posible que también necesite NonCommutativeMultiply[]:=1 para que las expresiones como 1**1 se simplifiquen correctamente (*). El único problema con todo esto, es para expresiones grandes, el patrón se compara con todo y esto se vuelve realmente lento.

Las dos definiciones anteriores para 0 y 1 se pueden combinar y generalizarse a

NonCommutativeMultiply[a___, n_?NumericQ, b___] := n a ** b 

qué factores a cabo cualquiera de los términos numéricos dentro de la expresión. Pero esto ralentiza las cosas aún más en expresiones grandes, ya que cada término se verifica para ver si es numérico.

para simplificar su a**a-a^2, necesita algo así como

NonCommutativeMultiply[a___, b_, b_, c___] := a ** b^2 ** c 

o más generalmente

NonCommutativeMultiply[a___, b_^n_., b_^m_., c___] := a ** b^(n + m) ** c 

(*) Tenga en cuenta que esto es sólo porque el orden predeterminado que pone de Mathematica su DownValues no es necesariamente el mejor en este caso. Cambie el orden para que NonCommutativeMultiply[a_] venga antes que a___ ** n_?NumericQ ** b___, luego NonCommutativeMultiply[] no será generado por las reglas, y no necesitará ese último patrón (a menos que produzca NonCommutativeMultiply[] de otra manera).

+0

Dicho sea de paso: mi papel y mi cuaderno están ahora [en el arXiv] (http://arxiv.org/abs/1102.3043). Como tenía expresiones muy grandes, verás que tuve que tomar decisiones difíciles sobre cómo simplificar las expresiones 'NonCommutativeMultiply'. Incluso entonces, tuve que tomar la mano de mma para algunos cálculos, de lo contrario nunca terminarían. – Simon

+0

@Simon, la optimización es definitivamente una preocupación para mí también. Me pregunto, si todo lo que necesito hacer es agregar 0 y 1 a **, cuánto más lento será. Gracias por toda su ayuda, revisaré el periódico ahora. También probaré este código e informaré sobre cualquier problema. – Cantormath

+0

@Simon, probé la definición que tienes arriba y devuelve "$ IterationLimit :: itlim: límite de iteración de 4096 excedido. >>" y la salida es Hold [1 ** 1 ** 1 ** .... * * 1 ** 1]. – Cantormath

1

OK, escribir reglas que jueguen bien con los atributos de NonCommutativeMultiply es a veces una molestia. Aquí hay un método alternativo que presenta un helper NCM que no tiene las reglas y atributos de NonCommutativeMultiply asociados.

El siguiente código también incorpora las últimas dos preguntas. (1)(2)

Unprotect[NonCommutativeMultiply]; 
Clear[NonCommutativeMultiply] 
(* Factor out numerics -- could generalize to some ScalarQ *) 
nc:NonCommutativeMultiply[a__]/;MemberQ[{a},_?NumericQ]:=NCMFactorNumericQ[NCM[a]]/.NCM->NonCommutativeMultiply 
(* Simplify Powers *) 
b___**a_^n_.**a_^m_.**c___:=NCM[b,a^(n+m),c]/.NCM->NonCommutativeMultiply 
(* Expand Brackets *) 
nc:NonCommutativeMultiply[a___,b_Plus,c___]:=Distribute[NCM[a,b,c]]/.NCM->NonCommutativeMultiply 
(* Sort Subscripts *) 
c___**Subscript[a_, i_]**Subscript[b_, j_]**d___/;i>j:=c**Subscript[b, j]**Subscript[a, i]**d 
Protect[NonCommutativeMultiply]; 

Unprotect[NCM]; 
Clear[NCM] 
NCMFactorNumericQ[nc_NCM]:=With[{pos=Position[nc,_?NumericQ,1]},[email protected]@Extract[nc,pos] Delete[nc,pos]] 
NCM[a_]:=a 
NCM[]:=1 
Protect[NCM]; 

Tenga en cuenta que NCMFactorNumericQ es rápido, ya que funciona en una sola pasada, pero la regla asociada a ella nc:NonCommutativeMultiply[a__]/;MemberQ[{a},_?NumericQ] es lento, porque el atributo plana significa que lo hace un número estúpida de cheques con NumericQ. Si realmente desea más velocidad y expresiones grandes, debe aplicar manualmente las rutinas Sort y Factor, de modo que Mathematica realice menos comprobaciones de patrones.

+0

@Simon, así que creo que tengo una definición de multiplicación que me gusta. No usé (* Simplify Powers *) y (* Expandir corchetes *), los aplicaré más adelante. Algo de lo que me he dado cuenta (* Simplify Powers *), si dices multiplicar expresiones idénticas que son la suma de muchos términos juntos usando **, cuadra (^ 2) la expresión en lugar de multiplicarla con la multiplicación no conmutativa. De nuevo, esto no es un problema ya que no lo estoy usando. Un problema con el que me estoy cruzando es con las variables negativas al comienzo de una expresión. Obtengo 'c + (- q) ** a' en lugar de' c-q ** a'. – Cantormath

+0

@Simon, entonces creo que tengo una definición de multiplicación que me gusta. No utilicé '(Simplify Powers)' y '(Expandir corchetes)', los aplicaré más tarde. Algo que noto sobre '(Simplify Powers)', si dices multiplicar expresiones idénticas que son la suma de muchos términos juntos usando '**', cuadra '(^ 2)' la expresión en lugar de multiplicarla con '** '. De nuevo, esto no es un problema ya que no lo estoy usando. Un problema con el que me estoy cruzando es con las variables negativas al comienzo de una expresión. Obtengo 'b ** c + (- q) ** a' en lugar de decir' b ** c-q ** a'. – Cantormath

+0

@Cantormath: El problema de alimentación proviene del atributo 'Flat' de' ** '. No usé esa regla en mi trabajo, y no estoy seguro de cómo evitarlo. Tal vez solo aplique manualmente ese tipo de simplificación al final de la evaluación. – Simon

1

El truco con

Unprotect[NonCommutativeMultiply]; 
.... 
Protect[NonCommutativeMultiply]; 

es muy bueno! Pasé 10 horas tratando de resolver un problema con NonCommutativeMultiply (cómo aplanar expresiones que incluían tanto n.c. y la multiplicación normal como a**b**(c*d*(e**f)) pero más complicado), pero no pensé en modificar NonCommutativeMultiply sí mismo. ¡Gracias!