Function Repository Resource:

MagnusTerms

Source Notebook

Generate terms in the Magnus expansion of a time-dependent operator

Contributed by: Mohammad Bahrami

ResourceFunction["MagnusTerms"][op,n,alg]

generates the order-n term in the Magnus expansion of the operator op, for the algebraic operation alg, which can be Dot,Composition,TensorProduct or NonCommutativeMultiply.

ResourceFunction["MagnusTerms"][op,n]

generates the order-n term in the Magnus expansion of the operator op, where NonCommutativeAlgebra with the default property values is used.

ResourceFunction["MagnusTerms"][op,n,alg,f]

generates the order-n term in the Magnus expansion of the operator op, for the algebraic operation alg, after reduction of each commutator using f where f is a NonCommutativePolynomialReduce function.

ResourceFunction["MagnusTerms"][op,n,f]

generates the order-n term in the Magnus expansion of the operator op after reduction of each commutator using f where f is a NonCommutativePolynomialReduce function and NonCommutativeAlgebra with the default property values is used to determine the algebraic operation.

Details and Options

MagnusTerms returns the term Ωn(t) in the Magnus expansion, or Magnus series, for the solution of matrix linear initial-value problem with Y(0)=I, where in general [A(t1),A(t2)]0. The exact solution can be written as Y(t)=eΩ(t).
The Magnus expansion expresses Ω(t) as an infinite series of time-ordered integrals of nested commutators: Ω(t)=∑n=1∞Ωn(t), where Ωn(t) is homogeneous of order-n in A. It contains n time integrals and n−1 commutators. For the case of quantum unitary evolution, i.e. , one needs to replace A(t) with -ⅈ H(t).
An efficient closed form (right-nested, independent commutators) for Ωn is given as follows: with where 𝒢n-1 is permutations of {1,2,,n-1}, and d(σ) is the number of descents of σ (indices i with σ(i)>σ(i+1)), and cn=(-1)d(σ)/().
Given n, ResourceFunction["MagnusTerms"] automatically assigns time variables for the time-dependent operator.
MagnusTerms take the following options:
"CommutatorForm"Falsewhether to hold the commutator form
"TimeIntegration"Falsewhether to return the time-integrated result
If the algebra argument is omitted, NonCommutativeAlgebra with the default property values is used.
ResourceFunction["MagnusTerms"] requires version 14.3 or higher of the Wolfram Language.

Examples

Basic Examples (4) 

Generate Ω1,com(t) which will be A(t):

In[1]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 1]
Out[1]=

Generate Ω1(t):

In[2]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 1, "TimeIntegration" -> True]
Out[2]=

Generate Ω2,com(t):

In[3]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2]
Out[3]=

Generate Ω2,com(t) while holding the commutation form:

In[4]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2, "CommutatorForm" -> True] // TraditionalForm
Out[4]=

Check whether it is the same as :

In[5]:=
ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2] - 1/2 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], \[FormalCapitalA][Subscript[\[FormalT], 2]]] // NonCommutativeExpand
Out[5]=

Do the commutation operation:

In[6]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2]
Out[6]=

Do the commutation operation for Dot as the operation:

In[7]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2, Dot]
Out[7]=

Do the commutation operation for Composition as the operation:

In[8]:=
ResourceFunction[
 "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2, Composition]
Out[8]=

Generate Ω2(t):

In[9]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 2, "TimeIntegration" -> True, "CommutatorForm" -> True] // TraditionalForm
Out[9]=

Scope (5) 

Generate Ω3,com(t):

In[10]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 3, "CommutatorForm" -> True] // TraditionalForm
Out[10]=

Check it is the same as :

In[11]:=
ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 3] - (1/3 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], \[FormalCapitalA][Subscript[\[FormalT], 3]]]] - 1/6 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], \[FormalCapitalA][Subscript[\[FormalT], 3]]]]) // NonCommutativeExpand
Out[11]=

Generate Ω3(t):

In[12]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 3, "TimeIntegration" -> True, "CommutatorForm" -> True] // TraditionalForm
Out[12]=

Generate Ω4,com(t):

In[13]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 4, "CommutatorForm" -> True] // TraditionalForm
Out[13]=

Check it is the same as which will be :

