Skip to main content
replaced http://mathematica.stackexchange.com/ with https://mathematica.stackexchange.com/
Source Link

For this problem, I wouldn't use a rule-based approach to realize the algebraic relations. Instead, if you don't want to load the Quaternions package, the most robust way to implement quaternions is using their matrix basis representation, see e.g. this Mathworld post.

Essentially, the basis vectors can be represented as multiples of the Pauli matrices, so I just modified my recent answer on the Pauli algebramy recent answer on the Pauli algebra to make it work in this case:

For simplicity, I use the symbols K[0] for 1, K[1] for i, K[2] for j and K[3] instead of k because the programming is easier when using indices for the four components. Here is a function that takes a quaternion expression in the component notation and simplifies it using the matrix representation. The multiplication between quaternion components is always required to be written as a Dot product because the underlying non-commutative algebra is realized with matrices:

Clear[quaternionReduce]
quaternionReduce[a_] := Module[{
   x,
   symbolicQIndices,
   expression,
   component = ({1, I, I, I} PauliMatrix[{0, 3, 2, 1}])
   },
  x = Array[\[FormalX], 4];
  symbolicQIndices = 
   DeleteDuplicates[Cases[a, K[i_Symbol] :> i, Infinity]];
  expression = 
   Array[K, 4, 
     0].(x /. 
      First[Solve[
        x.component == a /. 
         K[i_] :> 
          Sum[KroneckerDelta[i, k] component[[k + 1]], {k, 0, 3}], 
        x]]);
  FullSimplify[expression, 
   Assumptions -> 
    Map[# \[Element] Integers && 1 <= # <= 3 &, symbolicQIndices]]]

Here are some examples for doing algebra with this function:

quaternionReduce[K[1].K[2]]

(* ==> K[3] *)

quaternionReduce[K[2].K[1]]

(* ==> -K[3] *)

quaternionReduce[K[1].K[2].K[3]]

(* ==> -K[0] *)

quaternionReduce[MatrixPower[K[1], 3]]

(* ==> -K[1] *)

quaternionReduce[MatrixPower[(K[0] + K[1]), 2]]

(* ==> 2 K[1] *)

The K[0] above is the real unit 1, as mentioned above. In principle you could make the input and output fancier (i.e., more traditional symbols), but I wanted to keep the programming effort small.

The last two relations address the problem that led to the hang-up in your question. Here, powers are realized using MatrixPower and everything works as expected.

For this problem, I wouldn't use a rule-based approach to realize the algebraic relations. Instead, if you don't want to load the Quaternions package, the most robust way to implement quaternions is using their matrix basis representation, see e.g. this Mathworld post.

Essentially, the basis vectors can be represented as multiples of the Pauli matrices, so I just modified my recent answer on the Pauli algebra to make it work in this case:

For simplicity, I use the symbols K[0] for 1, K[1] for i, K[2] for j and K[3] instead of k because the programming is easier when using indices for the four components. Here is a function that takes a quaternion expression in the component notation and simplifies it using the matrix representation. The multiplication between quaternion components is always required to be written as a Dot product because the underlying non-commutative algebra is realized with matrices:

Clear[quaternionReduce]
quaternionReduce[a_] := Module[{
   x,
   symbolicQIndices,
   expression,
   component = ({1, I, I, I} PauliMatrix[{0, 3, 2, 1}])
   },
  x = Array[\[FormalX], 4];
  symbolicQIndices = 
   DeleteDuplicates[Cases[a, K[i_Symbol] :> i, Infinity]];
  expression = 
   Array[K, 4, 
     0].(x /. 
      First[Solve[
        x.component == a /. 
         K[i_] :> 
          Sum[KroneckerDelta[i, k] component[[k + 1]], {k, 0, 3}], 
        x]]);
  FullSimplify[expression, 
   Assumptions -> 
    Map[# \[Element] Integers && 1 <= # <= 3 &, symbolicQIndices]]]

Here are some examples for doing algebra with this function:

quaternionReduce[K[1].K[2]]

(* ==> K[3] *)

quaternionReduce[K[2].K[1]]

(* ==> -K[3] *)

quaternionReduce[K[1].K[2].K[3]]

(* ==> -K[0] *)

quaternionReduce[MatrixPower[K[1], 3]]

(* ==> -K[1] *)

quaternionReduce[MatrixPower[(K[0] + K[1]), 2]]

(* ==> 2 K[1] *)

The K[0] above is the real unit 1, as mentioned above. In principle you could make the input and output fancier (i.e., more traditional symbols), but I wanted to keep the programming effort small.

The last two relations address the problem that led to the hang-up in your question. Here, powers are realized using MatrixPower and everything works as expected.

For this problem, I wouldn't use a rule-based approach to realize the algebraic relations. Instead, if you don't want to load the Quaternions package, the most robust way to implement quaternions is using their matrix basis representation, see e.g. this Mathworld post.

Essentially, the basis vectors can be represented as multiples of the Pauli matrices, so I just modified my recent answer on the Pauli algebra to make it work in this case:

For simplicity, I use the symbols K[0] for 1, K[1] for i, K[2] for j and K[3] instead of k because the programming is easier when using indices for the four components. Here is a function that takes a quaternion expression in the component notation and simplifies it using the matrix representation. The multiplication between quaternion components is always required to be written as a Dot product because the underlying non-commutative algebra is realized with matrices:

Clear[quaternionReduce]
quaternionReduce[a_] := Module[{
   x,
   symbolicQIndices,
   expression,
   component = ({1, I, I, I} PauliMatrix[{0, 3, 2, 1}])
   },
  x = Array[\[FormalX], 4];
  symbolicQIndices = 
   DeleteDuplicates[Cases[a, K[i_Symbol] :> i, Infinity]];
  expression = 
   Array[K, 4, 
     0].(x /. 
      First[Solve[
        x.component == a /. 
         K[i_] :> 
          Sum[KroneckerDelta[i, k] component[[k + 1]], {k, 0, 3}], 
        x]]);
  FullSimplify[expression, 
   Assumptions -> 
    Map[# \[Element] Integers && 1 <= # <= 3 &, symbolicQIndices]]]

Here are some examples for doing algebra with this function:

quaternionReduce[K[1].K[2]]

(* ==> K[3] *)

quaternionReduce[K[2].K[1]]

(* ==> -K[3] *)

quaternionReduce[K[1].K[2].K[3]]

(* ==> -K[0] *)

quaternionReduce[MatrixPower[K[1], 3]]

(* ==> -K[1] *)

quaternionReduce[MatrixPower[(K[0] + K[1]), 2]]

(* ==> 2 K[1] *)

The K[0] above is the real unit 1, as mentioned above. In principle you could make the input and output fancier (i.e., more traditional symbols), but I wanted to keep the programming effort small.

The last two relations address the problem that led to the hang-up in your question. Here, powers are realized using MatrixPower and everything works as expected.

Source Link
Jens
  • 97.9k
  • 7
  • 215
  • 510

For this problem, I wouldn't use a rule-based approach to realize the algebraic relations. Instead, if you don't want to load the Quaternions package, the most robust way to implement quaternions is using their matrix basis representation, see e.g. this Mathworld post.

Essentially, the basis vectors can be represented as multiples of the Pauli matrices, so I just modified my recent answer on the Pauli algebra to make it work in this case:

For simplicity, I use the symbols K[0] for 1, K[1] for i, K[2] for j and K[3] instead of k because the programming is easier when using indices for the four components. Here is a function that takes a quaternion expression in the component notation and simplifies it using the matrix representation. The multiplication between quaternion components is always required to be written as a Dot product because the underlying non-commutative algebra is realized with matrices:

Clear[quaternionReduce]
quaternionReduce[a_] := Module[{
   x,
   symbolicQIndices,
   expression,
   component = ({1, I, I, I} PauliMatrix[{0, 3, 2, 1}])
   },
  x = Array[\[FormalX], 4];
  symbolicQIndices = 
   DeleteDuplicates[Cases[a, K[i_Symbol] :> i, Infinity]];
  expression = 
   Array[K, 4, 
     0].(x /. 
      First[Solve[
        x.component == a /. 
         K[i_] :> 
          Sum[KroneckerDelta[i, k] component[[k + 1]], {k, 0, 3}], 
        x]]);
  FullSimplify[expression, 
   Assumptions -> 
    Map[# \[Element] Integers && 1 <= # <= 3 &, symbolicQIndices]]]

Here are some examples for doing algebra with this function:

quaternionReduce[K[1].K[2]]

(* ==> K[3] *)

quaternionReduce[K[2].K[1]]

(* ==> -K[3] *)

quaternionReduce[K[1].K[2].K[3]]

(* ==> -K[0] *)

quaternionReduce[MatrixPower[K[1], 3]]

(* ==> -K[1] *)

quaternionReduce[MatrixPower[(K[0] + K[1]), 2]]

(* ==> 2 K[1] *)

The K[0] above is the real unit 1, as mentioned above. In principle you could make the input and output fancier (i.e., more traditional symbols), but I wanted to keep the programming effort small.

The last two relations address the problem that led to the hang-up in your question. Here, powers are realized using MatrixPower and everything works as expected.