In[14]:=
ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 4] - (1/4 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]] - 1/12 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]] - 1/12 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]] - 1/12 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]] - 1/12 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]] + 1/12 Commutator[\[FormalCapitalA][Subscript[\[FormalT], 3]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 2]], Commutator[\[FormalCapitalA][Subscript[\[FormalT], 1]], \[FormalCapitalA][Subscript[\[FormalT], 4]]]]]) // NonCommutativeExpand
Out[14]=

Generate Ω4(t):

In[15]:=
ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][\[FormalCapitalA], 4, "TimeIntegration" -> True, "CommutatorForm" -> True] // TraditionalForm
Out[15]=

Generate Ω5,com(t) and check it is the same as which will be :

In[16]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/a89e31eb-03f4-4711-9296-91b19a42d00c"]
Out[16]=

Applications (27) 

H(t)=f(t)(eⅈ ta+e-ⅈ ta)

Define a time-dependent Hamiltonian as H(t)=f(t)(eⅈ ta+e-ⅈ ta) with[a,a]=1 where a (a) is the annihilation (creation) operator:

In[17]:=
ClearAll[h1, f]
h1[t_] := f[t] (\[FormalA] Exp[I t] + SuperDagger[\[FormalA]] Exp[-I t])

The Hamiltonian above is expressed in the interaction picture; see Sec. 4.1.1 of the preprint (arXiv:0810.5488) for details. To avoid any conflict, we shall use formal symbol of t for the time.

Define the variables within the non-commutative algebra together with their corresponding commutation relations:

In[18]:=
ClearAll[vars1, rel1]
vars1 = {\[FormalA], SuperDagger[\[FormalA]]};
rel1 = {Commutator[\[FormalA], SuperDagger[\[FormalA]]] - 1};

Since in the Magnus series, there are many time-dependent terms that are only scalar variables, define corresponding non-commutative algebra and Gröbner basis for given n (where we needs to specify what are scalar variables for a given n):

In[19]:=
ClearAll[alg1, gb1]
alg1[n_] := NonCommutativeAlgebra[<|
    "ScalarVariables" -> Flatten[{#, f[#]} & /@ Table[Subscript[\[FormalT], i], {i, n}]]|>];
gb1[n_] := NonCommutativeGroebnerBasis[rel1, vars1, alg1[n]]

For scalar variables in above definitions, we use the same format as in the Magnus series defined in the previous section.

A function that simplifies and reduces the non-commutative polynomial of the annihilation and creation operators:

In[20]:=
ClearAll[reduceF1]
reduceF1[exp_, n_] := NonCommutativePolynomialReduce[exp, gb1[n], vars1, alg1[n]][[-1]]

We use Nest with ReleaseHold since the Magnus terms defined in the previous section are expressed in the hold commutator form.

As noted earlier, we chose a Hamiltonian that does not commute at different times. Show the Hamiltonian at different times do not commute:

In[21]:=
reduceF1[
  Commutator[h1[Subscript[\[FormalT], 1]], h1[Subscript[\[FormalT], 2]]], 2] // FullSimplify
Out[21]=

Show[H(t1),[H(t2),H(t3)]]=0:

In[22]:=
reduceF1[
 Commutator[h1[Subscript[\[FormalT], 1]], Commutator[h1[Subscript[\[FormalT], 2]], h1[Subscript[\[FormalT], 3]]]], 3]
Out[22]=

Find commutation term [H(t1),H(t2)] in the second term of Magnus expansion :

In[23]:=
With[{n = 2}, ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h1, n, reduceF1[#, n] &]] // FullSimplify
Out[23]=

Find commutation term, [H(t1),[H(t2),H(t3)]], in the third term of Magnus expansion :

In[24]:=
With[{n = 3}, ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h1, n, reduceF1[#, n] &]]
Out[24]=

It is interesting that the third them and so on are all zero. Therefore, only first and 2nd terms contribute to the exponential: which can be rewritten as U(t)=Exp[-ⅈ (α a+α*a)-β] with and :

In[25]:=
Table[ResourceFunction[
  "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h1, n, reduceF1[#, n] &], {n, 3, 8}]
Out[25]=

H(t)=f1(t) σ1+f2(t) σ2+f3(t) σ3

Define a time-dependent Hamiltonian as H(t)=f1(t) σ1+f2(t) σ2+f3(t) σ3 with σ1 the Pauli-X, σ2 the Pauli-Y, and σ3 the Pauli-Z:

In[26]:=
ClearAll[h2, f, \[Sigma]]
h2[t_] := Subscript[f, 1][t] Subscript[\[Sigma], 1] + Subscript[f, 2][t] Subscript[\[Sigma], 2] + Subscript[f, 3][t] Subscript[\[Sigma], 3]

Define the variables within the non-commutative algebra together with their corresponding commutation relations:

In[27]:=
ClearAll[vars2, rel2]
vars2 = Table[Subscript[\[Sigma], j], {j, 3}];
rel2 = Table[
   Subscript[\[Sigma], i] ** Subscript[\[Sigma], j] - KroneckerDelta[i, j] - I Sum[LeviCivitaTensor[3][[i, j, k]] Subscript[\[Sigma], k], {k, 3}], {i, 3}, {j, 3}] // Flatten
Out[7]=

Since in the Magnus series, there are many time-dependent terms that are only scalar variables, define corresponding non-commutative algebra and Gröbner basis for given n (where we needs to specify what are scalar variables for a given n):

In[28]:=
ClearAll[alg2, gb2]
alg2[n_] := NonCommutativeAlgebra[<|
    "ScalarVariables" -> Join[Flatten[
       Table[Subscript[f, j][Subscript[\[FormalT], i]], {j, 3}, {i, n}]],
       Table[Subscript[\[FormalT], i], {i, n}]]|>];
gb2[n_] := NonCommutativeGroebnerBasis[rel2, vars2, alg2[n]]

A function that simplifies and reduces the non-commutative polynomial of Pauli matrices:

In[29]:=
ClearAll[reduceF2]
reduceF2[exp_, n_] := NonCommutativePolynomialReduce[
   NonCommutativePolynomialReduce[exp, gb2[n], vars2, alg2[n]][[-1]], gb2[n], Reverse@vars2, alg2[n]][[-1]]

As noted earlier, we chose a Hamiltonian that does not commute at different times. Show the Hamiltonian at different times do not commute:

In[30]:=
reduceF2[
  Commutator[h2[Subscript[\[FormalT], 1]], h2[Subscript[\[FormalT], 2]]], 2] // FullSimplify
Out[30]=

In above code, we have applied NonCommutativePolynomialReduce two times to take care of all reductions (note the difference in the order of variables):

In[31]:=
With[{n = 3}, ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h2, n, reduceF2[#, n] &]] // FullSimplify
Out[31]=
In[32]:=
With[{n = 3}, ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h2, n, reduceF2[#, n] &]] // FullSimplify
Out[32]=

Define the Hamiltonian as :

In[33]:=
ClearAll[h3, \[CapitalDelta], \[Omega], \[Sigma]]
h3[t_] := \[CapitalDelta]/2 Subscript[\[Sigma], 3] + A Cos[\[Omega] t] Subscript[\[Sigma], 1]

Define corresponding algebra and Groebner Basis:

In[34]:=
ClearAll[vars2, rel2]
vars2 = Table[Subscript[\[Sigma], j], {j, 3}];
rel2 = Table[
   Subscript[\[Sigma], i] ** Subscript[\[Sigma], j] - KroneckerDelta[i, j] - I Sum[LeviCivitaTensor[3][[i, j, k]] Subscript[\[Sigma], k], {k, 3}], {i, 3}, {j, 3}] // Flatten
Out[7]=
In[35]:=
ClearAll[alg3]
alg3[n_] := NonCommutativeAlgebra[<|
    "ScalarVariables" -> Join[{\[CapitalDelta], A, \[Omega]}, Table[Subscript[\[FormalT], i], {i, n}]]|>];
gb3[n_] := NonCommutativeGroebnerBasis[rel2, vars2, alg3[n]]

Define a function to simplify corresponding polynomials:

In[36]:=
ClearAll[reduceF3]
reduceF3[exp_, n_] := NonCommutativePolynomialReduce[
   NonCommutativePolynomialReduce[exp, gb3[n], vars2, alg3[n]][[-1]], gb3[n], Reverse@vars2, alg3[n]][[-1]]

Calculate {Ω1(t),Ω2(t),Ω3(t),Ω4(t)} and then collect them by Pauli matrix terms:

In[37]:=
\[CapitalOmega]1To4 = NonCommutativeCollect[FullSimplify@#, vars2, NonCommutativeAlgebra[<|
      "ScalarVariables" -> {\[Omega], \[FormalCapitalT], A, \[CapitalDelta]}|>]] & /@ Table[ResourceFunction[
    "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h3, n, reduceF3[#, n] &, "TimeIntegration" -> True], {n, 4}]
Out[37]=

For each term, find the coefficient for Pauli matrices (keep in mind that we will have only linear terms):

In[38]:=
\[CapitalOmega]1To4CoefficientRules = CoefficientRules[Total@\[CapitalOmega]1To4, vars2]
Out[38]=

Now let's repeat the same process, but this time assigning explicit values to Pauli matrics and doing the commutation/dot calculations:

In[39]:=
ClearAll[h4, \[CapitalDelta], \[Omega], A, \[Sigma]]
h4[t_] := \[CapitalDelta]/2 PauliMatrix[3] + A Cos[\[Omega] t] PauliMatrix[1]

Ω1To4Manual=a1σ1+a2σ2+a3σ3

In[40]:=
\[CapitalOmega]1To4Manual = Sum[ResourceFunction[
   "MagnusTerms", ResourceSystemBase -> "https://www.wolframcloud.com/obj/resourcesystem/api/1.0"][h4, n, Dot, "TimeIntegration" -> True], {n, 4}]
Out[40]=

Note ai=Tr[σi.Ω1To4Manual]/2. One can calculate it and compare with the previous result:

In[41]:=
Table[Tr[\[CapitalOmega]1To4Manual . PauliMatrix[j]]/2, {j, 3}] - \[CapitalOmega]1To4CoefficientRules[[
   All, -1]] // FullSimplify
Out[41]=

As expected, the coefficients in front of Pauli matrices are the same the ones we obtained from non - commutative algebraic calculations.

Some numerical exploration. To find approximation to unitary operator determined by H(t), calculate {-ⅈ Ω1(t),(-ⅈ)2Ω2(t),(-ⅈ)3Ω3(t),(-ⅈ)4Ω4(t)}:

In[42]:=
omega = (Table[(-I)^n, {n, 4}] \[CapitalOmega]1To4) /. {A -> .2, \[CapitalDelta] -> .1, \[Omega] -> 1, Subscript[\[Sigma], 1] -> PauliMatrix[1], Subscript[\[Sigma], 2] -> PauliMatrix[2], Subscript[\[Sigma], 3] -> PauliMatrix[3]};

Calculate the unitary operator:

In[43]:=
ham = (\[CapitalDelta]/2 PauliMatrix[3] + A Cos[\[Omega] t] PauliMatrix[
       1] /. {A -> .2, \[CapitalDelta] -> .1, \[Omega] -> 1});
u = NDSolveValue[{\[FormalU]'[
     t] == -I ham . \[FormalU][t], \[FormalU][0] == IdentityMatrix[2]}, \[FormalU], {t, 0, tf = 4 \[Pi]}]
Out[44]=

Calculate {Ω1(t),∑n=12Ωn(t),∑n=13Ωn(t),∑n=14Ωn(t)}:

In[45]:=
\[CapitalOmega]n = Accumulate[omega];

Calculate nΩn(t) and compare it with the solution :

In[46]:=
Legended[
 Show[Table[
   LogPlot[Norm[
     MatrixExp[\[CapitalOmega]n[[j]]] - u[\[FormalCapitalT]]], {\[FormalCapitalT], 10^-3, tf}, PlotStyle -> ColorData[97][j]], {j, 4}], PlotRange -> All, GridLines -> Automatic, PlotLabel -> "Norm difference of unitary operator from Magnus approximation", AspectRatio -> 1/2, Frame -> True, FrameLabel -> {"time", "||\!\(\*SuperscriptBox[\(\[ExponentialE]\), \(\*SubscriptBox[\(\[Sum]\), \(n\)]\*SubscriptBox[\(\[CapitalOmega]\), \(n\)] \((t)\)\)]\)-\[ScriptCapitalT](\!\(\*SuperscriptBox[\(\[ExponentialE]\), \(\(-\[ImaginaryI]\)\\\ \(\*SubsuperscriptBox[\(\[Integral]\), \(0\), \(t\)]H \((s)\) \[DifferentialD]s\)\)]\))||"}, ImageSize -> 800], Placed[LineLegend[Table[ColorData[97][j], {j, 4}], Table["Magnus terms up to n=" <> ToString[j], {j, 4}]], {Right, Bottom}]]
Out[46]=

Publisher

Mads Bahrami

Version History

  • 1.0.0 – 29 October 2025

License Information