diff --git a/QuantumFramework/Kernel/SecondQuantization/BlasiakFormula.m b/QuantumFramework/Kernel/SecondQuantization/BlasiakFormula.m index 9334eade..06cb8134 100644 --- a/QuantumFramework/Kernel/SecondQuantization/BlasiakFormula.m +++ b/QuantumFramework/Kernel/SecondQuantization/BlasiakFormula.m @@ -2,176 +2,53 @@ Package["Wolfram`QuantumFramework`SecondQuantization`"] -PackageScope["BlasiakNormalOrder"] - PackageScope["MultiModeBlasiakOrder"] -PackageScope["ParseBlasiakMonomial"] - - - -ncPower[_, 0] := 1 -ncPower[op_, 1] := op -ncPower[op_, p_] := GeneralizedPower[NonCommutativeMultiply, op, p] - -blasiakBuildTerm[coeff_, 0, 0, b_, bdag_] := coeff -blasiakBuildTerm[coeff_, 0, q_, b_, bdag_] := coeff ncPower[b, q] -blasiakBuildTerm[coeff_, p_, 0, b_, bdag_] := coeff ncPower[bdag, p] -blasiakBuildTerm[coeff_, p_, q_, b_, bdag_] := coeff ncPower[bdag, p] ** ncPower[b, q] +General::ladpoly = "`1` is not a polynomial in the ladder operators." - -blasiakExponentsQ[v_] := v =!= {} && VectorQ[v, IntegerQ[#] && NonNegative[#] &] - - -blasiakCoefficient[cumVec_, powers_, k_] := - (1 / k!) Sum[ - Binomial[k, j] (-1)^(k - j) Times @@ MapThread[FactorialPower, {Most[cumVec] + j, powers}], - {j, 0, k} - ] - - -BlasiakNormalOrder::badexponents = - "expected equal-length vectors of non-negative integers, got `1` and `2`" - -BlasiakNormalOrder[rList_ ? blasiakExponentsQ, sList_ ? blasiakExponentsQ, var_] /; - Length[rList] === Length[sList] := -With[{ - excess = Total[rList - sList], - b = var, - bdag = SuperDagger[var] -}, - If[ excess >= 0, - With[{cumulative = FoldList[Plus, 0, rList - sList]}, - Sum[ - blasiakBuildTerm[ - blasiakCoefficient[cumulative, sList, k], - excess + k, k, b, bdag - ], - {k, First[sList], Total[sList]} - ] +(* A normal-ordered polynomial is <|{p1, \[Ellipsis], pn, q1, \[Ellipsis], qn} -> coefficient|>, and each mode of a product of two + normal-ordered monomials reorders by a^q a\[Dagger]^r = \[Sum]_k Binomial[q, k] FactorialPower[r, k] a\[Dagger]^(r-k) a^(q-k). *) +blasiakProduct[n_][kp_ -> cp_, kq_ -> cq_] := + (Join[#[[All, 1]], #[[All, 2]]] -> cp cq Times @@ #[[All, 3]]) & /@ Tuples @ Table[ + With[{p = kp[[i]], q = kp[[n + i]], r = kq[[i]], s = kq[[n + i]]}, + Table[{p + r - k, q + s - k, Binomial[q, k] FactorialPower[r, k]}, {k, 0, Min[q, r]}] ], - - With[{ - cumulative = FoldList[Plus, 0, Reverse[sList] - Reverse[rList]], - reversedPowers = Reverse[rList] - }, - Sum[ - blasiakBuildTerm[ - blasiakCoefficient[cumulative, reversedPowers, k], - k, k - excess, b, bdag - ], - {k, Last[rList], Total[rList]} - ] - ] + {i, n} ] -] - -BlasiakNormalOrder[rList_, sList_, var_] := - (Message[BlasiakNormalOrder::badexponents, rList, sList]; $Failed) - - - -ParseBlasiakMonomial::badfactor = "unsupported non-ladder factor: `1`" - -blasiakFactorType[f_, var_, bdag_] := Replace[f, { - x_ /; x === var :> {"b", 1}, - x_ /; x === bdag :> {"bdag", 1}, - GeneralizedPower[NonCommutativeMultiply, x_, n_] /; x === var :> {"b", n}, - GeneralizedPower[NonCommutativeMultiply, x_, n_] /; x === bdag :> {"bdag", n}, - Power[x_, n_] /; x === var :> {"b", n}, - Power[x_, n_] /; x === bdag :> {"bdag", n}, - _ :> {"unknown", 0} -}] - -ParseBlasiakMonomial[expr_, var_] := Module[{factors, typed, bad, blocks}, - factors = Replace[expr, {ncm_NonCommutativeMultiply :> List @@ ncm, e_ :> {e}}]; - typed = blasiakFactorType[#, var, SuperDagger[var]] & /@ factors; - - bad = FirstPosition[typed, {"unknown", _}, None, {1}]; - If[ bad =!= None, - Message[ParseBlasiakMonomial::badfactor, factors[[First[bad]]]]; - Return[$Failed, Module] - ]; - - blocks = {#[[1, 1]], Total[#[[All, 2]]]} & /@ Split[typed, First[#1] === First[#2] &]; - - blocks = Join[ - If[blocks =!= {} && blocks[[1, 1]] === "b", {{"bdag", 0}}, {}], - blocks, - If[blocks =!= {} && blocks[[-1, 1]] === "bdag", {{"b", 0}}, {}] - ]; - - {Reverse[blocks[[1 ;; ;; 2, 2]]], Reverse[blocks[[2 ;; ;; 2, 2]]]} -] - - - -blasiakModePolynomial[factors_List, {b_, bdag_}] := -With[{modeFactors = Select[factors, ! FreeQ[#, b | bdag] &]}, - If[ modeFactors === {}, - 1, - Replace[ - ParseBlasiakMonomial[NonCommutativeMultiply @@ modeFactors, b], - { - {rList_, sList_} :> BlasiakNormalOrder[rList, sList, b], - _ :> $Failed - } - ] +blasiakTimes[n_][pp_, qq_] := DeleteCases[Merge[Flatten @ Outer[blasiakProduct[n], Normal[pp], Normal[qq], 1], Total], 0] + +blasiakPolynomial[lv_, e_] := + With[{gens = Alternatives @@ lv["Generators"], zero = ConstantArray[0, Length[lv["Generators"]]], n = Length[lv["Creators"]]}, + Replace[e, { + s_ /; FreeQ[s, gens] :> <|zero -> s|>, + g : gens :> <|Boole[SameQ[g, #]] & /@ lv["Generators"] -> 1|>, + (GeneralizedPower[NonCommutativeMultiply, g : gens, k_Integer ? NonNegative] | Power[g : gens, k_Integer ? NonNegative]) :> + <|k (Boole[SameQ[g, #]] & /@ lv["Generators"]) -> 1|>, + (GeneralizedPower[NonCommutativeMultiply, x_, k_Integer ? NonNegative] | Power[x_, k_Integer ? NonNegative]) :> + With[{px = blasiakPolynomial[lv, x]}, Nest[blasiakTimes[n][#, px] &, <|zero -> 1|>, k]], + s_Plus :> Merge[blasiakPolynomial[lv, #] & /@ List @@ s, Total], + m_NonCommutativeMultiply :> Fold[blasiakTimes[n], blasiakPolynomial[lv, #] & /@ List @@ m], + t_Times :> With[{op = Select[List @@ t, ! FreeQ[#, gens] &]}, + If[Length[op] === 1, t / First[op] blasiakPolynomial[lv, First[op]], Throw[t, "ladpoly"]] + ], + f_ :> Throw[f, "ladpoly"] + }] ] -] - - -MultiModeBlasiakOrder[exprIn_, vars_List, scalars_List] := -With[{altVars = Alternatives @@ vars}, -Module[{expr, factors, scalarFactors, modePolys, result}, - - expr = exprIn //. { - GeneralizedPower[NonCommutativeMultiply, - NonCommutativeMultiply[args__], n_Integer ? Positive] :> - NonCommutativeMultiply @@ Flatten[ConstantArray[{args}, n]], - Power[NonCommutativeMultiply[args__], n_Integer ? Positive] :> - NonCommutativeMultiply @@ Flatten[ConstantArray[{args}, n]], - NonCommutativeMultiply[a___, NonCommutativeMultiply[b__], c___] :> - NonCommutativeMultiply[a, b, c] - }; - expr = LiftNCScalars[expr, vars]; - - factors = Catenate @ Map[ - Replace[{ncm_NonCommutativeMultiply :> List @@ ncm, f_ :> {f}}], - Replace[expr, {p : (_Times | _NonCommutativeMultiply) :> List @@ p, e_ :> {e}}] - ]; - - {scalarFactors, factors} = - Lookup[GroupBy[factors, FreeQ[#, altVars] &], {True, False}, {}]; - - modePolys = blasiakModePolynomial[factors, #] & /@ Partition[vars, 2]; - - If[ MemberQ[modePolys, $Failed], Return[$Failed, Module] ]; - - result = NonCommutativeMultiply @@ DeleteCases[modePolys, 1]; - - result = result //. { - NonCommutativeMultiply[a___, b_ + c_, d___] :> - NonCommutativeMultiply[a, b, d] + NonCommutativeMultiply[a, c, d], - NonCommutativeMultiply[a___, Times[c_, b__], d___] /; FreeQ[c, altVars] :> - c NonCommutativeMultiply[a, b, d], - NonCommutativeMultiply[a___, c_, d___] /; FreeQ[c, altVars] :> - c NonCommutativeMultiply[a, d] - }; - - result = result /. { - NonCommutativeMultiply[x_] :> x, - NonCommutativeMultiply[] -> 1 - }; +blasiakWord[lv_, e_] := + Replace[ + MapThread[Replace[{#1, #2}, {{_, 0} -> Nothing, {g_, 1} :> g, {g_, k_} :> GeneralizedPower[NonCommutativeMultiply, g, k]}] &, + {lv["Generators"], e}], + {{} -> 1, {x_} :> x, w_ :> NonCommutativeMultiply @@ w} + ] - result = result /. NonCommutativeMultiply[args__] :> - NonCommutativeMultiply @@ SortBy[{args}, { - FreeQ[#, SuperDagger] &, - First @ FirstPosition[vars, v_ /; ! FreeQ[#, v], {Infinity}, {1}] & - }]; +MultiModeBlasiakOrder[exprs_List, lv_Association, f_] := MultiModeBlasiakOrder[#, lv, f] & /@ exprs - (Times @@ scalarFactors) result -]] +MultiModeBlasiakOrder[expr_, lv_Association, f_] := + Catch[ + Total @ KeyValueMap[#2 blasiakWord[lv, #1] &, DeleteCases[Expand /@ blasiakPolynomial[lv, expr], 0]], + "ladpoly", + (Message[f::ladpoly, #1]; $Failed) & + ] diff --git a/QuantumFramework/Kernel/SecondQuantization/BosonicAlgebra.m b/QuantumFramework/Kernel/SecondQuantization/BosonicAlgebra.m index f5fa135b..dd7f7d1a 100644 --- a/QuantumFramework/Kernel/SecondQuantization/BosonicAlgebra.m +++ b/QuantumFramework/Kernel/SecondQuantization/BosonicAlgebra.m @@ -2,8 +2,6 @@ Package["Wolfram`QuantumFramework`SecondQuantization`"] -PackageExport["BosonicRelations"] - PackageExport["BosonicNormalOrder"] PackageExport["BosonicAntinormalOrder"] @@ -19,195 +17,99 @@ PackageScope["vevPolynomialQ"] -BosonicRelations::usage = -"\!\(\*RowBox[{\"BosonicRelations\", \"[\", RowBox[{StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) Returns the list of bosonic commutation relations for the operators in vars."; - -BosonicRelations[vars_List] := -Block[{pairs}, - pairs = Subsets[LexicographicSort@vars, {2}]; - Map[ - If[ MatchQ[#, {x_, SuperDagger[x_]} | {SuperDagger[x_], x_}], - Commutator[#[[1]], #[[2]]] - 1, - Commutator[#[[1]], #[[2]]] - ] &, - pairs - ] -] - - -grobnerNormalOrder[expr_, vars_List, scalars_List, direction_String : "Normal"] := -Block[{ - orderedVars = OrderVariables[vars, direction], - rels, - alg -}, - rels = BosonicRelations[vars]; - If[ Length[scalars] > 0, - alg = NonCommutativeAlgebra["ScalarVariables" -> scalars]; - NonCommutativePolynomialReduce[expr, rels, orderedVars, alg][[2]], - NonCommutativePolynomialReduce[expr, rels, NonCommutativeAlgebra[<|"Generators"-> orderedVars|>]][[2]] - ] -] - - BosonicNormalOrder::usage = -"\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) Brings expr into normal order using bosonic commutation relations.\n\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"Method->\", StyleBox[\"m\", \"TI\"]}], \"]\"}]\) Specifies the reduction method: Automatic (default), \"GrobnerBasis\", or \"Blasiak\".\n\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Scalars\\\"->\", StyleBox[\"syms\", \"TI\"]}], \"]\"}]\) Treats syms as commuting scalars during reduction."; +"\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"a\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}]}], \"]\"}]\) brings expr into normal order in the annihilators \!\(\*SubscriptBox[StyleBox[\"a\", \"TI\"], \"i\"]\) and creators \!\(\*SubsuperscriptBox[StyleBox[\"a\", \"TI\"], \"i\", \"\[Dagger]\"]\).\n\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", RowBox[{\"{\", RowBox[{RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"c\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}], \",\", RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"a\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}]}], \"}\"}]}], \"]\"}]\) takes the creators \!\(\*SubscriptBox[StyleBox[\"c\", \"TI\"], \"i\"]\).\n\!\(\*RowBox[{\"BosonicNormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"alg\", \"TI\"]}], \"]\"}]\) uses the WeylAlgebra alg."; BosonicNormalOrder::unknownMethod = "Unknown Method: `1`." -Options[BosonicNormalOrder] = {Method -> Automatic, "Scalars" -> {}} +Options[BosonicNormalOrder] = {Method -> Automatic} -(* Ordering is linear: a sum maps over its summands, and the map stays on - this kernel (parallel sub-kernels do not load the paclet). A summand the - monomial reducer rejects fails the whole sum rather than leaving a - $Failed inside a Plus. *) -linearOverSums[f_][expr_] := - If[ MatchQ[expr, _Plus], - Replace[Map[f, expr], p_ /; ! FreeQ[p, $Failed] :> $Failed], - f[expr] +expandCoefficients[expr_, lv_] := + With[{mono = _NonCommutativeMultiply | GeneralizedPower[NonCommutativeMultiply, Alternatives @@ lv["Generators"], _] | Alternatives @@ lv["Generators"]}, + Total @ KeyValueMap[Expand[Total[#2]] #1 &, + GroupBy[ + Replace[Replace[expr, {s_Plus :> List @@ s, s_ :> {s}}], + {m : mono :> {m, 1}, Times[c__, m : mono] :> {m, Times[c]}, c_ :> {1, c}}, {1}], + First -> Last + ] + ] ] -(* With no field variables there is nothing to reduce: a c-number is already in - normal order, so return it unchanged. *) -BosonicNormalOrder[expr_, {}, OptionsPattern[]] := expr - -BosonicNormalOrder[expr_, vars_List, opts : OptionsPattern[]] := -With[{ - method = OptionValue[Method], - scalars = OptionValue["Scalars"], - all = vevVars[vars] -}, - Replace[method, { - (* NonCommutativePolynomialReduce reduces a whole Plus itself. *) - Automatic | "GrobnerBasis" :> grobnerNormalOrder[expr, all, scalars], - (* MultiModeBlasiakOrder takes one monomial at a time. *) - "Blasiak" :> linearOverSums[MultiModeBlasiakOrder[#, all, scalars] &][expr], - _ :> (Message[BosonicNormalOrder::unknownMethod, method]; $Failed) - }] -] +ladderOrder[lv_, Automatic, _] := + expandCoefficients[ + NonCommutativeExpand[ + # //. GeneralizedPower[NonCommutativeMultiply, w_NonCommutativeMultiply, k_Integer ? Positive] :> + NonCommutativeMultiply @@ Catenate[ConstantArray[List @@ w, k]], + lv["Algebra"] + ], + lv + ] & + +ladderOrder[lv_, "Blasiak", f_] := MultiModeBlasiakOrder[#, lv, f] & + +BosonicNormalOrder[expr_, vars_, OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicNormalOrder, vars], method = OptionValue[Method]}, + Which[ + lv === $Failed, $Failed, + ! MatchQ[method, Automatic | "Blasiak"], Message[BosonicNormalOrder::unknownMethod, method]; $Failed, + True, ladderOrder[lv, method, BosonicNormalOrder][expr] + ] + ] (* a -> a\[Dagger], a\[Dagger] -> -a is an automorphism ([a\[Dagger], -a] = 1) carrying a normal-ordered monomial to an anti-ordered one, so conjugating by it turns any normal-ordering method into an anti-normal one. "Inverse" maps the result back. *) -ladderSwap[expr_, vars_List, direction_String : "Forward"] := -Block[{ - swap = Catenate @ Map[ - If[ direction === "Inverse", - {SuperDagger[#] -> #, # -> -SuperDagger[#]} &, - {SuperDagger[#] -> -#, # -> SuperDagger[#]} & +ladderSwap[expr_, lv_Association, direction_String : "Forward"] := + LiftNCScalars[ + expr /. If[ direction === "Inverse", + Join[Thread[lv["Creators"] -> lv["Annihilators"]], Thread[lv["Annihilators"] -> -lv["Creators"]]], + Join[Thread[lv["Creators"] -> -lv["Annihilators"]], Thread[lv["Annihilators"] -> lv["Creators"]]] ], - Select[vars, FreeQ[#, SuperDagger] &] + lv["Generators"] ] -}, - LiftNCScalars[expr /. swap, vars] -] BosonicAntinormalOrder::usage = -"\!\(\*RowBox[{\"BosonicAntinormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) Brings the polynomial expr into anti-normal order, with every annihilation operator to the left of every creation operator, using bosonic commutation relations.\n\!\(\*RowBox[{\"BosonicAntinormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"Method->\", StyleBox[\"m\", \"TI\"]}], \"]\"}]\) Specifies the reduction method: Automatic (default), \"GrobnerBasis\", or \"Blasiak\".\n\!\(\*RowBox[{\"BosonicAntinormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Scalars\\\"->\", StyleBox[\"syms\", \"TI\"]}], \"]\"}]\) Treats syms as commuting scalars during reduction."; +"\!\(\*RowBox[{\"BosonicAntinormalOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) brings expr into anti-normal order in the ladder operators vars."; BosonicAntinormalOrder::unknownMethod = "Unknown Method: `1`." Options[BosonicAntinormalOrder] = Options[BosonicNormalOrder] -(* With no field variables there is nothing to reorder: a c-number is already in - anti-normal order, so return it unchanged. *) -BosonicAntinormalOrder[expr_, {}, OptionsPattern[]] := expr - -BosonicAntinormalOrder[expr_, vars_List, opts : OptionsPattern[]] := -With[{ - method = OptionValue[Method], - scalars = OptionValue["Scalars"], - all = vevVars[vars] -}, - Replace[method, { - (* NonCommutativePolynomialReduce reduces a whole Plus itself. *) - Automatic | "GrobnerBasis" :> grobnerNormalOrder[expr, all, scalars, "Antinormal"], - (* Normal-order each swapped monomial, then swap back. *) - "Blasiak" :> linearOverSums[ - ladderSwap[ - MultiModeBlasiakOrder[ladderSwap[#, all], all, scalars], - all, - "Inverse" - ] & - ][expr], - _ :> (Message[BosonicAntinormalOrder::unknownMethod, method]; $Failed) - }] -] - - -bosonicReduce[poly_, ncVars_List] := -Block[{rels, scalars, alg}, - rels = BosonicRelations[ncVars]; - scalars = DeleteDuplicates @ Cases[ - {poly}, - s_Symbol /; !FormalSymbolQ[s] && !MemberQ[ncVars, s] && !NumericQ[s], - Infinity - ]; - alg = NonCommutativeAlgebra["ScalarVariables" -> scalars]; - NonCommutativePolynomialReduce[poly, rels, OrderVariables[ncVars], alg][[2]] -] +BosonicAntinormalOrder[expr_, vars_, OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicAntinormalOrder, vars], method = OptionValue[Method]}, + Which[ + lv === $Failed, $Failed, + ! MatchQ[method, Automatic | "Blasiak"], Message[BosonicAntinormalOrder::unknownMethod, method]; $Failed, + True, expandCoefficients[ladderSwap[ladderOrder[lv, method, BosonicAntinormalOrder][ladderSwap[expr, lv]], lv, "Inverse"], lv] + ] + ] BosonicBCHTerms::usage = -"\!\(\*RowBox[{\"BosonicBCHTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"]\"}]\) Computes the nth-order term of the BCH series log(\!\(\*SuperscriptBox[\(e\), \(op1\)]\) \!\(\*SuperscriptBox[\(e\), \(op2\)]\)\[Ellipsis]), reduced using bosonic commutation relations.\n\!\(\*RowBox[{\"BosonicBCHTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"], \",\", StyleBox[\"ncVars\", \"TI\"]}], \"]\"}]\) Uses the explicitly supplied list of non-commutative variables ncVars."; - -BosonicBCHTerms[ops_List, n_Integer] := BosonicBCHTerms[ops, n, ExtractNCVars[ops]] +"\!\(\*RowBox[{\"BosonicBCHTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) gives the nth-order term of log(\!\(\*SuperscriptBox[\(e\), \(op1\)]\) \!\(\*SuperscriptBox[\(e\), \(op2\)]\)\[Ellipsis]) in normal order."; -BosonicBCHTerms[ops_List, n_Integer, ncVars_List] := -Block[{bchTerm}, - bchTerm = ResourceFunction["BakerCampbellHausdorffTerms"][ops, n]; - bosonicReduce[NonCommutativeExpand[bchTerm], ncVars] -] +BosonicBCHTerms[ops_List, n_Integer, vars_] := + Replace[ResolveLadderVariables[BosonicBCHTerms, vars], + lv_Association :> NonCommutativeExpand[ResourceFunction["BakerCampbellHausdorffTerms"][ops, n], lv["Algebra"]] + ] BosonicZassenhausTerms::usage = -"\!\(\*RowBox[{\"BosonicZassenhausTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"]\"}]\) Computes the nth term of the Zassenhaus formula and reduces the expression using bosonic commutation relations.\n\!\(\*RowBox[{\"BosonicZassenhausTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"], \",\", StyleBox[\"ncVars\", \"TI\"]}], \"]\"}]\) Uses the explicitly supplied list of non-commutative variables ncVars."; - -BosonicZassenhausTerms[ops_List, n_Integer] := BosonicZassenhausTerms[ops, n, ExtractNCVars[ops]] +"\!\(\*RowBox[{\"BosonicZassenhausTerms\", \"[\", RowBox[{StyleBox[\"ops\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) gives the nth term of the Zassenhaus formula in normal order."; -BosonicZassenhausTerms[ops_List, n_Integer, ncVars_List] := -Block[{zassTerm}, - zassTerm = ResourceFunction["ZassenhausTerms"][ops, n]; - bosonicReduce[NonCommutativeExpand[zassTerm], ncVars] -] +BosonicZassenhausTerms[ops_List, n_Integer, vars_] := + Replace[ResolveLadderVariables[BosonicZassenhausTerms, vars], + lv_Association :> NonCommutativeExpand[ResourceFunction["ZassenhausTerms"][ops, n], lv["Algebra"]] + ] BosonicVEV::usage = -"\!\(\*RowBox[{\"BosonicVEV\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) Computes the vacuum expectation value \[LeftAngleBracket]0\[VerticalSeparator]expr\[VerticalSeparator]0\[RightAngleBracket] by normal-ordering expr and extracting the scalar (c-number) part.\n\!\(\*RowBox[{\"BosonicVEV\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"]}], \"]\"}]\) Auto-detects non-commutative variables from expr.\n\!\(\*RowBox[{\"BosonicVEV\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"Method->\", StyleBox[\"m\", \"TI\"]}], \"]\"}]\) Passes method options to BosonicNormalOrder."; - -BosonicVEV::novars = -"No field variables were recognized in `1`. Ladder operators must be Formal symbols (see FieldVariables), or be given explicitly as BosonicVEV[expr, vars]." +"\!\(\*RowBox[{\"BosonicVEV\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) gives the vacuum expectation value \[LeftAngleBracket]0\[VerticalSeparator]expr\[VerticalSeparator]0\[RightAngleBracket]."; Options[BosonicVEV] = Options[BosonicNormalOrder]; -BosonicVEV[expr_, opts : OptionsPattern[]] := - With[{vars = ExtractNCVars[{expr}]}, - (* Non-formal symbols are scalars, so with no field variables the only - operator structure left is a ** joining c-numbers; SuperDagger instead - means ladder operators were meant but not written as Formal symbols. - Short-circuit before re-dispatching: BosonicVEV[expr, {}] would re-match - this same rule ({} is absorbed as empty options), so calling it here would - recurse without bound. *) - With[{value = Which[ - vars =!= {}, - BosonicVEV[expr, vars, opts], - FreeQ[expr, SuperDagger], - vevCollapse[expr], - True, - Message[BosonicVEV::novars, expr]; $Failed - ]}, - (* An unevaluated inner call means there is nothing to read off; let - this call stay unevaluated too rather than echo the vars back. *) - value /; ! MatchQ[value, _BosonicVEV] - ] - ] - -vevVars[vars_List] := - DeleteDuplicates @ - Catenate[{#, SuperDagger[#]} & /@ DeleteDuplicates[vars /. SuperDagger[v_] :> v]] - vevCollapse[expr_] := expr //. { GeneralizedPower[NonCommutativeMultiply, op_, p_] :> op^p, NonCommutativeMultiply -> Times @@ -218,20 +120,21 @@ this same rule ({} is absorbed as empty options), so calling it here would PolynomialQ[vevCollapse[expr] /. Thread[vars -> syms], syms] ] -(* The condition sits on the left-hand side so a non-polynomial never reaches - BosonicNormalOrder: the reducer would both fail and leak its own messages. *) -BosonicVEV[expr_, vars_List, opts : OptionsPattern[]] /; - vevPolynomialQ[expr, vevVars[vars]] := - With[{all = vevVars[vars]}, - vevCollapse[BosonicNormalOrder[expr, all, opts] /. $nonuls] /. - (Alternatives @@ all -> 0) +BosonicVEV[exprs_List, vars_, opts : OptionsPattern[]] := BosonicVEV[#, vars, opts] & /@ exprs + +BosonicVEV[expr_, vars_, opts : OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicVEV, vars]}, + If[ lv === $Failed, + $Failed, + vevCollapse[BosonicNormalOrder[expr, vars, opts] /. $nonuls] /. Thread[lv["Generators"] -> 0] + ] /; lv === $Failed || vevPolynomialQ[expr, lv["Generators"]] ] BosonicMatrixElement::usage = -"\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", RowBox[{\"DisplacementOperator\", \"[\", RowBox[{StyleBox[\"\[Alpha]\", \"TI\"]}], \"]\"}]}], \"]\"}]\) Returns \[LeftAngleBracket]m\[VerticalSeparator]D(\[Alpha])\[VerticalSeparator]n\[RightAngleBracket] in closed form via associated Laguerre polynomials.\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", RowBox[{\"SqueezeOperator\", \"[\", RowBox[{StyleBox[\"\[Xi]\", \"TI\"]}], \"]\"}]}], \"]\"}]\) Returns \[LeftAngleBracket]m\[VerticalSeparator]S(\[Xi])\[VerticalSeparator]n\[RightAngleBracket] in closed form (zero when m+n is odd).\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", StyleBox[\"poly\", \"TI\"]}], \"]\"}]\) Returns \[LeftAngleBracket]m\[VerticalSeparator]poly\[VerticalSeparator]n\[RightAngleBracket] for a polynomial in the field variables of a single mode, by normal ordering and the closed form for \[LeftAngleBracket]m\[VerticalSeparator]\!\(\*SuperscriptBox[\"a\", RowBox[{\"\[Dagger]\", \"p\"}]]\)\!\(\*SuperscriptBox[\"a\", \"q\"]\)\[VerticalSeparator]n\[RightAngleBracket]. The Fock indices may be symbolic.\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"\[Alpha]\", \"TI\"], \",\", StyleBox[\"\[Beta]\", \"TI\"]}], \"}\"}], \",\", StyleBox[\"poly\", \"TI\"], \",\", \"\\\"Basis\\\"->\\\"Coherent\\\"\"}], \"]\"}]\) Returns \[LeftAngleBracket]\[Alpha]\[VerticalSeparator]poly\[VerticalSeparator]\[Beta]\[RightAngleBracket] between coherent states of amplitude \[Alpha] and \[Beta], by normal ordering and \[LeftAngleBracket]\[Alpha]\[VerticalSeparator]\!\(\*SuperscriptBox[\"a\", RowBox[{\"\[Dagger]\", \"p\"}]]\)\!\(\*SuperscriptBox[\"a\", \"q\"]\)\[VerticalSeparator]\[Beta]\[RightAngleBracket] = \!\(\*SuperscriptBox[OverscriptBox[\"\[Alpha]\", \"_\"], \"p\"]\)\!\(\*SuperscriptBox[\"\[Beta]\", \"q\"]\)\[LeftAngleBracket]\[Alpha]\[VerticalBar]\[Beta]\[RightAngleBracket].\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"m\", \"TI\"], StyleBox[\"1\", \"TR\"]], \",\", SubscriptBox[StyleBox[\"m\", \"TI\"], StyleBox[\"2\", \"TR\"]], \",\", StyleBox[\"\[Ellipsis]\", \"TR\"]}], \"}\"}], \",\", RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"n\", \"TI\"], StyleBox[\"1\", \"TR\"]], \",\", SubscriptBox[StyleBox[\"n\", \"TI\"], StyleBox[\"2\", \"TR\"]], \",\", StyleBox[\"\[Ellipsis]\", \"TR\"]}], \"}\"}]}], \"}\"}], \",\", StyleBox[\"poly\", \"TI\"]}], \"]\"}]\) Returns the element between multimode Fock states, one index per mode, for a polynomial in the field variables of several independent modes. The modes are the \"Generators\" in the order given, or else the field variables of poly, sorted; declare them when poly does not touch every mode. With \"Basis\"->\"Coherent\" the indices are amplitude vectors."; +"\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", RowBox[{\"DisplacementOperator\", \"[\", RowBox[{StyleBox[\"\[Alpha]\", \"TI\"]}], \"]\"}]}], \"]\"}]\) gives \[LeftAngleBracket]m\[VerticalSeparator]D(\[Alpha])\[VerticalSeparator]n\[RightAngleBracket].\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", RowBox[{\"SqueezeOperator\", \"[\", RowBox[{StyleBox[\"\[Xi]\", \"TI\"]}], \"]\"}]}], \"]\"}]\) gives \[LeftAngleBracket]m\[VerticalSeparator]S(\[Xi])\[VerticalSeparator]n\[RightAngleBracket].\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"m\", \"TI\"], \",\", StyleBox[\"n\", \"TI\"]}], \"}\"}], \",\", StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) gives \[LeftAngleBracket]m\[VerticalSeparator]expr\[VerticalSeparator]n\[RightAngleBracket] in the ladder operators vars.\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"m\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}], \",\", RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"n\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}]}], \"}\"}], \",\", StyleBox[\"poly\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) gives the element of poly between multimode Fock states.\n\!\(\*RowBox[{\"BosonicMatrixElement\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{StyleBox[\"\[Alpha]\", \"TI\"], \",\", StyleBox[\"\[Beta]\", \"TI\"]}], \"}\"}], \",\", StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Basis\\\"->\\\"Coherent\\\"\"}], \"]\"}]\) gives \[LeftAngleBracket]\[Alpha]\[VerticalSeparator]expr\[VerticalSeparator]\[Beta]\[RightAngleBracket] between coherent states."; -Options[BosonicMatrixElement] = {"Basis" -> "Fock", "Generators" -> Automatic} +Options[BosonicMatrixElement] = {"Basis" -> "Fock"} SetAttributes[BosonicMatrixElement, HoldRest] @@ -268,10 +171,10 @@ this same rule ({} is absorbed as empty options), so calling it here would coherentOverlap[\[Alpha]_, \[Beta]_] := Exp[Conjugate[\[Alpha]] \[Beta] - (Abs[\[Alpha]]^2 + Abs[\[Beta]]^2)/2] -ladderSum[element_, {ms_, ns_}, expr_, vs_List] := - Module[{x, y, k = Length[vs], vars, p}, +ladderSum[element_, {ms_, ns_}, expr_, lv_Association] := + Module[{x, y, k = Length[lv["Annihilators"]], vars, p}, vars = Join[Array[x, k], Array[y, k]]; - p = Expand[vevCollapse[BosonicNormalOrder[expr, vevVars[vs]]] /. Thread[Join[SuperDagger /@ vs, vs] -> vars]]; + p = Expand[vevCollapse[BosonicNormalOrder[expr, {lv["Creators"], lv["Annihilators"]}]] /. Thread[lv["Generators"] -> vars]]; Which[ p === 0, 0, k == 1, @@ -297,17 +200,7 @@ this same rule ({} is absorbed as empty options), so calling it here would coherentBasisQ[opts___] := OptionValue[BosonicMatrixElement, {opts}, "Basis"] === "Coherent" -(* Any formal symbol may name a mode, so a formal scalar is told apart only by declaring - the generators; left Automatic the variables are inferred as before. Declared - generators keep the order given and inferred ones are sorted, so an index vector - always has a settled mode to sit against. *) -fieldVariables[expr_, opts___] := - DeleteDuplicates[ - Replace[OptionValue[BosonicMatrixElement, {opts}, "Generators"], - Automatic :> Sort[ExtractNCVars[{expr}]]] /. SuperDagger[w_] :> w - ] - -BosonicMatrixElement[{{m_}, {n_}}, expr_, opts : OptionsPattern[]] := BosonicMatrixElement[{m, n}, expr, opts] +BosonicMatrixElement[{{m_}, {n_}}, rest__] := BosonicMatrixElement[{m, n}, rest] BosonicMatrixElement[{m_, n_}, c_ ? NumericQ, opts : OptionsPattern[]] /; Length[Flatten[{m}]] === Length[Flatten[{n}]] := @@ -316,102 +209,121 @@ this same rule ({} is absorbed as empty options), so calling it here would {Flatten[{m}], Flatten[{n}]} ] -BosonicMatrixElement[{m_, n_}, expr_, opts : OptionsPattern[]] := - With[{vs = fieldVariables[expr, opts], ms = Flatten[{m}], ns = Flatten[{n}]}, - If[ coherentBasisQ[opts], - Times @@ MapThread[coherentOverlap, {ms, ns}] * - ladderSum[ZeroLimitPower[Conjugate[#1], #3] ZeroLimitPower[#2, #4] &, {ms, ns}, expr, vs], - ladderSum[fockLadderElement, {ms, ns}, expr, vs] - ] /; - Length[ms] === Length[vs] && Length[ns] === Length[vs] && - FreeQ[expr, _QuantumOperator | _QuantumState] && - vevPolynomialQ[expr, vevVars[vs]] +BosonicMatrixElement[{_, _}, Except[_DisplacementOperator | _SqueezeOperator | _ ? NumericQ], OptionsPattern[]] := + (Message[BosonicMatrixElement::argrx, BosonicMatrixElement, 2, 3]; $Failed) + +BosonicMatrixElement[{m_, n_}, expr_, vars : Except[_Rule | _RuleDelayed], opts : OptionsPattern[]] := + Module[{lv = ResolveLadderVariables[BosonicMatrixElement, vars], ms = Flatten[{m}], ns = Flatten[{n}], pair, j, r}, + pair = If[AssociationQ[lv], {First[lv["Creators"]], First[lv["Annihilators"]]}]; + r = Which[ + lv === $Failed || ! FreeQ[expr, _QuantumOperator | _QuantumState], $Failed, + Length[ms] === Length[ns] === Length[lv["Annihilators"]] && vevPolynomialQ[expr, lv["Generators"]], + If[ coherentBasisQ[opts], + Times @@ MapThread[coherentOverlap, {ms, ns}] ladderSum[ZeroLimitPower[Conjugate[#1], #3] ZeroLimitPower[#2, #4] &, {ms, ns}, expr, lv], + ladderSum[fockLadderElement, {ms, ns}, expr, lv] + ], + Length[lv["Annihilators"]] =!= 1 || ListQ[m] || ListQ[n], $Failed, + True, + Replace[normalProductElement[expr, pair, m, n, j, coherentBasisQ[opts]], + $Failed /; ! FreeQ[expr, E] :> + normalProductElement[BosonicExpOrder[expr, {lv["Creators"], lv["Annihilators"]}], pair, m, n, j, coherentBasisQ[opts]]] + ]; + r /; lv === $Failed || r =!= $Failed ] (* Normal ordering changes the function: :Exp[c n]: is (1 + c)^n on the diagonal. A base that vanishes leaves only the vacuum, so 0^n with n >= 0 is KroneckerDelta[n, 0] rather than 0^0 once n is set to 0; the factor 1 + b keeps a machine zero inexact. *) -numberDiagonal[expr_, v_, k_] := - With[{nn = SuperDagger[v] ** v}, +numberDiagonal[expr_, {cr_, an_}, k_] := + With[{nn = cr ** an}, With[{f = Replace[expr, { - NormalOrdered[Exp[c_. w_]] /; w === nn :> (1 + c)^k, + NormalOrdered[Exp[c_. w_], _] /; w === nn :> (1 + c)^k, e_ :> ReplaceAll[e, nn -> k] - }] /. Power[b_ /; TrueQ[b == 0], p_ /; TrueQ[Simplify[p >= 0, k >= 0]]] :> - (1 + b) KroneckerDelta[p, 0]}, - If[FreeQ[f, v | SuperDagger[v] | NormalOrdered], f, $Failed] + }] /. { + Power[b_ /; TrueQ[b == 0], p_ /; TrueQ[Simplify[p >= 0, k >= 0]]] :> (1 + b) KroneckerDelta[p, 0], + Power[b_ /; TrueQ[b == 0], p_ /; ! FreeQ[p, k]] :> Piecewise[{{1 + b, p == 0}}, b^p] + }}, + If[FreeQ[f, cr | an | NormalOrdered], f, $Failed] ] ] -(* A wing is an exponential of one operator alone, so its element is a Taylor coefficient - of Exp[P]: a displacement's linear wing and a squeeze's quadratic one share a formula, +(* A wing is a function of one operator alone, x^p Exp[P], so its element is a Taylor + coefficient: a displacement's linear wing and a squeeze's quadratic one share a formula, and the latter's parity rule is the vanishing of the odd coefficients. *) -wing[m_, k_, p_, x_] := SeriesCoefficient[Exp[p], {x, 0, m - k}] Sqrt[m!/k!] +wing[m_, k_, g_, x_] := SeriesCoefficient[g, {x, 0, m - k}] Sqrt[m!/k!] -wingPolynomial[s_, target_, v_, x_] := - With[{p = s /. target -> x /. NonCommutativeMultiply -> Times}, - If[FreeQ[p, v | _SuperDagger] && PolynomialQ[p, x] && TrueQ[(p /. x -> 0) == 0], - p, $Failed] +wingPolynomial[s_, pair_, side_, x_] := + Module[{c, a}, + With[{p = s /. Thread[pair -> {c, a}] /. If[side === "Up", c, a] -> x /. NonCommutativeMultiply -> Times}, + If[FreeQ[p, c | a] && PolynomialQ[p, x] && TrueQ[(p /. x -> 0) == 0], p, $Failed] + ] ] -normalFactor[fac_, v_, k_, x_] := +normalFactor[cr_, {cr_, _}, _, _] := "Creators" -> 1 + +normalFactor[GeneralizedPower[NonCommutativeMultiply, cr_, p_Integer ? Positive], {cr_, _}, _, _] := "Creators" -> p + +normalFactor[an_, {_, an_}, _, _] := "Annihilators" -> 1 + +normalFactor[GeneralizedPower[NonCommutativeMultiply, an_, q_Integer ? Positive], {_, an_}, _, _] := "Annihilators" -> q + +normalFactor[fac_, pair_, k_, x_] := With[{s = Replace[fac, {Exp[e_] :> e, _ :> None}]}, With[{ - up = If[s === None, $Failed, wingPolynomial[s, SuperDagger[v], v, x]], - dn = If[s === None, $Failed, wingPolynomial[s, v, v, x]] + up = If[s === None, $Failed, wingPolynomial[s, pair, "Up", x]], + dn = If[s === None, $Failed, wingPolynomial[s, pair, "Down", x]] }, Which[ up =!= $Failed, "Up" -> up, dn =!= $Failed, "Down" -> dn, - True, Replace[numberDiagonal[fac, v, k], f : Except[$Failed] :> "Diagonal" -> f] + True, Replace[numberDiagonal[fac, pair, k], f : Except[$Failed] :> "Diagonal" -> f] ] ] ] -(* scalar Exp[P[ad]] f[n] Exp[Q[a]], any factor absent. Wings of a kind commute so their - exponents add; between Fock states the middle sum runs only to Min[m, n]. *) -normalProductElement[expr_, v_, m_, n_, j_] := - Module[{x, terms, scalar, tagged, u, w, f, r}, +(* scalar Exp[P[ad]] ad^p f[n] a^q Exp[Q[a]], any factor absent. Factors of a kind commute, + so the up side is x^p Exp[P] and the down side x^q Exp[Q]; between Fock states the middle + sum runs only to Min[m, n]. Without exponentials the element is read in closed form, and + it vanishes for n < q before f[n - q] is evaluated, so a^dagger f[N] a keeps the vacuum + even when f[n - 1] is singular at n = 0. Between coherent states both sides are numbers + and the middle is summed in t before the amplitudes go in, so a zero amplitude meets no 0^j. + The factors must arrive in normal order: an antinormal product would otherwise be silently + reordered and keep its own scalar, wrong by the exponential of the commutator. *) +normalProductElement[expr_, pair_, m_, n_, j_, coherent_] := + Module[{x, t, terms, scalar, tagged, u, w, p, q, fu, fd, f, mono, r}, terms = If[Head[expr] === Times, List @@ expr, {expr}]; - scalar = Times @@ Select[terms, FreeQ[#, v | SuperDagger[v]] &]; - tagged = Replace[Times @@ Select[terms, ! FreeQ[#, v | SuperDagger[v]] &], + scalar = Times @@ Select[terms, FreeQ[#, Alternatives @@ pair] &]; + tagged = Replace[Times @@ Select[terms, ! FreeQ[#, Alternatives @@ pair] &], {q_NonCommutativeMultiply :> List @@ q, q_ :> {q}}]; - tagged = normalFactor[#, v, j, x] & /@ tagged; + tagged = normalFactor[#, pair, j, x] & /@ tagged; If[MemberQ[tagged, $Failed], Return[$Failed, Module]]; - (* The factors are assembled as one normally ordered product, so they must arrive - in that order: an antinormal product would otherwise be silently reordered and - keep its own scalar, which is wrong by the exponential of the commutator. *) - If[ ! OrderedQ[First /@ tagged /. {"Up" -> 1, "Diagonal" -> 2, "Down" -> 3}], + If[ ! OrderedQ[First /@ tagged /. {"Up" | "Creators" -> 1, "Diagonal" -> 2, "Down" | "Annihilators" -> 3}], Return[$Failed, Module] ]; u = Total[Cases[tagged, ("Up" -> c_) :> c]]; w = Total[Cases[tagged, ("Down" -> c_) :> c]]; + p = Total[Cases[tagged, ("Creators" -> c_) :> c]]; + q = Total[Cases[tagged, ("Annihilators" -> c_) :> c]]; + fu = x^p Exp[u]; + fd = x^q Exp[w]; f = Times @@ Cases[tagged, ("Diagonal" -> g_) :> g]; + mono = scalar KroneckerDelta[m - p, n - q] Sqrt[FactorialPower[m, p]] Sqrt[FactorialPower[n, q]] (f /. j -> n - q) &; r = Which[ - u === 0 && w === 0, scalar (f /. j -> n) KroneckerDelta[m, n], - w === 0, scalar wing[m, n, u, x] (f /. j -> n), - u === 0, scalar (f /. j -> m) wing[n, m, w, x], + coherent, + scalar (fu /. x -> Conjugate[m]) (fd /. x -> n) Exp[-(Abs[m]^2 + Abs[n]^2)/2] * + (Sum[f t^j/j!, {j, 0, Infinity}] /. t -> Conjugate[m] n), + fu === 1 && fd === 1, scalar (f /. j -> n) KroneckerDelta[m, n], + u === 0 && w === 0, + If[ IntegerQ[m] && IntegerQ[n], + If[m >= p && n >= q, mono[], 0], + Piecewise[{{mono[], m >= p && n >= q}}, 0] + ], + fd === 1, scalar wing[m, n, fu, x] (f /. j -> n), + fu === 1, scalar (f /. j -> m) wing[n, m, fd, x], IntegerQ[m] && IntegerQ[n], - scalar Sum[wing[m, j, u, x] f wing[n, j, w, x], {j, 0, Min[m, n]}], + scalar Sum[wing[m, j, fu, x] f wing[n, j, fd, x], {j, 0, Min[m, n]}], True, $Failed ]; If[FreeQ[r, SeriesCoefficient], r, $Failed] ] - -BosonicMatrixElement[{m_, n_}, expr_, opts : OptionsPattern[]] := - Module[{v = Replace[fieldVariables[expr, opts], {{u_} :> u, _ :> None}], j, t, r}, - r = Which[ - v === None || ListQ[m] || ListQ[n], $Failed, - (* summed in t before the amplitudes go in, so a zero amplitude meets no 0^j *) - coherentBasisQ[opts], - Replace[numberDiagonal[expr, v, j], - f : Except[$Failed] :> - Exp[-(Abs[m]^2 + Abs[n]^2)/2] (Sum[f t^j/j!, {j, 0, Infinity}] /. t -> Conjugate[m] n)], - True, - (* A mixed exponential is not yet a product of wings; disentangle and retry. *) - Replace[normalProductElement[expr, v, m, n, j], - $Failed /; ! FreeQ[expr, E] :> - normalProductElement[BosonicExpOrder[expr], v, m, n, j]] - ]; - r /; r =!= $Failed && FreeQ[expr, _QuantumOperator | _QuantumState] - ] diff --git a/QuantumFramework/Kernel/SecondQuantization/BosonicExp.m b/QuantumFramework/Kernel/SecondQuantization/BosonicExp.m index a36b713f..73d21f34 100644 --- a/QuantumFramework/Kernel/SecondQuantization/BosonicExp.m +++ b/QuantumFramework/Kernel/SecondQuantization/BosonicExp.m @@ -13,28 +13,30 @@ PackageExport["BosonicExpBraid"] -algA[v_] := algA[v] = NonCommutativeAlgebra[<|"Generators" -> {v, SuperDagger[v]}|>]; +ladderVars[lv_] := {lv["Creators"], lv["Annihilators"]} -algA[vars_List] := algA[vars] = NonCommutativeAlgebra[<|"Generators" -> vars|>]; +ladderPairs[lv_] := Transpose[ladderVars[lv]] -shiftPolynomialQ[expr_, v_] := - NonCommutativePolynomialQ[expr, algA[v]] && FreeQ[expr, Power[E, _?(! FreeQ[#, _?FormalSymbolQ] &)]]; +shiftPolynomialQ[expr_, lv_] := + NonCommutativePolynomialQ[expr, lv["Algebra"]] && FreeQ[expr, Power[E, _?(! FreeQ[#, Alternatives @@ lv["Generators"]] &)]]; -ladderRank[f_] := Which[ - FreeQ[f, SuperDagger], 3, - FreeQ[f /. SuperDagger[_?FormalSymbolQ] -> 1, _?FormalSymbolQ], 1, +ladderRank[lv_][f_] := Which[ + FreeQ[f, Alternatives @@ lv["Creators"]], 3, + FreeQ[f /. Thread[lv["Creators"] -> 1], Alternatives @@ lv["Annihilators"]], 1, True, 2 ]; -modeSwap[rank_] := NonCommutativeMultiply[l___, +ladderModes[lv_, f_] := Union @ Lookup[lv["Modes"], Cases[f, Alternatives @@ lv["Generators"], {0, Infinity}]] + +modeSwap[lv_, rank_] := NonCommutativeMultiply[l___, x : (_Power | _NormalOrdered | _AntinormalOrdered), y : (_Power | _NormalOrdered | _AntinormalOrdered), r___] /; - ! FreeQ[x, _?FormalSymbolQ] && ! FreeQ[y, _?FormalSymbolQ] && rank[x] > rank[y] && - DisjointQ @@ (DeleteDuplicates[Cases[#, w_?FormalSymbolQ :> w, {0, Infinity}]] & /@ {x, y}) :> + ! FreeQ[x, Alternatives @@ lv["Generators"]] && ! FreeQ[y, Alternatives @@ lv["Generators"]] && rank[x] > rank[y] && + DisjointQ[ladderModes[lv, x], ladderModes[lv, y]] :> NonCommutativeMultiply[l, y, x, r]; -modeMerge = NonCommutativeMultiply[l___, Power[E, x_], Power[E, y_], r___] /; - ! FreeQ[x, _?FormalSymbolQ] && ladderRank[x] === ladderRank[y] && ladderRank[x] =!= 2 && - SameQ @@ (Union[Cases[#, w_?FormalSymbolQ :> w, {0, Infinity}]] & /@ {x, y}) :> +modeMerge[lv_] := NonCommutativeMultiply[l___, Power[E, x_], Power[E, y_], r___] /; + ! FreeQ[x, Alternatives @@ lv["Generators"]] && ladderRank[lv][x] === ladderRank[lv][y] && ladderRank[lv][x] =!= 2 && + ladderModes[lv, x] === ladderModes[lv, y] :> NonCommutativeMultiply[l, Exp[x + y], r]; @@ -45,167 +47,173 @@ getNCPower[_, _] := 0; -thm44RHS[L_, R_, lambda_, v_] := +thm44RHS[L_, R_, lambda_, {cr_, an_}] := With[{e = L + R - 1}, - With[{adagE = If[e == 1, - SuperDagger[v], - GeneralizedPower[NonCommutativeMultiply, SuperDagger[v], e] - ]}, + With[{adagE = If[e == 1, cr, GeneralizedPower[NonCommutativeMultiply, cr, e]]}, (1 - e lambda adagE)^(-(R/e)) ** - Exp[((1 - e lambda adagE)^(-1/e) - 1) ** SuperDagger[v] ** v] + Exp[((1 - e lambda adagE)^(-1/e) - 1) ** cr ** an] ] ] -thm44ANRHS[L_, R_, lambda_, v_] := +thm44ANRHS[L_, R_, lambda_, {cr_, an_}] := With[{e = L + R - 1}, - With[{aE = If[e == 1, - v, - GeneralizedPower[NonCommutativeMultiply, v, e] - ]}, + With[{aE = If[e == 1, an, GeneralizedPower[NonCommutativeMultiply, an, e]]}, (1 + e lambda aE)^(-(R/e)) ** - Exp[(1 - (1 + e lambda aE)^(-1/e)) ** v ** SuperDagger[v]] + Exp[(1 - (1 + e lambda aE)^(-1/e)) ** an ** cr] ] ] -rulesNO = { - Exp[alpha_. SuperDagger[v_?FormalSymbolQ] + beta_. v_?FormalSymbolQ] :> - Exp[(alpha beta)/2] Exp[alpha SuperDagger[v]] ** Exp[beta v], +modeRulesNO[{cr_, an_}, vv_, lv_] := { + Exp[alpha_. cr + beta_. an] :> + Exp[(alpha beta)/2] Exp[alpha cr] ** Exp[beta an], - Exp[alpha_. v_?FormalSymbolQ] ** Exp[beta_. SuperDagger[v_?FormalSymbolQ]] :> - Exp[alpha beta] Exp[beta SuperDagger[v]] ** Exp[alpha v], + Exp[alpha_. an] ** Exp[beta_. cr] :> + Exp[alpha beta] Exp[beta cr] ** Exp[alpha an], - Exp[lambda_. SuperDagger[v_?FormalSymbolQ] ** v_?FormalSymbolQ] :> - NormalOrdered[Exp[(E^lambda - 1) SuperDagger[v] ** v]], + Exp[lambda_. cr ** an] :> + NormalOrdered[Exp[(E^lambda - 1) cr ** an], vv], - Exp[lambda_. v_?FormalSymbolQ ** SuperDagger[v_?FormalSymbolQ]] :> - E^lambda NormalOrdered[Exp[(E^lambda - 1) SuperDagger[v] ** v]], + Exp[lambda_. an ** cr] :> + E^lambda NormalOrdered[Exp[(E^lambda - 1) cr ** an], vv], - Exp[alpha_. (v_?FormalSymbolQ ** v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, 2])] ** - Exp[beta_. (SuperDagger[v_?FormalSymbolQ] ** SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], 2])] :> - Exp[(beta GeneralizedPower[NonCommutativeMultiply, SuperDagger[v], 2])/(1 - 4 alpha beta)] ** - Exp[-Log[1 - 4 alpha beta] SuperDagger[v] ** v] ** - Exp[(alpha GeneralizedPower[NonCommutativeMultiply, v, 2])/(1 - 4 alpha beta)] / Sqrt[1 - 4 alpha beta], + Exp[alpha_. (an ** an | GeneralizedPower[NonCommutativeMultiply, an, 2])] ** + Exp[beta_. (cr ** cr | GeneralizedPower[NonCommutativeMultiply, cr, 2])] :> + Exp[(beta GeneralizedPower[NonCommutativeMultiply, cr, 2])/(1 - 4 alpha beta)] ** + Exp[-Log[1 - 4 alpha beta] cr ** an] ** + Exp[(alpha GeneralizedPower[NonCommutativeMultiply, an, 2])/(1 - 4 alpha beta)] / Sqrt[1 - 4 alpha beta], - Exp[alpha_. (v_?FormalSymbolQ ** v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, 2]) + - beta_. (SuperDagger[v_?FormalSymbolQ] ** SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], 2])] :> + Exp[alpha_. (an ** an | GeneralizedPower[NonCommutativeMultiply, an, 2]) + + beta_. (cr ** cr | GeneralizedPower[NonCommutativeMultiply, cr, 2])] :> With[{omega = 2 Sqrt[alpha beta]}, - Exp[((beta Tan[omega]) GeneralizedPower[NonCommutativeMultiply, SuperDagger[v], 2])/omega] ** - Exp[Log[Sec[omega]] (1/2 + SuperDagger[v] ** v)] ** - Exp[((alpha Tan[omega]) GeneralizedPower[NonCommutativeMultiply, v, 2])/omega] + Exp[((beta Tan[omega]) GeneralizedPower[NonCommutativeMultiply, cr, 2])/omega] ** + Exp[Log[Sec[omega]] (1/2 + cr ** an)] ** + Exp[((alpha Tan[omega]) GeneralizedPower[NonCommutativeMultiply, an, 2])/omega] ], - Exp[alpha_. v_?FormalSymbolQ] ** expr_ /; shiftPolynomialQ[expr, v] :> - BosonicNormalOrder[expr /. {SuperDagger[v] -> SuperDagger[v] + alpha}, {v, SuperDagger[v]}] ** Exp[alpha v], + Exp[alpha_. an] ** expr_ /; shiftPolynomialQ[expr, lv] :> + BosonicNormalOrder[expr /. {cr -> cr + alpha}, vv] ** Exp[alpha an], - expr_ ** Exp[beta_. SuperDagger[v_?FormalSymbolQ]] /; shiftPolynomialQ[expr, v] :> - Exp[beta SuperDagger[v]] ** BosonicNormalOrder[expr /. {SuperDagger[v]-> SuperDagger[v], v -> v + beta}, {v, SuperDagger[v]}], + expr_ ** Exp[beta_. cr] /; shiftPolynomialQ[expr, lv] :> + Exp[beta cr] ** BosonicNormalOrder[expr /. {cr -> cr, an -> an + beta}, vv], - Exp[lambda_*(adagL : (SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], _])) ** - v_?FormalSymbolQ ** (adagR : (SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], _]))] :> - NormalOrdered @ thm44RHS[getNCPower[adagL, SuperDagger[v]], getNCPower[adagR, SuperDagger[v]], lambda, v], + Exp[lambda_*(adagL : (cr | GeneralizedPower[NonCommutativeMultiply, cr, _])) ** + an ** (adagR : (cr | GeneralizedPower[NonCommutativeMultiply, cr, _]))] :> + NormalOrdered[thm44RHS[getNCPower[adagL, cr], getNCPower[adagR, cr], lambda, {cr, an}], vv], - Exp[lambda_*v_?FormalSymbolQ ** (adagR : GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], _])] :> - NormalOrdered @ thm44RHS[0, getNCPower[adagR, SuperDagger[v]], lambda, v], + Exp[lambda_*an ** (adagR : GeneralizedPower[NonCommutativeMultiply, cr, _])] :> + NormalOrdered[thm44RHS[0, getNCPower[adagR, cr], lambda, {cr, an}], vv], - Exp[lambda_*(adagL : GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], _]) ** v_?FormalSymbolQ] :> - NormalOrdered @ thm44RHS[getNCPower[adagL, SuperDagger[v]], 0, lambda, v], + Exp[lambda_*(adagL : GeneralizedPower[NonCommutativeMultiply, cr, _]) ** an] :> + NormalOrdered[thm44RHS[getNCPower[adagL, cr], 0, lambda, {cr, an}], vv] +} - Exp[alpha_. SuperDagger[v1_?FormalSymbolQ] ** v2_?FormalSymbolQ + beta_. v1_?FormalSymbolQ ** SuperDagger[v2_?FormalSymbolQ]] /; v1 =!= v2 :> +pairRulesNO[{cr1_, an1_}, {cr2_, an2_}] := { + Exp[alpha_. cr1 ** an2 + beta_. an1 ** cr2] :> With[{Omega = Sqrt[alpha beta]}, - Exp[(alpha Tanh[Omega]/Omega) SuperDagger[v1] ** v2] ** - (Exp[-Log[Cosh[Omega]] SuperDagger[v1] ** v1] - Exp[Log[Cosh[Omega]] SuperDagger[v2] ** v2]) ** - Exp[(beta Tanh[Omega]/Omega) v1 ** SuperDagger[v2]] + Exp[(alpha Tanh[Omega]/Omega) cr1 ** an2] ** + (Exp[-Log[Cosh[Omega]] cr1 ** an1] + Exp[Log[Cosh[Omega]] cr2 ** an2]) ** + Exp[(beta Tanh[Omega]/Omega) an1 ** cr2] ], - Exp[alpha_. v1_?FormalSymbolQ ** v2_?FormalSymbolQ + beta_. SuperDagger[v1_?FormalSymbolQ] ** SuperDagger[v2_?FormalSymbolQ]] /; v1 =!= v2 :> + Exp[alpha_. an1 ** an2 + beta_. cr1 ** cr2] :> With[{Omega = Sqrt[alpha beta]}, - Sec[Omega] (Exp[(beta Tan[Omega]/Omega) SuperDagger[v1] ** SuperDagger[v2]] ** - Exp[Log[Sec[Omega]] (SuperDagger[v1] ** v1 + SuperDagger[v2] ** v2)] ** - Exp[(alpha Tan[Omega]/Omega) v1 ** v2]) - ], - - modeSwap[ladderRank], - - modeMerge -}; - + Sec[Omega] (Exp[(beta Tan[Omega]/Omega) cr1 ** cr2] ** + Exp[Log[Sec[Omega]] (cr1 ** an1 + cr2 ** an2)] ** + Exp[(alpha Tan[Omega]/Omega) an1 ** an2]) + ] +} -rulesAN = { - Exp[alpha_. SuperDagger[v_?FormalSymbolQ] + beta_. v_?FormalSymbolQ] :> - Exp[-(alpha beta)/2] Exp[beta v] ** Exp[alpha SuperDagger[v]], +modeRulesAN[{cr_, an_}, vv_, lv_] := { + Exp[alpha_. cr + beta_. an] :> + Exp[-(alpha beta)/2] Exp[beta an] ** Exp[alpha cr], - Exp[beta_. SuperDagger[v_?FormalSymbolQ]] ** Exp[alpha_. v_?FormalSymbolQ] :> - Exp[-alpha beta] Exp[alpha v] ** Exp[beta SuperDagger[v]], + Exp[beta_. cr] ** Exp[alpha_. an] :> + Exp[-alpha beta] Exp[alpha an] ** Exp[beta cr], - Exp[lambda_. v_?FormalSymbolQ ** SuperDagger[v_?FormalSymbolQ]] :> - AntinormalOrdered[Exp[(1 - E^(-lambda)) v ** SuperDagger[v]]], + Exp[lambda_. an ** cr] :> + AntinormalOrdered[Exp[(1 - E^(-lambda)) an ** cr], vv], - Exp[lambda_. SuperDagger[v_?FormalSymbolQ] ** v_?FormalSymbolQ] :> - E^(-lambda) AntinormalOrdered[Exp[(1 - E^(-lambda)) v ** SuperDagger[v]]], + Exp[lambda_. cr ** an] :> + E^(-lambda) AntinormalOrdered[Exp[(1 - E^(-lambda)) an ** cr], vv], - Exp[beta_. (SuperDagger[v_?FormalSymbolQ] ** SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], 2])] ** - Exp[alpha_. (v_?FormalSymbolQ ** v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, 2])] :> - Exp[(alpha GeneralizedPower[NonCommutativeMultiply, v, 2])/(1 - 4 alpha beta)] ** - Exp[Log[1 - 4 alpha beta] v ** SuperDagger[v]] ** - Exp[(beta GeneralizedPower[NonCommutativeMultiply, SuperDagger[v], 2])/(1 - 4 alpha beta)] / Sqrt[1 - 4 alpha beta], + Exp[beta_. (cr ** cr | GeneralizedPower[NonCommutativeMultiply, cr, 2])] ** + Exp[alpha_. (an ** an | GeneralizedPower[NonCommutativeMultiply, an, 2])] :> + Exp[(alpha GeneralizedPower[NonCommutativeMultiply, an, 2])/(1 - 4 alpha beta)] ** + Exp[Log[1 - 4 alpha beta] an ** cr] ** + Exp[(beta GeneralizedPower[NonCommutativeMultiply, cr, 2])/(1 - 4 alpha beta)] / Sqrt[1 - 4 alpha beta], - Exp[alpha_. (v_?FormalSymbolQ ** v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, 2]) + - beta_. (SuperDagger[v_?FormalSymbolQ] ** SuperDagger[v_?FormalSymbolQ] | GeneralizedPower[NonCommutativeMultiply, SuperDagger[v_?FormalSymbolQ], 2])] :> + Exp[alpha_. (an ** an | GeneralizedPower[NonCommutativeMultiply, an, 2]) + + beta_. (cr ** cr | GeneralizedPower[NonCommutativeMultiply, cr, 2])] :> With[{omega = 2 Sqrt[alpha beta]}, - Exp[((alpha Tan[omega]) GeneralizedPower[NonCommutativeMultiply, v, 2])/omega] ** - Exp[Log[Sec[omega]] (1/2 - v ** SuperDagger[v])] ** - Exp[((beta Tan[omega]) GeneralizedPower[NonCommutativeMultiply, SuperDagger[v], 2])/omega] + Exp[((alpha Tan[omega]) GeneralizedPower[NonCommutativeMultiply, an, 2])/omega] ** + Exp[Log[Sec[omega]] (1/2 - an ** cr)] ** + Exp[((beta Tan[omega]) GeneralizedPower[NonCommutativeMultiply, cr, 2])/omega] ], - expr_ ** Exp[alpha_. v_?FormalSymbolQ] /; shiftPolynomialQ[expr, v] :> - Exp[alpha v] ** BosonicAntinormalOrder[expr /. {SuperDagger[v] -> SuperDagger[v] - alpha}, {v, SuperDagger[v]}], + expr_ ** Exp[alpha_. an] /; shiftPolynomialQ[expr, lv] :> + Exp[alpha an] ** BosonicAntinormalOrder[expr /. {cr -> cr - alpha}, vv], - Exp[beta_. SuperDagger[v_?FormalSymbolQ]] ** expr_ /; shiftPolynomialQ[expr, v] :> - BosonicAntinormalOrder[expr /. {SuperDagger[v] -> SuperDagger[v], v -> v - beta}, {v, SuperDagger[v]}] ** Exp[beta SuperDagger[v]], + Exp[beta_. cr] ** expr_ /; shiftPolynomialQ[expr, lv] :> + BosonicAntinormalOrder[expr /. {cr -> cr, an -> an - beta}, vv] ** Exp[beta cr], - Exp[lambda_*(aL : (v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, _])) ** - SuperDagger[v_?FormalSymbolQ] ** (aR : (v_?FormalSymbolQ | GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, _]))] :> - AntinormalOrdered @ thm44ANRHS[getNCPower[aL, v], getNCPower[aR, v], lambda, v], + Exp[lambda_*(aL : (an | GeneralizedPower[NonCommutativeMultiply, an, _])) ** + cr ** (aR : (an | GeneralizedPower[NonCommutativeMultiply, an, _]))] :> + AntinormalOrdered[thm44ANRHS[getNCPower[aL, an], getNCPower[aR, an], lambda, {cr, an}], vv], - Exp[lambda_*SuperDagger[v_?FormalSymbolQ] ** (aR : GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, _])] :> - AntinormalOrdered @ thm44ANRHS[0, getNCPower[aR, v], lambda, v], + Exp[lambda_*cr ** (aR : GeneralizedPower[NonCommutativeMultiply, an, _])] :> + AntinormalOrdered[thm44ANRHS[0, getNCPower[aR, an], lambda, {cr, an}], vv], - Exp[lambda_*(aL : GeneralizedPower[NonCommutativeMultiply, v_?FormalSymbolQ, _]) ** SuperDagger[v_?FormalSymbolQ]] :> - AntinormalOrdered @ thm44ANRHS[getNCPower[aL, v], 0, lambda, v], + Exp[lambda_*(aL : GeneralizedPower[NonCommutativeMultiply, an, _]) ** cr] :> + AntinormalOrdered[thm44ANRHS[getNCPower[aL, an], 0, lambda, {cr, an}], vv] +} - Exp[alpha_. SuperDagger[v1_?FormalSymbolQ] ** v2_?FormalSymbolQ + beta_. v1_?FormalSymbolQ ** SuperDagger[v2_?FormalSymbolQ]] /; v1 =!= v2 :> +pairRulesAN[{cr1_, an1_}, {cr2_, an2_}] := { + Exp[alpha_. cr1 ** an2 + beta_. an1 ** cr2] :> With[{Omega = Sqrt[alpha beta]}, - Exp[(beta Tanh[Omega]/Omega) v1 ** SuperDagger[v2]] ** - (Exp[Log[Cosh[Omega]] v1 ** SuperDagger[v1]] - Exp[-Log[Cosh[Omega]] v2 ** SuperDagger[v2]]) ** - Exp[(alpha Tanh[Omega]/Omega) SuperDagger[v1] ** v2] + Exp[(beta Tanh[Omega]/Omega) an1 ** cr2] ** + (Exp[Log[Cosh[Omega]] an1 ** cr1] + Exp[-Log[Cosh[Omega]] an2 ** cr2]) ** + Exp[(alpha Tanh[Omega]/Omega) cr1 ** an2] ], - Exp[alpha_. v1_?FormalSymbolQ ** v2_?FormalSymbolQ + beta_. SuperDagger[v1_?FormalSymbolQ] ** SuperDagger[v2_?FormalSymbolQ]] /; v1 =!= v2 :> + Exp[alpha_. an1 ** an2 + beta_. cr1 ** cr2] :> With[{Omega = Sqrt[alpha beta]}, - Sec[Omega] (Exp[(alpha Tan[Omega]/Omega) v1 ** v2] ** - Exp[-Log[Sec[Omega]] (v1 ** SuperDagger[v1] + v2 ** SuperDagger[v2])] ** - Exp[(beta Tan[Omega]/Omega) SuperDagger[v1] ** SuperDagger[v2]]) - ], + Sec[Omega] (Exp[(alpha Tan[Omega]/Omega) an1 ** an2] ** + Exp[-Log[Sec[Omega]] (an1 ** cr1 + an2 ** cr2)] ** + Exp[(beta Tan[Omega]/Omega) cr1 ** cr2]) + ] +} - modeSwap[4 - ladderRank[#] &], - modeMerge -}; +expRules[lv_, "Normal"] := expRules[lv, "Normal"] = Join[ + Flatten @ Transpose[modeRulesNO[#, ladderVars[lv], lv] & /@ ladderPairs[lv]], + Flatten[pairRulesNO @@@ Permutations[ladderPairs[lv], {2}]], + {modeSwap[lv, ladderRank[lv]], modeMerge[lv]} +] +expRules[lv_, "Antinormal"] := expRules[lv, "Antinormal"] = Join[ + Flatten @ Transpose[modeRulesAN[#, ladderVars[lv], lv] & /@ ladderPairs[lv]], + Flatten[pairRulesAN @@@ Permutations[ladderPairs[lv], {2}]], + {modeSwap[lv, 4 - ladderRank[lv][#] &], modeMerge[lv]} +] -canonicalizeGenerators[expr_] := - (expr /. Exp[g_] :> Exp[Expand[g]]) //. NonCommutativeMultiply[ - a___, - x : (mx_?FormalSymbolQ | SuperDagger[mx_?FormalSymbolQ]), - y : (my_?FormalSymbolQ | SuperDagger[my_?FormalSymbolQ]), - b___ - ] /; mx =!= my && !OrderedQ[{mx, my}] :> - NonCommutativeMultiply[a, y, x, b] + +exponentTerm[t_, g_] := + With[{f = Replace[t, {u_Times :> List @@ u, u_ :> {u}}]}, + Times @@ Select[f, ! FreeQ[#, g] &] -> Times @@ Select[f, FreeQ[#, g] &] + ] + +canonicalizeGenerators[expr_, lv_] := + With[{g = Alternatives @@ lv["Generators"]}, + (expr /. Exp[e_] :> Exp[Total @ KeyValueMap[#1 #2 &, + GroupBy[exponentTerm[#, g] & /@ Replace[Expand[e], {s_Plus :> List @@ s, s_ :> {s}}], First -> Last, Total]]]) //. + NonCommutativeMultiply[l___, x : g, y : g, r___] /; lv["Modes"][x] > lv["Modes"][y] :> + NonCommutativeMultiply[l, y, x, r] + ] @@ -218,115 +226,135 @@ ladderMonomial[adag_, 0, a_, k_] := ladderPower[a, k] ladderMonomial[adag_, m_, a_, k_] := ladderPower[adag, m] ** ladderPower[a, k] -orderedMonomial[NormalOrdered, v_, {m_, k_}] := ladderMonomial[SuperDagger[v], m, v, k] -orderedMonomial[AntinormalOrdered, v_, {m_, k_}] := ladderMonomial[v, k, SuperDagger[v], m] +orderedMonomial[NormalOrdered, {cr_, an_}, {m_, k_}] := ladderMonomial[cr, m, an, k] +orderedMonomial[AntinormalOrdered, {cr_, an_}, {m_, k_}] := ladderMonomial[an, k, cr, m] MakeBoxes[SeriesIndex[s_String], StandardForm] ^:= InterpretationBox[s, SeriesIndex[s]] MakeBoxes[SeriesIndex[s_String], TraditionalForm] ^:= InterpretationBox[s, SeriesIndex[s]] -expSeriesTerm[ord_, coeff_, v_] := With[{k = SeriesIndex["k"]}, +expSeriesTerm[ord_, coeff_, pair_] := With[{k = SeriesIndex["k"]}, Inactivate[Sum[ - (coeff^k/k!) orderedMonomial[ord, v, {k, k}], + (coeff^k/k!) orderedMonomial[ord, pair, {k, k}], {k, 0, Infinity} ], Sum] ] -NormalOrdered /: Times[c_, NormalOrdered[expr_]] /; FreeQ[c, _?FormalSymbolQ] := NormalOrdered[c expr] +NormalOrdered::usage = +"\!\(\*RowBox[{\"NormalOrdered\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) represents the normal-ordered product :expr: in the ladder operators vars."; + +AntinormalOrdered::usage = +"\!\(\*RowBox[{\"AntinormalOrdered\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) represents the anti-normal-ordered product of expr in the ladder operators vars."; -AntinormalOrdered /: Times[c_, AntinormalOrdered[expr_]] /; FreeQ[c, _?FormalSymbolQ] := AntinormalOrdered[c expr] +NormalOrdered /: Times[s_, NormalOrdered[expr_, vars_]] := + With[{lv = ResolveLadderVariables[NormalOrdered, vars]}, + NormalOrdered[s expr, vars] /; AssociationQ[lv] && FreeQ[s, Alternatives @@ lv["Generators"]] + ] +AntinormalOrdered /: Times[s_, AntinormalOrdered[expr_, vars_]] := + With[{lv = ResolveLadderVariables[AntinormalOrdered, vars]}, + AntinormalOrdered[s expr, vars] /; AssociationQ[lv] && FreeQ[s, Alternatives @@ lv["Generators"]] + ] -NormalOrdered[expr_]["Series"] := expr /. { - Exp[c_. + coeff_ SuperDagger[v_] ** v_] /; FreeQ[c, _?FormalSymbolQ] :> - Exp[c] expSeriesTerm[NormalOrdered, coeff, v] -} -AntinormalOrdered[expr_]["Series"] := expr /. { - Exp[c_. + coeff_ v_?FormalSymbolQ ** SuperDagger[v_?FormalSymbolQ]] /; FreeQ[c, _?FormalSymbolQ] :> - Exp[c] expSeriesTerm[AntinormalOrdered, coeff, v] -} +NormalOrdered[expr_, vars_]["Series"] := + With[{lv = ResolveLadderVariables[NormalOrdered, vars]}, + (expr /. ((Exp[s_. + coeff_ #1 ** #2] /; FreeQ[s, Alternatives @@ lv["Generators"]] :> + Exp[s] expSeriesTerm[NormalOrdered, coeff, {#1, #2}]) & @@@ ladderPairs[lv])) /; AssociationQ[lv] + ] + +AntinormalOrdered[expr_, vars_]["Series"] := + With[{lv = ResolveLadderVariables[AntinormalOrdered, vars]}, + (expr /. ((Exp[s_. + coeff_ #2 ** #1] /; FreeQ[s, Alternatives @@ lv["Generators"]] :> + Exp[s] expSeriesTerm[AntinormalOrdered, coeff, {#1, #2}]) & @@@ ladderPairs[lv])) /; AssociationQ[lv] + ] -dequantizeLadder[expr_, v_, x_, y_] := expr //. { +dequantizeLadder[expr_, {cr_, an_}, x_, y_] := expr //. { GeneralizedPower[NonCommutativeMultiply, op_, p_] :> op^p, - SuperDagger[v] -> x, - v -> y, + cr -> x, + an -> y, NonCommutativeMultiply -> Times } -ladderMode[expr_] := - Replace[ - DeleteDuplicates[ExtractNCVars[{expr}] /. SuperDagger[w_] :> w], - {{v_} :> v, _ :> None} - ] +ladderMode[expr_, lv_] := + Replace[Select[ladderPairs[lv], ! FreeQ[expr, Alternatives @@ #] &], {{p_} :> p, _ :> None}] -orderedSeries[ord_, expr_, lambda_] := Module[{v, x, y, n, coefN}, - v = ladderMode[expr]; +orderedSeries[ord_, expr_, lambda_, lv_] := Module[{v, x, y, n, coefN}, + v = ladderMode[expr, lv]; If[v === None, Return[$Failed, Module]]; n = SeriesIndex["n"]; coefN = SeriesCoefficient[dequantizeLadder[expr, v, x, y], {lambda, 0, n}]; coefN = coefN /. Piecewise[{{val_, _}}, _] :> val; - ord @ Inactivate[ - Sum[lambda^n (coefN /. {x -> SuperDagger[v], y -> v}), {n, 0, Infinity}], - Sum + ord[ + Inactivate[Sum[lambda^n (coefN /. {x -> First[v], y -> Last[v]}), {n, 0, Infinity}], Sum], + ladderVars[lv] ] ] -NormalOrdered[expr_]["Series", lambda_Symbol] := orderedSeries[NormalOrdered, expr, lambda] +NormalOrdered[expr_, vars_]["Series", lambda_Symbol] := + With[{lv = ResolveLadderVariables[NormalOrdered, vars]}, orderedSeries[NormalOrdered, expr, lambda, lv] /; AssociationQ[lv]] -AntinormalOrdered[expr_]["Series", lambda_Symbol] := orderedSeries[AntinormalOrdered, expr, lambda] +AntinormalOrdered[expr_, vars_]["Series", lambda_Symbol] := + With[{lv = ResolveLadderVariables[AntinormalOrdered, vars]}, orderedSeries[AntinormalOrdered, expr, lambda, lv] /; AssociationQ[lv]] -orderedSeriesOrder[ord_, expr_, lambda_, order_] := Module[{v, x, y}, - v = ladderMode[expr]; +orderedSeriesOrder[ord_, expr_, lambda_, order_, lv_] := Module[{v, x, y}, + v = ladderMode[expr, lv]; If[v === None, Return[$Failed, Module]]; ord[ - Normal @ Series[dequantizeLadder[expr, v, x, y], {lambda, 0, order}] /. - {x -> SuperDagger[v], y -> v} + Normal @ Series[dequantizeLadder[expr, v, x, y], {lambda, 0, order}] /. {x -> First[v], y -> Last[v]}, + ladderVars[lv] ] ] -NormalOrdered[expr_]["Series", lambda_Symbol, order_Integer] := - orderedSeriesOrder[NormalOrdered, expr, lambda, order] +NormalOrdered[expr_, vars_]["Series", lambda_Symbol, order_Integer] := + With[{lv = ResolveLadderVariables[NormalOrdered, vars]}, orderedSeriesOrder[NormalOrdered, expr, lambda, order, lv] /; AssociationQ[lv]] -AntinormalOrdered[expr_]["Series", lambda_Symbol, order_Integer] := - orderedSeriesOrder[AntinormalOrdered, expr, lambda, order] +AntinormalOrdered[expr_, vars_]["Series", lambda_Symbol, order_Integer] := + With[{lv = ResolveLadderVariables[AntinormalOrdered, vars]}, orderedSeriesOrder[AntinormalOrdered, expr, lambda, order, lv] /; AssociationQ[lv]] -ncMonomials[ord_, expr_, v_] := Module[{x, y}, +ncMonomials[ord_, expr_, pair_] := Module[{x, y}, Total[ - (#[[2]] orderedMonomial[ord, v, #[[1]]]) & /@ - CoefficientRules[Expand[dequantizeLadder[expr, v, x, y]], {x, y}] + (#[[2]] orderedMonomial[ord, pair, #[[1]]]) & /@ + CoefficientRules[Expand[dequantizeLadder[expr, pair, x, y]], {x, y}] ] ] -ladderPolynomialQ[expr_] := Module[{v = ladderMode[expr], x, y}, - v =!= None && PolynomialQ[dequantizeLadder[expr, v, x, y], {x, y}] -] +ladderPolynomialQ[expr_, pair_] := + Module[{x, y}, + With[{d = dequantizeLadder[expr, pair, x, y]}, + PolynomialQ[d, {x, y}] && AllTrue[Variables[d], MatchQ[#, x | y] || FreeQ[#, x | y] &] + ] + ] -NormalOrdered[expr_] /; ladderPolynomialQ[expr] := - ncMonomials[NormalOrdered, expr, ladderMode[expr]] +NormalOrdered[expr_, vars_] := + With[{p = Replace[Quiet @ ResolveLadderVariables[NormalOrdered, vars], {lv_Association :> ladderMode[expr, lv], _ -> None}]}, + ncMonomials[NormalOrdered, expr, p] /; p =!= None && ladderPolynomialQ[expr, p] + ] -AntinormalOrdered[expr_] /; ladderPolynomialQ[expr] := - ncMonomials[AntinormalOrdered, expr, ladderMode[expr]] +AntinormalOrdered[expr_, vars_] := + With[{p = Replace[Quiet @ ResolveLadderVariables[AntinormalOrdered, vars], {lv_Association :> ladderMode[expr, lv], _ -> None}]}, + ncMonomials[AntinormalOrdered, expr, p] /; p =!= None && ladderPolynomialQ[expr, p] + ] -expApplyRules[expr_, assum_, rules_] := +expApplyRules[expr_, assum_, rules_, lv_] := Assuming[assum, Simplify[ FixedPoint[ (# /. Prepend[rules, n : (_NormalOrdered | _AntinormalOrdered) :> n]) //. - (NonCommutativeMultiply[l___, Times[c_, m_NonCommutativeMultiply], r___] /; FreeQ[c, _?FormalSymbolQ] :> - c NonCommutativeMultiply[l, m, r]) &, - canonicalizeGenerators[expr] + (NonCommutativeMultiply[l___, Times[s_, m_NonCommutativeMultiply], r___] /; FreeQ[s, Alternatives @@ lv["Generators"]] :> + s NonCommutativeMultiply[l, m, r]) &, + canonicalizeGenerators[expr, lv] ], ExcludedForms -> _GeneralizedPower ] @@ -334,38 +362,44 @@ BosonicExpOrder::usage = -"\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", StyleBox[\"expr\", \"TI\"], \"]\"}]\) brings an expression built from exponentials of a formal field variable (e.g. \[FormalA]) and its \!\(\*RowBox[{StyleBox[\"var\", \"TI\"], SuperscriptBox[\"\[Dagger]\", \"\"]}]\) into normal order, using the boson disentangling identities.\n\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", \"\\\"Ordering\\\"->\", \"\\\"Antinormal\\\"\"}], \"]\"}]\) brings expr into anti-normal order, with every annihilation operator to the left of every creation operator.\n\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"assum\", \"TI\"]}], \"]\"}]\) uses \!\(\*StyleBox[\"assum\", \"TI\"]\) as additional simplifying assumptions.\n\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", RowBox[{\[Ellipsis], \",\", \"TimeConstraint->\", StyleBox[\"t\", \"TI\"]}], \"]\"}]\) limits simplification to \!\(\*StyleBox[\"t\", \"TI\"]\) seconds (default 30)."; +"\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) brings a product of exponentials of the ladder operators vars into normal order.\n\!\(\*RowBox[{\"BosonicExpOrder\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Ordering\\\"->\", \"\\\"Antinormal\\\"\"}], \"]\"}]\) brings it into anti-normal order."; BosonicExpOrder::ordering = "`1` is not a valid setting for \"Ordering\"; use \"Normal\" or \"Antinormal\"." +BosonicExpOrder::assum = "`1` reads as assumptions rather than ladder operators; give the ladder operators second and the assumptions as Assumptions -> `1`." + Options[BosonicExpOrder] = { "Ordering" -> "Normal", TimeConstraint -> 30, Assumptions -> $Assumptions }; -BosonicExpOrder[expr_, opts : OptionsPattern[]] := BosonicExpOrder[expr, True, opts] - -BosonicExpOrder[expr_, assum_, opts : OptionsPattern[]] := - Block[{tmax = OptionValue[TimeConstraint], fullAssum}, - fullAssum = Union[Flatten[{assum}], Flatten[{OptionValue[Assumptions]}]]; - Replace[OptionValue["Ordering"], { - "Normal" :> - TimeConstrained[expApplyRules[expr, fullAssum, rulesNO], tmax, expr], - "Antinormal" :> - TimeConstrained[expApplyRules[expr, fullAssum, rulesAN], tmax, expr], - other_ :> (Message[BosonicExpOrder::ordering, other]; $Failed) - }] +BosonicExpOrder[expr_, opts : OptionsPattern[]] := (Message[BosonicExpOrder::argr, BosonicExpOrder, 2]; $Failed) + +With[{p = True | False | _Greater | _GreaterEqual | _Less | _LessEqual | _Equal | _Unequal | _Element | _NotElement | _And | _Or}, + BosonicExpOrder[expr_, assum : (p | {p ..}), OptionsPattern[]] := (Message[BosonicExpOrder::assum, assum]; $Failed) +] + +BosonicExpOrder[expr_, vars_, opts : OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicExpOrder, vars]}, + If[ lv === $Failed, + $Failed, + Replace[OptionValue["Ordering"], { + ord : "Normal" | "Antinormal" :> + TimeConstrained[expApplyRules[expr, OptionValue[Assumptions], expRules[lv, ord], lv], OptionValue[TimeConstraint], expr], + other_ :> (Message[BosonicExpOrder::ordering, other]; $Failed) + }] + ] ] BosonicExpSimplify::usage = -"\!\(\*RowBox[{\"BosonicExpSimplify\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) simplifies a product of exponentials, or a conjugation by an exponential, of the bosonic operators vars, returning a closed form when the algebra closes and expr unchanged otherwise.\n\!\(\*RowBox[{\"BosonicExpSimplify\", \"[\", StyleBox[\"expr\", \"TI\"], \"]\"}]\) detects the non-commutative variables and scalars appearing in expr.\n\!\(\*RowBox[{\"BosonicExpSimplify\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Scalars\\\"->\", StyleBox[\"syms\", \"TI\"]}], \"]\"}]\) treats syms as commuting scalars.\n\!\(\*RowBox[{\"BosonicExpSimplify\", \"[\", RowBox[{\[Ellipsis], \",\", \"Assumptions->\", StyleBox[\"assum\", \"TI\"]}], \"]\"}]\) uses \!\(\*StyleBox[\"assum\", \"TI\"]\) as simplifying assumptions while reducing."; +"\!\(\*RowBox[{\"BosonicExpSimplify\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) simplifies products of exponentials and functions of number operators in the ladder operators vars."; -Options[BosonicExpSimplify] = {"Scalars" -> {}, Assumptions :> $Assumptions}; +Options[BosonicExpSimplify] = {Assumptions :> $Assumptions}; -ncPolyQ[exprs_List, vars_] := - AllTrue[exprs, NonCommutativePolynomialQ[#, algA[vars]] && vevPolynomialQ[#, vars] &] +ncPolyQ[exprs_List, lv_] := + AllTrue[exprs, NonCommutativePolynomialQ[#, lv["Algebra"]] && vevPolynomialQ[#, lv["Generators"]] &] ncJoin[xs___] := ncJoinList @ DeleteCases[{xs}, 1] @@ -378,28 +412,25 @@ inverseExponentsQ[b_, c_] := TrueQ[Simplify[b + c] == 0] -ncCommutator[a_, b_, vars_, scalars_] := - ncCommutator[a, b, vars, scalars, $Assumptions] +ncCommutator[a_, b_, lv_] := + ncCommutator[a, b, lv, $Assumptions] -ncCommutator[a_, b_, vars_, scalars_, assum_] := - ncCommutator[a, b, vars, scalars, assum] = - Simplify[ - BosonicNormalOrder[Commutator[a, b], vars, "Scalars" -> scalars], - assum - ] +ncCommutator[a_, b_, lv_, assum_] := + ncCommutator[a, b, lv, assum] = + Simplify[BosonicNormalOrder[Commutator[a, b], ladderVars[lv]], assum] -adRotate[op_, cmt_, lam_, vars_] /; cNumberQ[lam, vars] := +adRotate[op_, cmt_, lam_, lv_] /; cNumberQ[lam, lv["Generators"]] := With[{w = I Sqrt[lam]}, Simplify[Cos[w] op + Sin[w] / w cmt] /. $nonuls] adRotate[___] := $Failed -adAction[b_, op_, vars_, scalars_] := - With[{cmt = ncCommutator[b, op, vars, scalars]}, - With[{cmt2 = ncCommutator[b, cmt, vars, scalars]}, +adAction[b_, op_, lv_] := + With[{cmt = ncCommutator[b, op, lv]}, + With[{cmt2 = ncCommutator[b, cmt, lv]}, Which[ - cmt === 0, op, - cNumberQ[cmt, vars] || zeroQ[cmt2], op + cmt, - True, adRotate[op, cmt, Simplify[cmt2 / op], vars] + cmt === 0, op, + cNumberQ[cmt, lv["Generators"]] || zeroQ[cmt2], op + cmt, + True, adRotate[op, cmt, Simplify[cmt2 / op], lv] ] ] ] @@ -407,130 +438,169 @@ expOrFailed[$Failed] := $Failed expOrFailed[h_] := Exp[h] -expConjugate[b_, Exp[g_], vars_, scalars_] /; ncPolyQ[{b, g}, vars] := - expOrFailed @ adAction[b, g, vars, scalars] +expConjugate[b_, Exp[g_], lv_] /; ncPolyQ[{b, g}, lv] := + expOrFailed @ adAction[b, g, lv] -expConjugate[b_, op_, vars_, scalars_] /; ncPolyQ[{b, op}, vars] := - adAction[b, op, vars, scalars] +expConjugate[b_, op_, lv_] /; ncPolyQ[{b, op}, lv] := + Replace[adAction[b, op, lv], $Failed :> conjugateParts[b, op, lv]] expConjugate[___] := $Failed -expReduceRules[vars_, scalars_] := { +conjugateParts[b_, op_Plus, lv_] := + With[{gs = expConjugate[b, #, lv] & /@ List @@ op}, If[MemberQ[gs, $Failed], $Failed, Total[gs]]] + +conjugateParts[b_, op_Times, lv_] := + With[{s = Select[op, FreeQ[#, Alternatives @@ lv["Generators"]] &]}, + If[s === 1, $Failed, Replace[expConjugate[b, op / s, lv], g : Except[$Failed] :> s g]] + ] + +conjugateParts[b_, op_NonCommutativeMultiply, lv_] := + With[{gs = expConjugate[b, #, lv] & /@ List @@ op}, If[MemberQ[gs, $Failed], $Failed, NonCommutativeMultiply @@ gs]] + +conjugateParts[b_, GeneralizedPower[NonCommutativeMultiply, x_, n_Integer ? Positive], lv_] := + Replace[expConjugate[b, x, lv], g : Except[$Failed] :> GeneralizedPower[NonCommutativeMultiply, g, n]] + +conjugateParts[___] := $Failed + +numberFunctionQ[f_, {cr_, an_}] := Module[{k}, ! FreeQ[f, cr ** an] && FreeQ[f /. cr ** an -> k, cr | an]] + +balancedWordQ[w_List, {cr_, an_}] := + MatchQ[w, {(cr | an | GeneralizedPower[NonCommutativeMultiply, cr | an, _Integer ? Positive]) ..}] && + Total[getNCPower[#, cr] - getNCPower[#, an] & /@ w] == 0 + +numberPolynomial[w_List, {cr_, an_}] := + BosonicNormalOrder[NonCommutativeMultiply @@ w, {{cr}, {an}}] /. + GeneralizedPower[NonCommutativeMultiply, cr, k_] ** GeneralizedPower[NonCommutativeMultiply, an, k_] :> + Product[cr ** an - j, {j, 0, k - 1}] + +(* a^q f(N) = f(N + q) a^q and f(N) ad^p = ad^p f(N + p), and functions of one N commute. + A word with as many ad as a beside a function of N is itself a polynomial in N, ad^k a^k + = N (N - 1) ... (N - k + 1). Ladder powers only move outward, never into ad f(N) a = N f(N - 1), + whose cancellation would lose the vacuum. *) +shiftRules[{cr_, an_}] := { + NonCommutativeMultiply[l___, f_, w__, r___] /; numberFunctionQ[f, {cr, an}] && balancedWordQ[{w}, {cr, an}] :> + ncJoin[l, Together[f numberPolynomial[{w}, {cr, an}]], r], + NonCommutativeMultiply[l___, w__, f_, r___] /; numberFunctionQ[f, {cr, an}] && balancedWordQ[{w}, {cr, an}] :> + ncJoin[l, Together[numberPolynomial[{w}, {cr, an}] f], r], + NonCommutativeMultiply[l___, f_, g_, r___] /; numberFunctionQ[f, {cr, an}] && numberFunctionQ[g, {cr, an}] :> + ncJoin[l, Together[f g], r], + NonCommutativeMultiply[l___, x : (an | GeneralizedPower[NonCommutativeMultiply, an, _Integer ? Positive]), f_, r___] /; + numberFunctionQ[f, {cr, an}] :> + ncJoin[l, f /. cr ** an -> cr ** an + getNCPower[x, an], x, r], + NonCommutativeMultiply[l___, f_, x : (cr | GeneralizedPower[NonCommutativeMultiply, cr, _Integer ? Positive]), r___] /; + numberFunctionQ[f, {cr, an}] :> + ncJoin[l, x, f /. cr ** an -> cr ** an + getNCPower[x, cr], r] +} + +expReduceRules[lv_] := Join[{ NonCommutativeMultiply[l___, 1, r___] :> ncJoin[l, r], NonCommutativeMultiply[l___, Exp[b_], mid_, Exp[c_], r___] /; inverseExponentsQ[b, c] :> - With[{g = expConjugate[b, mid, vars, scalars]}, + With[{g = expConjugate[b, mid, lv]}, ncJoin[l, g, r] /; g =!= $Failed ], NonCommutativeMultiply[l___, Exp[b_], mid__, Exp[c_], r___] /; Length[{mid}] > 1 && inverseExponentsQ[b, c] :> - With[{gs = expConjugate[b, #, vars, scalars] & /@ {mid}}, + With[{gs = expConjugate[b, #, lv] & /@ {mid}}, ncJoin[l, ##, r] & @@ gs /; FreeQ[gs, $Failed] ], - NonCommutativeMultiply[l___, Exp[b1_], Exp[b2_], r___] /; ncPolyQ[{b1, b2}, vars] :> - With[{c = ncCommutator[b1, b2, vars, scalars]}, - ncJoin[l, Exp[c / 2] Exp[b1 + b2], r] /; cNumberQ[c, vars] + NonCommutativeMultiply[l___, Exp[b1_], Exp[b2_], r___] /; ncPolyQ[{b1, b2}, lv] :> + With[{c = ncCommutator[b1, b2, lv]}, + ncJoin[l, Exp[c / 2] Exp[Expand[b1 + b2]], r] /; cNumberQ[c, lv["Generators"]] ], - NonCommutativeMultiply[l___, op_, Exp[b_], r___] /; ncPolyQ[{op, b}, vars] :> - With[{cmt = ncCommutator[b, op, vars, scalars]}, - With[{cmt2 = ncCommutator[b, cmt, vars, scalars]}, + NonCommutativeMultiply[l___, op_, Exp[b_], r___] /; ncPolyQ[{op, b}, lv] :> + With[{cmt = ncCommutator[b, op, lv]}, + With[{cmt2 = ncCommutator[b, cmt, lv]}, ncJoin[l, Exp[b], op - cmt, r] /; zeroQ[cmt2] ] ] -} +}, Catenate[shiftRules /@ ladderPairs[lv]]] -BosonicExpSimplify[expr_, {}, OptionsPattern[]] := expr +BosonicExpSimplify[expr_, opts : OptionsPattern[]] := (Message[BosonicExpSimplify::argr, BosonicExpSimplify, 2]; $Failed) -BosonicExpSimplify[expr_, opts : OptionsPattern[]] := - With[{ - vars = ExtractNCVars[{expr}], - scalars = DeleteDuplicates @ Cases[{expr}, - s_Symbol /; ! FormalSymbolQ[s] && ! NumericQ[s], Infinity] - }, - BosonicExpSimplify[expr, vars, opts, "Scalars" -> scalars] - ] - -BosonicExpSimplify[expr_, vars_List, opts : OptionsPattern[]] := - With[{assum = OptionValue[Assumptions], scalars = OptionValue["Scalars"]}, - Assuming[assum, expr //. expReduceRules[vars, scalars]] +BosonicExpSimplify[expr_, vars_, opts : OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicExpSimplify, vars]}, + If[lv === $Failed, $Failed, Assuming[OptionValue[Assumptions], expr //. expReduceRules[lv]]] ] -adFamilyRules[cr_, v_, vars_] /; ! FreeQ[Values[cr], Alternatives @@ vars] := $Failed +adFamilyRules[cr_, _, gens_] /; ! FreeQ[Values[cr], Alternatives @@ gens] := $Failed -adFamilyRules[cr_, v_, vars_] /; Keys[cr] === {{1, 1}} := +adFamilyRules[cr_, {cre_, ann_}, _] /; Keys[cr] === {{1, 1}} := With[{lam = Lookup[cr, Key[{1, 1}]]}, - {SuperDagger[v] -> Exp[lam] SuperDagger[v], v -> Exp[-lam] v} + {cre -> Exp[lam] cre, ann -> Exp[-lam] ann} ] -adFamilyRules[cr_, v_, vars_] /; SubsetQ[{{1, 0}, {0, 1}}, Keys[cr]] := +adFamilyRules[cr_, {cre_, ann_}, _] /; SubsetQ[{{1, 0}, {0, 1}}, Keys[cr]] := With[{mu = Lookup[cr, Key[{1, 0}], 0], nu = Lookup[cr, Key[{0, 1}], 0]}, - {SuperDagger[v] -> SuperDagger[v] + nu, v -> v - mu} + {cre -> cre + nu, ann -> ann - mu} ] -adFamilyRules[cr_, v_, vars_] /; SubsetQ[{{2, 0}, {0, 2}}, Keys[cr]] := +adFamilyRules[cr_, {cre_, ann_}, _] /; SubsetQ[{{2, 0}, {0, 2}}, Keys[cr]] := With[{p = Lookup[cr, Key[{2, 0}], 0], q = Lookup[cr, Key[{0, 2}], 0]}, With[{lam = 2 Sqrt[p q]}, - {SuperDagger[v] -> Cos[lam] SuperDagger[v] + 2 q Sinc[lam] v, - v -> Cos[lam] v - 2 p Sinc[lam] SuperDagger[v]} + {cre -> Cos[lam] cre + 2 q Sinc[lam] ann, + ann -> Cos[lam] ann - 2 p Sinc[lam] cre} ] ] adFamilyRules[___] := $Failed -modeAdRules[gen_, v_, vars_] := +modeAdRules[gen_, pair_, gens_] := Module[{x, y}, adFamilyRules[ KeyDrop[ Association @ CoefficientRules[ - Expand @ dequantizeLadder[gen, v, x, y], {x, y}], + Expand @ dequantizeLadder[gen, pair, x, y], {x, y}], Key[{0, 0}] ], - v, vars + pair, gens ] ] -adRules[gen_, vars_] := - With[{perMode = modeAdRules[gen, #, vars] & /@ Select[vars, FreeQ[#, SuperDagger] &]}, +adRules[gen_, lv_] := + With[{perMode = modeAdRules[gen, #, lv["Generators"]] & /@ ladderPairs[lv]}, Catenate[perMode] /; FreeQ[perMode, $Failed] ] adRules[___] := $Failed -adApply[rules_, expr_, vars_] := LiftNCScalars[expr /. rules, vars] +adApply[rules_, expr_, lv_] := LiftNCScalars[expr /. rules, lv["Generators"]] -rulesBraidRight[vars_] := { +rulesBraidRight[lv_] := { NonCommutativeMultiply[l___, Exp[bA_], Exp[bB_], r___] :> - With[{ar = adRules[bA, vars]}, - ncJoin[l, Exp[adApply[ar, bB, vars]], Exp[bA], r] /; ar =!= $Failed + With[{ar = adRules[bA, lv]}, + ncJoin[l, Exp[adApply[ar, bB, lv]], Exp[bA], r] /; ar =!= $Failed ] } -rulesBraidLeft[vars_] := { +rulesBraidLeft[lv_] := { NonCommutativeMultiply[l___, Exp[bA_], Exp[bB_], r___] :> - With[{br = adRules[-bB, vars]}, - ncJoin[l, Exp[bB], Exp[adApply[br, bA, vars]], r] /; br =!= $Failed + With[{br = adRules[-bB, lv]}, + ncJoin[l, Exp[bB], Exp[adApply[br, bA, lv]], r] /; br =!= $Failed ] } BosonicExpBraid::usage = -"\!\(\*RowBox[{\"BosonicExpBraid\", \"[\", StyleBox[\"expr\", \"TI\"], \"]\"}]\) moves the left factor of an adjacent pair of exponentials past the right one, transporting the right generator by the adjoint action of the left: \!\(\*SuperscriptBox[\"e\", \"A\"]\)\!\(\*SuperscriptBox[\"e\", \"B\"]\) becomes \!\(\*SuperscriptBox[\"e\", RowBox[{\"Ad\", \"[\", RowBox[{\"A\", \",\", \"B\"}], \"]\"}]]\)\!\(\*SuperscriptBox[\"e\", \"A\"]\). It reorders only, performing no ordering, merging or cancellation.\n\!\(\*RowBox[{\"BosonicExpBraid\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", \"\\\"Direction\\\"->\", \"\\\"Left\\\"\"}], \"]\"}]\) instead moves the right factor left, as \!\(\*SuperscriptBox[\"e\", \"A\"]\)\!\(\*SuperscriptBox[\"e\", \"B\"]\) becomes \!\(\*SuperscriptBox[\"e\", \"B\"]\)\!\(\*SuperscriptBox[\"e\", RowBox[{\"Ad\", \"[\", RowBox[{RowBox[{\"-\", \"B\"}], \",\", \"A\"}], \"]\"}]]\).\n\!\(\*RowBox[{\"BosonicExpBraid\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) uses vars as the field variables."; +"\!\(\*RowBox[{\"BosonicExpBraid\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) moves the left exponential of an adjacent pair past the right one, \!\(\*SuperscriptBox[\"e\", \"A\"]\)\!\(\*SuperscriptBox[\"e\", \"B\"]\) \[Rule] \!\(\*SuperscriptBox[\"e\", RowBox[{\"Ad\", \"[\", RowBox[{\"A\", \",\", \"B\"}], \"]\"}]]\)\!\(\*SuperscriptBox[\"e\", \"A\"]\).\n\!\(\*RowBox[{\"BosonicExpBraid\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", \"\\\"Direction\\\"->\", \"\\\"Left\\\"\"}], \"]\"}]\) moves the right one left, \!\(\*SuperscriptBox[\"e\", \"A\"]\)\!\(\*SuperscriptBox[\"e\", \"B\"]\) \[Rule] \!\(\*SuperscriptBox[\"e\", \"B\"]\)\!\(\*SuperscriptBox[\"e\", RowBox[{\"Ad\", \"[\", RowBox[{RowBox[{\"-\", \"B\"}], \",\", \"A\"}], \"]\"}]]\)."; BosonicExpBraid::direction = "`1` is not a valid setting for \"Direction\"; use \"Right\" or \"Left\"." Options[BosonicExpBraid] = {"Direction" -> "Right"}; -BosonicExpBraid[expr_, {}, OptionsPattern[]] := expr - -BosonicExpBraid[expr_, opts : OptionsPattern[]] := - BosonicExpBraid[expr, ExtractNCVars[{expr}], opts] - -BosonicExpBraid[expr_, vars_List, opts : OptionsPattern[]] := - Replace[OptionValue["Direction"], { - "Right" :> expr /. rulesBraidRight[vars], - "Left" :> expr /. rulesBraidLeft[vars], - other_ :> (Message[BosonicExpBraid::direction, other]; $Failed) - }] +BosonicExpBraid[expr_, opts : OptionsPattern[]] := (Message[BosonicExpBraid::argr, BosonicExpBraid, 2]; $Failed) + +BosonicExpBraid[expr_, vars_, opts : OptionsPattern[]] := + With[{lv = ResolveLadderVariables[BosonicExpBraid, vars]}, + If[ lv === $Failed, + $Failed, + Replace[OptionValue["Direction"], { + "Right" :> expr /. rulesBraidRight[lv], + "Left" :> expr /. rulesBraidLeft[lv], + other_ :> (Message[BosonicExpBraid::direction, other]; $Failed) + }] + ] + ] diff --git a/QuantumFramework/Kernel/SecondQuantization/Operators.m b/QuantumFramework/Kernel/SecondQuantization/Operators.m index 0e32c5db..f7c0c651 100644 --- a/QuantumFramework/Kernel/SecondQuantization/Operators.m +++ b/QuantumFramework/Kernel/SecondQuantization/Operators.m @@ -58,7 +58,7 @@ ordering = Replace[OptionValue["Ordering"], Automatic -> "Weak"], a, adag }, - {a, adag} = FieldVariables[order]; + {{adag}, {a}} = FieldVariables[order]; Switch[ordering, "Normal", Exp[-\[Alpha] Conjugate[\[Alpha]]/2] * Exp[\[Alpha] * adag] ** Exp[-Conjugate[\[Alpha]] * a], @@ -120,7 +120,7 @@ tau = Exp[I Arg[xi]] Tanh[Abs[xi]], a, adag }, - {a, adag} = FieldVariables[order]; + {{adag}, {a}} = FieldVariables[order]; Replace[ Switch[ordering, "Normal", diff --git a/QuantumFramework/Kernel/SecondQuantization/Utils.m b/QuantumFramework/Kernel/SecondQuantization/Utils.m index 18940098..b222b1e4 100644 --- a/QuantumFramework/Kernel/SecondQuantization/Utils.m +++ b/QuantumFramework/Kernel/SecondQuantization/Utils.m @@ -14,16 +14,12 @@ PackageExport["FieldVariables"] -PackageScope["OrderVariables"] +PackageScope["ResolveLadderVariables"] PackageExport["ToBosonicOperator"] -PackageScope["ExtractNCVars"] - PackageScope["LiftNCScalars"] -PackageScope["FormalSymbolQ"] - PackageScope["$nonuls"] PackageScope["cNumberQ"] @@ -50,9 +46,55 @@ Tr[state["Operator"]@(op^2)]-Tr[state["Operator"]@op]^2 -FormalSymbolQ[var_Symbol]:=StringStartsQ[ToString[FullForm[var]],"\\[Formal"]; +General::ladvars = "`1` does not declare ladder operators; give {{c1, \[Ellipsis], cn}, {a1, \[Ellipsis], an}}, creators first, or a WeylAlgebra."; +General::ladflat = "The list `1` mixes creators and annihilators; give the annihilators alone, `2`, or {{creators}, {annihilators}}."; +General::ladpairs = "`1` lists one {creator, annihilator} pair per mode; write `2`, the creators of every mode first."; +General::ladlen = "The creators `1` and the annihilators `2` differ in number."; +General::ladvar = "`1` cannot name a ladder operator."; +General::laddup = "`1` is declared more than once in `2`."; +General::laddagger = "The annihilator `1` carries a dagger; give {{c1, \[Ellipsis], cn}, {a1, \[Ellipsis], an}}, creators first."; +General::ladpair = "The creator `1` is paired with `2` instead of `3`."; +General::ladalg = "`1` is not a Weyl algebra."; + +daggerVariables[vars_] := With[{as = DeleteDuplicates[Flatten[vars] /. SuperDagger[v_] :> v]}, {SuperDagger /@ as, as}] + +ResolveLadderVariables[f_, alg_NonCommutativeAlgebra] := + Replace[alg["Structure"], { + {"Weyl", vars_} :> ResolveLadderVariables[f, vars], + _ :> (Message[f::ladalg, alg]; $Failed) + }] + +ResolveLadderVariables[f_, vars : {Except[_List] ..}] := + If[ FreeQ[vars, SuperDagger], + ResolveLadderVariables[f, {SuperDagger /@ vars, vars}], + Message[f::ladflat, vars, First @ daggerVariables[vars] /. SuperDagger[v_] :> v]; $Failed + ] + +ResolveLadderVariables[f_, vars : {cs : {__}, as : {__}}] := + With[{ + bad = SelectFirst[Join[cs, as], + NumericQ[#] || ! MatchQ[#, _Symbol | Except[Plus | Times | Power | List | NonCommutativeMultiply | GeneralizedPower, _Symbol][___]] &, None], + dup = FirstCase[Tally[Join[cs, as]], {v_, k_ /; k > 1} :> v, None], + cross = If[Length[cs] === Length[as], + FirstCase[Transpose[{cs, as}], {SuperDagger[x_], a_} /; x =!= a && MemberQ[as, x] :> {SuperDagger[x], a, x}, None], None] + }, + Which[ + ! FreeQ[vars, {___, x_, ___, SuperDagger[x_], ___} | {___, SuperDagger[x_], ___, x_, ___}], + Message[f::ladpairs, vars, daggerVariables[vars]]; $Failed, + Length[cs] =!= Length[as], Message[f::ladlen, cs, as]; $Failed, + bad =!= None, Message[f::ladvar, bad]; $Failed, + dup =!= None, Message[f::laddup, dup, vars]; $Failed, + MemberQ[as, _SuperDagger], Message[f::laddagger, FirstCase[as, _SuperDagger]]; $Failed, + cross =!= None, Message[f::ladpair, Sequence @@ cross]; $Failed, + True, <| + "Creators" -> cs, "Annihilators" -> as, "Generators" -> Join[cs, as], + "Algebra" -> WeylAlgebra[vars], + "Modes" -> AssociationThread[Join[cs, as], Join[#, #] & @ Range[Length[cs]]] + |> + ] + ] -FormalSymbolQ[_]:=False; +ResolveLadderVariables[f_, vars_] := (Message[f::ladvars, vars]; $Failed) $nonuls = {0. -> 0, 0. I -> 0, Complex[0., 0.] -> 0, Complex[x_, 0.] :> x, @@ -62,34 +104,20 @@ FieldVariables::usage = -"\!\(\*RowBox[{\"FieldVariables\", \"[\", \"]\"}]\) returns the default field variables {\[FormalA], \!\(\*SuperscriptBox[\"\[FormalA]\", \"\[Dagger]\"])\)}.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"var\", \"TI\"]}], \"]\"}]\) returns {var, \!\(\*SuperscriptBox[StyleBox[\"var\", \"TI\"], \"\[Dagger]\"]\)} for a formal symbol \!\(\*StyleBox[\"var\", \"TI\"]\).\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"labels\", \"TI\"]}], \"]\"}]\) returns field variables indexed by \!\(\*StyleBox[\"labels\", \"TI\"]\), using \[FormalA] as base.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"var\", \"TI\"], \",\", StyleBox[\"labels\", \"TI\"]}], \"]\"}]\) returns {\!\(\*SubscriptBox[StyleBox[\"var\", \"TI\"], \"L\"]\), \!\(\*SubsuperscriptBox[StyleBox[\"var\", \"TI\"], \"L\", \"\[Dagger]\"]\)} for each label L in \!\(\*StyleBox[\"labels\", \"TI\"]\)."; - -FieldVariables::notformal = -"The variable `1` is not a strict Mathematica Formal symbol. Please use \\[Formal`1`] instead." +"\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{}], \"]\"}]\) gives the ladder variables {{\!\(\*SuperscriptBox[\"\[FormalA]\", \"\[Dagger]\"]\)}, {\[FormalA]}}.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"var\", \"TI\"]}], \"]\"}]\) gives {{\!\(\*SuperscriptBox[StyleBox[\"var\", \"TI\"], \"\[Dagger]\"]\)}, {var}}.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{RowBox[{\"{\", RowBox[{SubscriptBox[StyleBox[\"var\", \"TI\"], \"1\"], \",\", \"\[Ellipsis]\"}], \"}\"}]}], \"]\"}]\) gives {{\!\(\*SubsuperscriptBox[StyleBox[\"var\", \"TI\"], \"1\", \"\[Dagger]\"]\), \[Ellipsis]}, {\!\(\*SubscriptBox[StyleBox[\"var\", \"TI\"], \"1\"]\), \[Ellipsis]}}.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"var\", \"TI\"], \",\", StyleBox[\"labels\", \"TI\"]}], \"]\"}]\) gives one mode per label, named var with the label appended.\n\!\(\*RowBox[{\"FieldVariables\", \"[\", RowBox[{StyleBox[\"labels\", \"TI\"]}], \"]\"}]\) uses \[FormalA]."; -FieldVariables[] := {\[FormalA], SuperDagger[\[FormalA]]} +FieldVariables[] := FieldVariables[\[FormalA]] -FieldVariables[var_Symbol ?FormalSymbolQ] := {var, SuperDagger[var]} +FieldVariables[var_Symbol] := {{SuperDagger[var]}, {var}} -FieldVariables[vars : {__Symbol ? FormalSymbolQ}] := - Flatten[{#, SuperDagger[#]} & /@ vars] +FieldVariables[vars : {__Symbol}] := {SuperDagger /@ vars, vars} FieldVariables[labels_List] := FieldVariables[\[FormalA], labels] -FieldVariables[var_Symbol ?FormalSymbolQ, labels_List] := - Flatten[ - Table[ - {Symbol[SymbolName[var] <> ToString[L]], SuperDagger[Symbol[SymbolName[var] <> ToString[L]]]}, - {L, labels} - ] - ] - -FieldVariables[var_Symbol, args___] /; !FormalSymbolQ[var] := - (Message[FieldVariables::notformal, var]; $Failed) +FieldVariables[var_Symbol, labels_List] := + FieldVariables[Symbol[SymbolName[var] <> ToString[#]] & /@ labels] -ExtractNCVars[ops_List] := - DeleteDuplicates @ Cases[ops, (v : (_? FormalSymbolQ | SuperDagger[_? FormalSymbolQ])) :> v, {0, Infinity}] @@ -103,43 +131,26 @@ } -(* Working order for default behavior of NCA in version 15. *) -OrderVariables[vars_List, direction_String : "Normal"] := Block[{annihilators, creators}, - - annihilators = Select[vars, FreeQ[#, SuperDagger] &]; - - creators = Select[vars, !FreeQ[#, SuperDagger] &]; - - If[ direction === "Antinormal", - Join[Sort[annihilators],Sort[creators]], - Join[Sort[creators],Sort[annihilators]] - ] -] - - ToBosonicOperator::usage = -"\!\(\*RowBox[{\"ToBosonicOperator\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"]}], \"]\"}]\) realizes a symbolic expression expr built from field variables (see FieldVariables) as a truncated \!\(\*RowBox[{\"QuantumOperator\", \"[\", \"]\"}]\), replacing each annihilation variable with \!\(\*RowBox[{\"AnnihilationOperator\", \"[\", \"]\"}]\) and each \!\(\*SuperscriptBox[\"\[Dagger]\", \"\"]\)-decorated variable with its adjoint, and realizing \[FormalCapitalX]**\[FormalCapitalY] as operator composition.\n\!\(\*RowBox[{\"ToBosonicOperator\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) uses vars as the ordered list of annihilation-type field variables, assigning mode k to vars[[k]].\n\!\(\*RowBox[{\"ToBosonicOperator\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", StyleBox[\"size\", \"TI\"]}], \"]\"}]\) truncates each mode to Fock space dimension size (default: \!\(\*StyleBox[\"$FockSize\", \"TI\"]\))."; - -ToBosonicOperator[expr_, vars_List : Automatic, size : _Integer?Positive : $FockSize] := - Block[{annihilators, rules}, - annihilators = If[vars === Automatic, - DeleteDuplicates[ - Cases[expr,(v : (_ ? FormalSymbolQ | SuperDagger[_ ? FormalSymbolQ])) :> v, {0, Infinity}] /. - SuperDagger[v_] :> v - ], - vars - ]; - rules = Flatten @ MapIndexed[ - With[{op = AnnihilationOperator[size, {First[#2]}]}, - {#1 -> op, SuperDagger[#1] -> op["Dagger"]} - ] &, - annihilators - ]; - expr /. { - GeneralizedPower[NonCommutativeMultiply, b_, n_Integer] :> Power[b, n], - Power[base_, x_] /; FreeQ[base, Alternatives @@ annihilators] && !FreeQ[x, Alternatives @@ annihilators] :> - MatrixExp[Log[base] x] - } /. Prepend[rules, NonCommutativeMultiply -> boseCompose] +"\!\(\*RowBox[{\"ToBosonicOperator\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"]}], \"]\"}]\) realizes expr in the ladder operators vars as a truncated QuantumOperator.\n\!\(\*RowBox[{\"ToBosonicOperator\", \"[\", RowBox[{StyleBox[\"expr\", \"TI\"], \",\", StyleBox[\"vars\", \"TI\"], \",\", StyleBox[\"size\", \"TI\"]}], \"]\"}]\) truncates each mode to dimension size."; + +ToBosonicOperator[expr_] := (Message[ToBosonicOperator::argr, ToBosonicOperator, 2]; $Failed) + +ToBosonicOperator[expr_, vars_, size : _Integer?Positive : $FockSize] := + With[{lv = ResolveLadderVariables[ToBosonicOperator, vars]}, + If[ lv === $Failed, + $Failed, + With[{ops = Table[AnnihilationOperator[size, {k}], {k, Length[lv["Annihilators"]]}], g = Alternatives @@ lv["Generators"]}, + expr /. { + GeneralizedPower[NonCommutativeMultiply, b_, n_Integer] :> Power[b, n], + Power[base_, x_] /; FreeQ[base, g] && ! FreeQ[x, g] :> MatrixExp[Log[base] x] + } /. Join[ + {NonCommutativeMultiply -> boseCompose}, + Thread[lv["Creators"] -> (#["Dagger"] & /@ ops)], + Thread[lv["Annihilators"] -> ops] + ] + ] + ] ] boseCompose[] := 1 diff --git a/Tests/SecondQuantization.wlt b/Tests/SecondQuantization.wlt index 7f13036c..b8e4b06f 100644 --- a/Tests/SecondQuantization.wlt +++ b/Tests/SecondQuantization.wlt @@ -46,45 +46,45 @@ VerificationTest[ TestID -> "SQ-coherent-g2-is-one" ] -(* BosonicVEV[expr] auto-detects the field variables and must agree with the - explicit two-argument form. Single mode: [a, a^dag] = 1 gives <0|a a^dag|0> = 1, - and a annihilates the vacuum so <0|a^dag a|0> = 0. *) +(* BosonicVEV with the annihilators alone as vars, {a}, must agree with the full form + {{a^dag}, {a}}. Single mode: [a, a^dag] = 1 gives <0|a a^dag|0> = 1, and a + annihilates the vacuum so <0|a^dag a|0> = 0. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]]}, { - BosonicVEV[a ** ad], - BosonicVEV[a ** ad] === BosonicVEV[a ** ad, {a, ad}], - BosonicVEV[ad ** a] + BosonicVEV[a ** ad, {a}], + BosonicVEV[a ** ad, {a}] === BosonicVEV[a ** ad, {{ad}, {a}}], + BosonicVEV[ad ** a, {a}] } ], {1, True, 0}, - TestID -> "SQ-BosonicVEV-single-mode-auto-detect" + TestID -> "SQ-BosonicVEV-single-mode-shorthand" ] -(* Auto-detection does real work only with more than one mode. Independent modes - commute, so <0|a a^dag b b^dag|0> = 1, while a fully normal-ordered product has - no c-number part: <0|a^dag a b^dag b|0> = 0. Single-arg must match two-arg. *) +(* Two modes. Independent modes commute, so <0|a a^dag b b^dag|0> = 1, while a fully + normal-ordered product has no c-number part: <0|a^dag a b^dag b|0> = 0. The + shorthand must match the full form. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]], b = \[FormalB], bd = SuperDagger[\[FormalB]]}, { - BosonicVEV[a ** ad ** b ** bd], - BosonicVEV[a ** ad ** b ** bd] === BosonicVEV[a ** ad ** b ** bd, {a, ad, b, bd}], - BosonicVEV[ad ** a ** bd ** b] + BosonicVEV[a ** ad ** b ** bd, {a, b}], + BosonicVEV[a ** ad ** b ** bd, {a, b}] === BosonicVEV[a ** ad ** b ** bd, {{ad, bd}, {a, b}}], + BosonicVEV[ad ** a ** bd ** b, {a, b}] } ], {1, True, 0}, - TestID -> "SQ-BosonicVEV-multimode-auto-detect" + TestID -> "SQ-BosonicVEV-multimode-shorthand" ] -(* Wick's theorem for the vacuum: <0|a^n (a^dag)^n|0> = n!. Exercises the - auto-detect path on a family, single-arg agreeing with two-arg. n is kept - concrete: the reduction does not accept a symbolic exponent. *) +(* Wick's theorem for the vacuum: <0|a^n (a^dag)^n|0> = n!, the shorthand agreeing + with the full form on the whole family. n is kept concrete: the reduction does not + accept a symbolic exponent. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]]}, With[{chains = Table[NonCommutativeMultiply @@ Join[ConstantArray[a, n], ConstantArray[ad, n]], {n, 5}]}, { - BosonicVEV /@ chains, - (BosonicVEV[#] === BosonicVEV[#, {a, ad}] &) /@ chains + BosonicVEV[#, {a}] & /@ chains, + (BosonicVEV[#, {a}] === BosonicVEV[#, {{ad}, {a}}] &) /@ chains } ] ], @@ -93,12 +93,12 @@ VerificationTest[ ] (* A symbolic scalar coefficient passes straight through the vacuum projection: - <0| lambda (a a^dag) |0> = lambda. *) + <0| lambda (a a^dag) |0> = lambda. Symbols outside vars are scalars. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]]}, { - BosonicVEV[\[Lambda] (a ** ad)], - BosonicVEV[\[Lambda] (a ** ad)] === BosonicVEV[\[Lambda] (a ** ad), {a, ad}] + BosonicVEV[\[Lambda] (a ** ad), {a}], + BosonicVEV[\[Lambda] (a ** ad), {a}] === BosonicVEV[\[Lambda] (a ** ad), {{ad}, {a}}] } ], {\[Lambda], True}, @@ -109,7 +109,7 @@ VerificationTest[ Fock-space matrix element <0|a a^dag|0> built from the ladder operators. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]]}, - BosonicVEV[a ** ad] === + BosonicVEV[a ** ad, {a}] === (FockState[0]["Dagger"] @ (AnnihilationOperator[] @ AnnihilationOperator[]["Dagger"]) @ FockState[0])["Scalar"] ], True, @@ -123,9 +123,9 @@ VerificationTest[ VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]], b = \[FormalB], bd = SuperDagger[\[FormalB]]}, { - BosonicVEV[a ** ad ** b ** bd] === BosonicVEV[a ** ad] BosonicVEV[b ** bd], - BosonicVEV[a ** b ** ad ** bd], - BosonicVEV[ad ** b ** a ** bd] + BosonicVEV[a ** ad ** b ** bd, {a, b}] === BosonicVEV[a ** ad, {a}] BosonicVEV[b ** bd, {b}], + BosonicVEV[a ** b ** ad ** bd, {a, b}], + BosonicVEV[ad ** b ** a ** bd, {a, b}] } ], {True, 1, 0}, @@ -137,19 +137,16 @@ VerificationTest[ the balanced a a a^dag a^dag follows Wick, <0|a^2 (a^dag)^2|0> = 2. *) VerificationTest[ With[{a = \[FormalA], ad = SuperDagger[\[FormalA]]}, - {BosonicVEV[a ** a ** ad], BosonicVEV[a ** ad ** ad], BosonicVEV[a ** a ** ad ** ad]} + {BosonicVEV[a ** a ** ad, {a}], BosonicVEV[a ** ad ** ad, {a}], BosonicVEV[a ** a ** ad ** ad, {a}]} ], {0, 0, 2}, TestID -> "SQ-BosonicVEV-number-selection-rule" ] -(* A c-number has no field operators, so it is its own vacuum expectation: - <0|c|0> = c. The single-argument auto-detect path finds an empty variable list - and must return the c-number rather than recurse to the recursion limit; the - explicit empty-list form BosonicVEV[c, {}] routes through the same rule. *) +(* A c-number has no field operators, so it is its own vacuum expectation: <0|c|0> = c. *) VerificationTest[ - {BosonicVEV[7], BosonicVEV[\[Lambda]], BosonicVEV[7, {}]}, - {7, \[Lambda], 7}, + {BosonicVEV[7, {\[FormalA]}], BosonicVEV[\[Lambda], {\[FormalA]}]}, + {7, \[Lambda]}, TestID -> "SQ-BosonicVEV-cnumber-is-itself" ] @@ -160,57 +157,59 @@ VerificationTest[ operators. Returning the unevaluated call asserts nothing, where returning expr itself would claim <0|Cosh[a]|0> == Cosh[a]. *) VerificationTest[ - BosonicVEV[Cosh[\[FormalA]]], - BosonicVEV[Cosh[\[FormalA]]], + BosonicVEV[Cosh[\[FormalA]], {\[FormalA]}], + BosonicVEV[Cosh[\[FormalA]], {\[FormalA]}], {}, TestID -> "SQ-BosonicVEV-nonpolynomial-stays-unevaluated" ] (* The dangerous case: <0|D(\[Alpha])|0> = E^(-Abs[\[Alpha]]^2/2), so a silent 0 or 1 here - would be indistinguishable from a real result. Unevaluated is safe; the - auto-detected variable list must not leak into the echoed call either. *) + would be indistinguishable from a real result. Unevaluated is safe. *) VerificationTest[ - BosonicVEV[Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]]], - BosonicVEV[Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]]], + BosonicVEV[Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]], {\[FormalA]}], + BosonicVEV[Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]], {\[FormalA]}], {}, TestID -> "SQ-BosonicVEV-displacement-stays-unevaluated" ] -(* The explicit-vars form stays unevaluated in its own shape. *) +(* The full-form vars stays unevaluated in its own shape. *) VerificationTest[ - BosonicVEV[Cosh[\[FormalA]], {\[FormalA], SuperDagger[\[FormalA]]}], - BosonicVEV[Cosh[\[FormalA]], {\[FormalA], SuperDagger[\[FormalA]]}], + BosonicVEV[Cosh[\[FormalA]], {{SuperDagger[\[FormalA]]}, {\[FormalA]}}], + BosonicVEV[Cosh[\[FormalA]], {{SuperDagger[\[FormalA]]}, {\[FormalA]}}], {}, TestID -> "SQ-BosonicVEV-explicit-vars-stays-unevaluated" ] -(* An expression naming only one of the two ladder operators still needs both to - build the commutation relation; the missing partner is supplied. *) +(* Naming the annihilator alone supplies its SuperDagger partner. *) VerificationTest[ - { - BosonicVEV[\[FormalA] ** SuperDagger[\[FormalA]], {\[FormalA]}], - BosonicVEV[\[FormalA] ** SuperDagger[\[FormalA]], {SuperDagger[\[FormalA]]}] - }, - {1, 1}, + BosonicVEV[\[FormalA] ** SuperDagger[\[FormalA]], {\[FormalA]}], + 1, {}, TestID -> "SQ-BosonicVEV-completes-the-ladder-pair" ] -(* Normal-ordering with no field variables is the identity on the c-number: with - nothing to reduce, the reducer is never invoked and the constant passes through - unchanged and message-free. *) +(* A creator cannot stand in the annihilator list. *) VerificationTest[ - {BosonicNormalOrder[7, {}], BosonicNormalOrder[\[Lambda], {}]}, - {7, \[Lambda]}, - TestID -> "SQ-BosonicNormalOrder-empty-vars-is-identity" + BosonicVEV[\[FormalA] ** SuperDagger[\[FormalA]], {SuperDagger[\[FormalA]]}], + $Failed, + {BosonicVEV::ladflat}, + TestID -> "SQ-BosonicVEV-rejects-creator-as-annihilator" ] -(* Anti-normal-ordering with no field variables is likewise the identity on the - c-number: nothing to reorder, so the constant passes through message-free. *) +(* A c-number is already in normal and anti-normal order, whatever modes are declared. *) VerificationTest[ - {BosonicAntinormalOrder[7, {}], BosonicAntinormalOrder[\[Lambda], {}]}, - {7, \[Lambda]}, - TestID -> "SQ-BosonicAntinormalOrder-empty-vars-is-identity" + {BosonicNormalOrder[7, {\[FormalA]}], BosonicNormalOrder[\[Lambda], {\[FormalA]}], + BosonicAntinormalOrder[7, {\[FormalA]}], BosonicAntinormalOrder[\[Lambda], {\[FormalA]}]}, + {7, \[Lambda], 7, \[Lambda]}, + TestID -> "SQ-ordering-cnumber-is-identity" +] + +(* An empty declaration names no ladder operators and is rejected. *) +VerificationTest[ + {BosonicNormalOrder[7, {}], BosonicAntinormalOrder[7, {}]}, + {$Failed, $Failed}, + {BosonicNormalOrder::ladvars, BosonicAntinormalOrder::ladvars}, + TestID -> "SQ-ordering-empty-vars-rejected" ] (* Phase-space functions at the origin alpha = 0. The closed-form kernels carry a diff --git a/Tests/SecondQuantization/Antinormal.wlt b/Tests/SecondQuantization/Antinormal.wlt index d9bf9e02..fc39e4cc 100644 --- a/Tests/SecondQuantization/Antinormal.wlt +++ b/Tests/SecondQuantization/Antinormal.wlt @@ -3,7 +3,7 @@ Needs["Wolfram`QuantumFramework`SecondQuantization`"] (* Shared scaffolding: a battery of monomials/polynomials to check invariants over, and a structural predicate asserting that no creator precedes an annihilator in any monomial *) -$antiVars = {\[FormalA], SuperDagger[\[FormalA]]}; +$antiVars = {{SuperDagger[\[FormalA]]}, {\[FormalA]}}; $antiBattery = { SuperDagger[\[FormalA]] ** \[FormalA], @@ -26,7 +26,7 @@ $antiOrderedQ[expr_, vars_] := AllTrue[ FirstCase[term, _NonCommutativeMultiply, term, {0, Infinity}], {NonCommutativeMultiply[f__] :> {f}, f_ :> {f}} ], - ! FreeQ[#, Alternatives @@ vars] & + ! FreeQ[#, Alternatives @@ Flatten[vars]] & ] ] ] @@ -97,7 +97,7 @@ BeginTestSection["BosonicAntinormalOrder - two modes"] VerificationTest[ BosonicAntinormalOrder[ SuperDagger[\[FormalA]] ** \[FormalA] ** SuperDagger[\[FormalB]] ** \[FormalB], - {\[FormalA], SuperDagger[\[FormalA]], \[FormalB], SuperDagger[\[FormalB]]}], + {{SuperDagger[\[FormalA]], SuperDagger[\[FormalB]]}, {\[FormalA], \[FormalB]}}], 1 - \[FormalA] ** SuperDagger[\[FormalA]] - \[FormalB] ** SuperDagger[\[FormalB]] + \[FormalA] ** \[FormalB] ** SuperDagger[\[FormalA]] ** SuperDagger[\[FormalB]], TestID -> "Antinormal-TwoModeNumberProduct" @@ -105,7 +105,7 @@ VerificationTest[ (* Mixed two-mode polynomial: check the operator is preserved *) VerificationTest[ - Module[{vars = {\[FormalA], SuperDagger[\[FormalA]], \[FormalB], SuperDagger[\[FormalB]]}, x}, + Module[{vars = {{SuperDagger[\[FormalA]], SuperDagger[\[FormalB]]}, {\[FormalA], \[FormalB]}}, x}, x = 2 SuperDagger[\[FormalA]] ** \[FormalA] + SuperDagger[\[FormalA]] ** SuperDagger[\[FormalB]] ** \[FormalA] ** \[FormalB]; Simplify[ @@ -121,13 +121,12 @@ EndTestSection[] BeginTestSection["BosonicAntinormalOrder - scalars"] -(* Symbolic coefficients declared through "Scalars" must survive the reduction *) +(* Symbols outside vars are scalars and must survive the reduction *) VerificationTest[ BosonicAntinormalOrder[ \[Alpha] SuperDagger[\[FormalA]] ** \[FormalA] + \[Beta] SuperDagger[\[FormalA]] ** SuperDagger[\[FormalA]] ** \[FormalA] ** \[FormalA], - $antiVars, - "Scalars" -> {\[Alpha], \[Beta]}], + $antiVars], -\[Alpha] + 2 \[Beta] + (\[Alpha] - 4 \[Beta]) \[FormalA] ** SuperDagger[\[FormalA]] + \[Beta] GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2] ** GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2], @@ -140,7 +139,7 @@ EndTestSection[] BeginTestSection["BosonicAntinormalOrder - methods"] (* "Blasiak" reaches anti-normal order by conjugating the normal-ordering formula with the - automorphism a -> a^dagger, a^dagger -> -a; it must agree with the Grobner reduction *) + automorphism a -> a^dagger, a^dagger -> -a; it must agree with the Weyl algebra reduction *) VerificationTest[ AllTrue[$antiBattery, Simplify[ @@ -148,7 +147,7 @@ VerificationTest[ BosonicAntinormalOrder[#, $antiVars] ] === 0 &], True, - TestID -> "Antinormal-BlasiakMatchesGrobner" + TestID -> "Antinormal-BlasiakMatchesWeyl" ] (* The conjugating automorphism introduces a sign on odd-degree creator blocks, so the Blasiak diff --git a/Tests/SecondQuantization/BosonicExpBraid.wlt b/Tests/SecondQuantization/BosonicExpBraid.wlt index 482ba7bd..f66e71d6 100644 --- a/Tests/SecondQuantization/BosonicExpBraid.wlt +++ b/Tests/SecondQuantization/BosonicExpBraid.wlt @@ -5,6 +5,7 @@ $a = \[FormalA]; $ad = SuperDagger[\[FormalA]]; $n = $ad ** $a; $disp = \[Alpha] $ad - Conjugate[\[Alpha]] $a; +$vars = {{$ad}, {$a}}; exponentOf[Exp[x_]] := x; exponentOf[_] := $Failed; @@ -39,7 +40,7 @@ BeginTestSection["BosonicExpBraid - number-operator generator"] (* The identity that motivated the function: e^(\[Beta] n) D(\[Alpha]) = e^(\[Alpha] e^\[Beta] a\[Dagger] - \[Alpha]\[Conjugate] e^-\[Beta] a) e^(\[Beta] n). *) VerificationTest[ - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp]], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp], $vars], Exp[\[Alpha] Exp[\[Beta]] $ad - Conjugate[\[Alpha]] Exp[-\[Beta]] $a] ** Exp[\[Beta] $n], {}, TestID -> "BosonicExpBraid-NumberPastDisplacement" @@ -48,7 +49,7 @@ VerificationTest[ VerificationTest[ braidHoldsQ[ Exp[\[Beta] $n] ** Exp[$disp], - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp]], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp], $vars], {\[Beta] -> 0.3 + 0.2 I, \[Alpha] -> 0.5 - 0.4 I} ], True, @@ -59,7 +60,7 @@ VerificationTest[ (* Any partner is allowed, including GeneralizedPower and unordered products. Each a\[Dagger] picks up e^\[Lambda], each a picks up e^-\[Lambda]. *) VerificationTest[ - BosonicExpBraid[Exp[\[Lambda] $n] ** Exp[\[Xi] $ad ** $ad]], + BosonicExpBraid[Exp[\[Lambda] $n] ** Exp[\[Xi] $ad ** $ad], $vars], Exp[\[Xi] Exp[2 \[Lambda]] $ad ** $ad] ** Exp[\[Lambda] $n], {}, TestID -> "BosonicExpBraid-NumberPastQuadraticPartner" @@ -67,7 +68,7 @@ VerificationTest[ VerificationTest[ BosonicExpBraid[ - Exp[\[Lambda] $n] ** Exp[\[Xi] GeneralizedPower[NonCommutativeMultiply, $a, 3]]], + Exp[\[Lambda] $n] ** Exp[\[Xi] GeneralizedPower[NonCommutativeMultiply, $a, 3]], $vars], Exp[\[Xi] Exp[-3 \[Lambda]] GeneralizedPower[NonCommutativeMultiply, $a, 3]] ** Exp[\[Lambda] $n], {}, TestID -> "BosonicExpBraid-NumberPastGeneralizedPower" @@ -76,7 +77,7 @@ VerificationTest[ (* a**a\[Dagger] = n + 1 differs from n by a central term, so the ad-action is the same and this partner comes back untouched - it is NOT normal-ordered. *) VerificationTest[ - BosonicExpBraid[Exp[\[Lambda] $n] ** Exp[\[Xi] $a ** $ad]], + BosonicExpBraid[Exp[\[Lambda] $n] ** Exp[\[Xi] $a ** $ad], $vars], Exp[\[Xi] $a ** $ad] ** Exp[\[Lambda] $n], {}, TestID -> "BosonicExpBraid-DoesNotOrderThePartner" @@ -89,7 +90,7 @@ BeginTestSection["BosonicExpBraid - linear and quadratic generators"] (* Ad_(\[Alpha] a\[Dagger]) shifts a by -\[Alpha] and fixes a\[Dagger]. *) VerificationTest[ - BosonicExpBraid[Exp[\[Alpha] $ad] ** Exp[\[Lambda] $n]], + BosonicExpBraid[Exp[\[Alpha] $ad] ** Exp[\[Lambda] $n], $vars], Exp[\[Lambda] $ad ** ($a - \[Alpha])] ** Exp[\[Alpha] $ad], {}, TestID -> "BosonicExpBraid-CreationPastNumber" @@ -98,7 +99,7 @@ VerificationTest[ VerificationTest[ braidHoldsQ[ Exp[\[Alpha] $ad] ** Exp[\[Lambda] $n], - BosonicExpBraid[Exp[\[Alpha] $ad] ** Exp[\[Lambda] $n]], + BosonicExpBraid[Exp[\[Alpha] $ad] ** Exp[\[Lambda] $n], $vars], {\[Lambda] -> -0.35 + 0.1 I, \[Alpha] -> 0.4 - 0.2 I} ], True, @@ -112,7 +113,7 @@ VerificationTest[ sameBraidQ[ BosonicExpBraid[ Exp[(1/4) (GeneralizedPower[NonCommutativeMultiply, $ad, 2] - - GeneralizedPower[NonCommutativeMultiply, $a, 2])] ** Exp[\[Alpha] $ad]], + GeneralizedPower[NonCommutativeMultiply, $a, 2])] ** Exp[\[Alpha] $ad], $vars], Exp[\[Alpha] (Cosh[1/2] $ad - Sinh[1/2] $a)] ** Exp[(1/4) (GeneralizedPower[NonCommutativeMultiply, $ad, 2] - GeneralizedPower[NonCommutativeMultiply, $a, 2])] @@ -125,7 +126,7 @@ VerificationTest[ VerificationTest[ braidHoldsQ[ Exp[(1/4) ($ad ** $ad - $a ** $a)] ** Exp[\[Alpha] $ad], - BosonicExpBraid[Exp[(1/4) ($ad ** $ad - $a ** $a)] ** Exp[\[Alpha] $ad]], + BosonicExpBraid[Exp[(1/4) ($ad ** $ad - $a ** $a)] ** Exp[\[Alpha] $ad], $vars], {\[Alpha] -> 0.3 - 0.25 I} ], True, @@ -140,7 +141,7 @@ BeginTestSection["BosonicExpBraid - direction"] (* Left transport: e^A e^B = e^B e^(Ad_-B A). *) VerificationTest[ - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Alpha] $ad], "Direction" -> "Left"], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Alpha] $ad], $vars, "Direction" -> "Left"], Exp[\[Alpha] $ad] ** Exp[\[Beta] $ad ** ($a + \[Alpha])], {}, TestID -> "BosonicExpBraid-LeftDirection" @@ -149,7 +150,7 @@ VerificationTest[ VerificationTest[ braidHoldsQ[ Exp[\[Beta] $n] ** Exp[\[Alpha] $ad], - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Alpha] $ad], "Direction" -> "Left"], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Alpha] $ad], $vars, "Direction" -> "Left"], {\[Beta] -> 0.2 - 0.3 I, \[Alpha] -> 0.45 + 0.15 I} ], True, @@ -158,7 +159,7 @@ VerificationTest[ ] VerificationTest[ - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp], "Direction" -> "Sideways"], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[$disp], $vars, "Direction" -> "Sideways"], $Failed, {BosonicExpBraid::direction}, TestID -> "BosonicExpBraid-RejectsUnknownDirection" @@ -172,7 +173,7 @@ BeginTestSection["BosonicExpBraid - stays in its lane"] (* Commuting exponentials are swapped, never merged - merging belongs to BosonicExpSimplify. *) VerificationTest[ - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Gamma] $n]], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[\[Gamma] $n], $vars], Exp[\[Gamma] $n] ** Exp[\[Beta] $n], {}, TestID -> "BosonicExpBraid-DoesNotMergeCommutingPair" @@ -180,7 +181,7 @@ VerificationTest[ (* An exponential and its inverse are swapped, never cancelled. *) VerificationTest[ - BosonicExpBraid[Exp[\[Beta] $n] ** Exp[-\[Beta] $n]], + BosonicExpBraid[Exp[\[Beta] $n] ** Exp[-\[Beta] $n], $vars], Exp[-\[Beta] $n] ** Exp[\[Beta] $n], {}, TestID -> "BosonicExpBraid-DoesNotCancelInversePair" @@ -188,7 +189,7 @@ VerificationTest[ (* A generator outside the recognized families transports nothing, silently. *) VerificationTest[ - BosonicExpBraid[Exp[\[Lambda] $ad ** $a ** $a] ** Exp[\[Alpha] $ad]], + BosonicExpBraid[Exp[\[Lambda] $ad ** $a ** $a] ** Exp[\[Alpha] $ad], $vars], Exp[\[Lambda] $ad ** $a ** $a] ** Exp[\[Alpha] $ad], {}, TestID -> "BosonicExpBraid-UnrecognizedGeneratorIsInert" @@ -196,7 +197,7 @@ VerificationTest[ (* Mixed families in one generator (number + linear) are not claimed. *) VerificationTest[ - BosonicExpBraid[Exp[\[Lambda] $n + \[Alpha] $ad] ** Exp[\[Gamma] $a]], + BosonicExpBraid[Exp[\[Lambda] $n + \[Alpha] $ad] ** Exp[\[Gamma] $a], $vars], Exp[\[Lambda] $n + \[Alpha] $ad] ** Exp[\[Gamma] $a], {}, TestID -> "BosonicExpBraid-MixedFamilyIsInert" @@ -211,7 +212,7 @@ BeginTestSection["BosonicExpBraid - multimode"] VerificationTest[ Module[{b = \[FormalB], bd = SuperDagger[\[FormalB]]}, BosonicExpBraid[ - Exp[\[Lambda] $n + \[Mu] bd ** b] ** Exp[\[Alpha] $ad ** b]] + Exp[\[Lambda] $n + \[Mu] bd ** b] ** Exp[\[Alpha] $ad ** b], {{$ad, bd}, {$a, b}}] ], Module[{b = \[FormalB], bd = SuperDagger[\[FormalB]]}, Exp[\[Alpha] Exp[\[Lambda] - \[Mu]] $ad ** b] ** Exp[\[Lambda] $n + \[Mu] bd ** b] @@ -223,7 +224,7 @@ VerificationTest[ (* A cross-mode generator (beam splitter) is not a recognized family. *) VerificationTest[ Module[{b = \[FormalB], bd = SuperDagger[\[FormalB]]}, - BosonicExpBraid[Exp[\[Theta] $ad ** b] ** Exp[\[Alpha] $ad]] + BosonicExpBraid[Exp[\[Theta] $ad ** b] ** Exp[\[Alpha] $ad], {{$ad, bd}, {$a, b}}] ], Module[{b = \[FormalB]}, Exp[\[Theta] $ad ** b] ** Exp[\[Alpha] $ad] diff --git a/Tests/SecondQuantization/BosonicExpOrder.wlt b/Tests/SecondQuantization/BosonicExpOrder.wlt index 82036029..cddd802e 100644 --- a/Tests/SecondQuantization/BosonicExpOrder.wlt +++ b/Tests/SecondQuantization/BosonicExpOrder.wlt @@ -8,6 +8,11 @@ Needs["Wolfram`QuantumFramework`SecondQuantization`"] normalizeIndex[expr_, s_] := expr /. Inactive[Sum][b_, {i_, lo_, hi_}] :> Inactive[Sum][b /. i -> s, {s, lo, hi}] +$vA = {{SuperDagger[\[FormalA]]}, {\[FormalA]}}; +$vB = {{SuperDagger[\[FormalB]]}, {\[FormalB]}}; +$vC = {{SuperDagger[\[FormalC]]}, {\[FormalC]}}; +$vAB = {{SuperDagger[\[FormalA]], SuperDagger[\[FormalB]]}, {\[FormalA], \[FormalB]}}; + BeginTestSection["BosonicExpOrder - independence from parallel sub-kernels"] @@ -24,14 +29,14 @@ BeginTestSection["BosonicExpOrder - independence from parallel sub-kernels"] the parallel pool: it closes any running kernels and ends with the pool empty. *) VerificationTest[ - (CloseKernels[]; BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]]]), + (CloseKernels[]; BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]], $vA]), (\[Alpha] + SuperDagger[\[FormalA]])**E^(\[FormalA]*\[Alpha]), TestID -> "PlusSplitZeroKernels" ] VerificationTest[ (LaunchKernels[2]; - With[{ordered = BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]]]}, + With[{ordered = BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]], $vA]}, CloseKernels[]; ordered]), (\[Alpha] + SuperDagger[\[FormalA]])**E^(\[FormalA]*\[Alpha]), TestID -> "PlusSplitLaunchedKernels" @@ -58,8 +63,7 @@ BeginTestSection["BosonicExpOrder - ordering sums"] VerificationTest[ BosonicNormalOrder[\[FormalA]**SuperDagger[\[FormalA]] + \[FormalB]**SuperDagger[\[FormalB]] + \[FormalA]**SuperDagger[\[FormalB]] + \[Lambda]*SuperDagger[\[FormalA]]**\[FormalB], - {\[FormalA], SuperDagger[\[FormalA]], \[FormalB], SuperDagger[\[FormalB]]}, - "Scalars" -> {\[Lambda]}], + $vAB], 2 + SuperDagger[\[FormalA]]**\[FormalA] + \[Lambda]*SuperDagger[\[FormalA]]**\[FormalB] + SuperDagger[\[FormalB]]**\[FormalA] + SuperDagger[\[FormalB]]**\[FormalB], TestID -> "TwoModeSumNormalOrders" @@ -69,7 +73,7 @@ VerificationTest[ VerificationTest[ BosonicAntinormalOrder[SuperDagger[\[FormalA]]**\[FormalA] - 4*\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA], - {\[FormalA], SuperDagger[\[FormalA]]}, "Scalars" -> {\[Lambda]}], + $vA], -1 + 4*\[Lambda] + (1 - 4*\[Lambda])*\[FormalA]**SuperDagger[\[FormalA]], TestID -> "AntinormalSumCollects" ] @@ -81,13 +85,13 @@ VerificationTest[ x = \[FormalA]**SuperDagger[\[FormalA]], y = GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]**\[FormalA], z = \[Lambda]*\[FormalA], - vars = {\[FormalA], SuperDagger[\[FormalA]]} + vars = $vA }, { - Simplify[BosonicNormalOrder[x + y + z, vars, "Scalars" -> {\[Lambda]}] - - Total[BosonicNormalOrder[#, vars, "Scalars" -> {\[Lambda]}] & /@ {x, y, z}]], - Simplify[BosonicAntinormalOrder[x + y + z, vars, "Scalars" -> {\[Lambda]}] - - Total[BosonicAntinormalOrder[#, vars, "Scalars" -> {\[Lambda]}] & /@ {x, y, z}]] + Simplify[BosonicNormalOrder[x + y + z, vars] - + Total[BosonicNormalOrder[#, vars] & /@ {x, y, z}]], + Simplify[BosonicAntinormalOrder[x + y + z, vars] - + Total[BosonicAntinormalOrder[#, vars] & /@ {x, y, z}]] } ], {0, 0}, @@ -98,7 +102,7 @@ VerificationTest[ routes to the default reduction. *) VerificationTest[ BosonicNormalOrder[\[FormalA] + SuperDagger[\[FormalA]], - {\[FormalA], SuperDagger[\[FormalA]]}, Method -> "NoSuchMethod"], + $vA, Method -> "NoSuchMethod"], $Failed, {BosonicNormalOrder::unknownMethod}, TestID -> "UnknownMethodOnSumFailsOnce" @@ -106,7 +110,7 @@ VerificationTest[ VerificationTest[ BosonicNormalOrder[\[FormalA]**SuperDagger[\[FormalA]], - {\[FormalA], SuperDagger[\[FormalA]]}, Method -> Automatic], + $vA, Method -> Automatic], 1 + SuperDagger[\[FormalA]]**\[FormalA], TestID -> "AutomaticMethodRoutesToDefault" ] @@ -115,9 +119,9 @@ VerificationTest[ survive inside a Plus. *) VerificationTest[ BosonicNormalOrder[\[FormalA]**SuperDagger[\[FormalA]] + Sin[\[FormalA]], - {\[FormalA], SuperDagger[\[FormalA]]}, Method -> "Blasiak"], + $vA, Method -> "Blasiak"], $Failed, - {Wolfram`QuantumFramework`SecondQuantization`PackageScope`ParseBlasiakMonomial::badfactor}, + {BosonicNormalOrder::ladpoly}, TestID -> "BlasiakPartialFailureCollapses" ] @@ -126,7 +130,7 @@ VerificationTest[ through degree six. *) VerificationTest[ Table[Simplify[BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]** - GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], m]] - + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], m], $vA] - Sum[Binomial[m, j]*\[Alpha]^(m - j)* If[j === 0, 1, GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], j]], {j, 0, m}]**E^(\[FormalA]*\[Alpha])], {m, 1, 6}], @@ -139,7 +143,7 @@ VerificationTest[ VerificationTest[ BosonicNormalOrder[\[FormalA]**SuperDagger[\[FormalA]] + SuperDagger[\[FormalA]]**\[FormalA]**SuperDagger[\[FormalA]], - {\[FormalA], SuperDagger[\[FormalA]]}, Method -> "Blasiak"], + $vA, Method -> "Blasiak"], 1 + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]**\[FormalA] + SuperDagger[\[FormalA]]**\[FormalA] + SuperDagger[\[FormalA]], TestID -> "BlasiakSumMatchesDefaultRoute" @@ -149,15 +153,15 @@ VerificationTest[ idempotent on an already-ordered sum. *) VerificationTest[ With[{x = SuperDagger[\[FormalA]]**\[FormalA]**SuperDagger[\[FormalA]] + \[Lambda]*\[FormalA], - vars = {\[FormalA], SuperDagger[\[FormalA]]}}, + vars = $vA}, { BosonicNormalOrder[Commutator[\[FormalA], SuperDagger[\[FormalA]]], vars], - Simplify[BosonicNormalOrder[BosonicNormalOrder[x, vars, "Scalars" -> {\[Lambda]}], - vars, "Scalars" -> {\[Lambda]}] - - BosonicNormalOrder[x, vars, "Scalars" -> {\[Lambda]}]], - Simplify[BosonicAntinormalOrder[BosonicAntinormalOrder[x, vars, "Scalars" -> {\[Lambda]}], - vars, "Scalars" -> {\[Lambda]}] - - BosonicAntinormalOrder[x, vars, "Scalars" -> {\[Lambda]}]] + Simplify[BosonicNormalOrder[BosonicNormalOrder[x, vars], + vars] - + BosonicNormalOrder[x, vars]], + Simplify[BosonicAntinormalOrder[BosonicAntinormalOrder[x, vars], + vars] - + BosonicAntinormalOrder[x, vars]] } ], {1, 0, 0}, @@ -169,7 +173,7 @@ VerificationTest[ VerificationTest[ Table[BosonicVEV[GeneralizedPower[NonCommutativeMultiply, \[FormalA], m]** GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], m], - {\[FormalA], SuperDagger[\[FormalA]]}], {m, 1, 5}], + $vA], {m, 1, 5}], {1, 2, 6, 24, 120}, TestID -> "VacuumMomentsAreFactorials" ] @@ -180,7 +184,7 @@ VerificationTest[ VerificationTest[ With[{ gen = \[FormalA]**SuperDagger[\[FormalB]] + SuperDagger[\[FormalA]]**\[FormalB], - vars = {\[FormalA], SuperDagger[\[FormalA]], \[FormalB], SuperDagger[\[FormalB]]} + vars = $vAB }, { BosonicNormalOrder[Commutator[ @@ -201,7 +205,7 @@ VerificationTest[ Module[{size = 12, block = 8, am, adm, toMatrix, pN, pA, vars}, am = AnnihilationOperator[size]["Matrix"]; adm = ConjugateTranspose[am]; - vars = {\[FormalA], SuperDagger[\[FormalA]]}; + vars = $vA; toMatrix[e_Plus] := Total[toMatrix /@ (List @@ e)]; toMatrix[e_ /; FreeQ[e, \[FormalA]]] := e IdentityMatrix[size, SparseArray]; toMatrix[e_] := e /. { @@ -233,14 +237,14 @@ BeginTestSection["BosonicExpOrder - number-operator exponentials"] NormalOrdered[Exp[(E^lambda - 1) a^dagger a]]. The "Series" property re-expresses that as an inactive sum over normally-ordered monomials. *) VerificationTest[ - BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]]], - NormalOrdered[E^((-1 + E^\[Lambda])*SuperDagger[\[FormalA]]**\[FormalA])], + BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], $vA], + NormalOrdered[E^((-1 + E^\[Lambda])*SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedRes1" ] VerificationTest[ normalizeIndex[ - BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]]]["Series"], k], + BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], $vA]["Series"], k], Inactive[Sum][ ((-1 + E^\[Lambda])^k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], k]** GeneralizedPower[NonCommutativeMultiply, \[FormalA], k])/k!, {k, 0, Infinity}], @@ -248,15 +252,15 @@ VerificationTest[ ] VerificationTest[ - BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]]], + BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]], $vA], E^\[Lambda]*NormalOrdered[ - E^((-1 + E^\[Lambda])*SuperDagger[\[FormalA]]**\[FormalA])], + E^((-1 + E^\[Lambda])*SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedRes2" ] VerificationTest[ normalizeIndex[ - BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]]]["Series"], k], + BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]], $vA]["Series"], k], E^\[Lambda]*Inactive[Sum][ ((-1 + E^\[Lambda])^k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], k]** GeneralizedPower[NonCommutativeMultiply, \[FormalA], k])/k!, {k, 0, Infinity}], @@ -264,14 +268,14 @@ VerificationTest[ ] VerificationTest[ - BosonicExpOrder[Exp[(3/10)*SuperDagger[\[FormalA]]**\[FormalA]]], - NormalOrdered[E^((-1 + E^(3/10))*SuperDagger[\[FormalA]]**\[FormalA])], + BosonicExpOrder[Exp[(3/10)*SuperDagger[\[FormalA]]**\[FormalA]], $vA], + NormalOrdered[E^((-1 + E^(3/10))*SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedResExactNumber" ] VerificationTest[ - BosonicExpOrder[Exp[0.3*SuperDagger[\[FormalB]]**\[FormalB]]], - NormalOrdered[E^((Exp[0.3] - 1)*SuperDagger[\[FormalB]]**\[FormalB])], + BosonicExpOrder[Exp[0.3*SuperDagger[\[FormalB]]**\[FormalB]], $vB], + NormalOrdered[E^((Exp[0.3] - 1)*SuperDagger[\[FormalB]]**\[FormalB]), $vB], TestID -> "NormalOrderOtherVariableAndFloat" ] @@ -283,33 +287,33 @@ BeginTestSection["BosonicExpOrder - linear ladder combinations"] (* A linear combination in a and a^dagger disentangles by the Weyl relation, picking up the Gaussian prefactor Exp[alpha beta / 2]. *) VerificationTest[ - BosonicExpOrder[Exp[\[Lambda]*\[FormalA] + \[Beta]*SuperDagger[\[FormalA]]]], + BosonicExpOrder[Exp[\[Lambda]*\[FormalA] + \[Beta]*SuperDagger[\[FormalA]]], $vA], Exp[(\[Beta]*\[Lambda])/2]*Exp[\[Beta]*SuperDagger[\[FormalA]]]** Exp[\[Lambda]*\[FormalA]], TestID -> "LinearCombinationLadder" ] VerificationTest[ - BosonicExpOrder[Exp[\[Lambda]*\[FormalA] + \[Beta]*SuperDagger[\[FormalA]]], + BosonicExpOrder[Exp[\[Lambda]*\[FormalA] + \[Beta]*SuperDagger[\[FormalA]]], $vA, Assumptions -> \[Beta] == 1/\[Lambda]], Sqrt[E]*E^(\[Beta]*SuperDagger[\[FormalA]])**E^(\[FormalA]*\[Lambda]), TestID -> "TestAssumptions" ] VerificationTest[ - BosonicExpOrder[Exp[0.3*\[FormalA] + 0.5*SuperDagger[\[FormalA]]]], + BosonicExpOrder[Exp[0.3*\[FormalA] + 0.5*SuperDagger[\[FormalA]]], $vA], 1.0778841508846315*E^(0.5*SuperDagger[\[FormalA]])**E^(0.3*\[FormalA]), TestID -> "LinearCombinationLadderFloat" ] VerificationTest[ - BosonicExpOrder[Exp[0.8*SuperDagger[\[FormalA]] + 0.5*\[FormalA]]], + BosonicExpOrder[Exp[0.8*SuperDagger[\[FormalA]] + 0.5*\[FormalA]], $vA], E^((0.8*0.5)/2)*E^(0.8*SuperDagger[\[FormalA]])**E^(0.5*\[FormalA]), TestID -> "LinearCombinationLadderFloat2" ] VerificationTest[ - BosonicExpOrder[DisplacementOperator[\[Alpha], Infinity]], + BosonicExpOrder[DisplacementOperator[\[Alpha], Infinity], FieldVariables[{1}]], DisplacementOperator[\[Alpha], Infinity, "Ordering" -> "Normal"], TestID -> "DisplacementOperatorNormal" ] @@ -324,7 +328,7 @@ BeginTestSection["BosonicExpOrder - SU(1,1) disentangling and squeezing"] Exp[a^dagger a^dagger] . (...)^(a^dagger a) . Exp[a a] normal form. *) VerificationTest[ BosonicExpOrder[Exp[k*\[FormalC]**\[FormalC]]** - Exp[m*SuperDagger[\[FormalC]]**SuperDagger[\[FormalC]]]], + Exp[m*SuperDagger[\[FormalC]]**SuperDagger[\[FormalC]]], $vC], E^((m*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalC]], 2])/ (1 - 4*k*m))**(1 - 4*k*m)^(-SuperDagger[\[FormalC]]**\[FormalC])** E^((k*GeneralizedPower[NonCommutativeMultiply, \[FormalC], 2])/(1 - 4*k*m))/Sqrt[1 - 4*k*m], @@ -333,7 +337,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[Exp[Conjugate[\[Lambda]]*\[FormalC]**\[FormalC]]** - Exp[\[Lambda]*SuperDagger[\[FormalC]]**SuperDagger[\[FormalC]]]], + Exp[\[Lambda]*SuperDagger[\[FormalC]]**SuperDagger[\[FormalC]]], $vC], E^((\[Lambda]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalC]], 2])/ (1 - 4*\[Lambda]*Conjugate[\[Lambda]]))**(1 - 4*\[Lambda]*Conjugate[\[Lambda]])^ (-SuperDagger[\[FormalC]]**\[FormalC])** @@ -346,7 +350,7 @@ VerificationTest[ comparison rounds every Real to twelve digits before matching. *) VerificationTest[ Evaluate[BosonicExpOrder[Exp[0.5*SuperDagger[\[FormalA]]**SuperDagger[\[FormalA]] - - 0.2*\[FormalA]**\[FormalA]]]], + 0.2*\[FormalA]**\[FormalA]], $vA]], E^(0.4425138959884551*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2])**(0.9103119246332295/ E^(0.18793592776541562*SuperDagger[\[FormalA]]**\[FormalA]))** @@ -360,7 +364,7 @@ VerificationTest[ keeping the su(1,1) structure the float form collapses. *) VerificationTest[ BosonicExpOrder[Exp[(1/2)*SuperDagger[\[FormalA]]**SuperDagger[\[FormalA]] - - (1/5)*\[FormalA]**\[FormalA]]], + (1/5)*\[FormalA]**\[FormalA]], $vA], E^((Sqrt[5/2]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]* Tanh[Sqrt[2/5]])/2)**Sech[Sqrt[2/5]]^(1/2 + SuperDagger[\[FormalA]]**\[FormalA])** E^(-((GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]*Tanh[Sqrt[2/5]])/Sqrt[10])), @@ -370,7 +374,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[ Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] - - \[Beta]*\[FormalA]**\[FormalA]]], + \[Beta]*\[FormalA]**\[FormalA]], $vA], E^((k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]* Tan[2*Sqrt[(-k)*\[Beta]]])/(2*Sqrt[(-k)*\[Beta]]))** Sec[2*Sqrt[(-k)*\[Beta]]]^(1/2 + SuperDagger[\[FormalA]]**\[FormalA])** @@ -382,7 +386,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[ Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] - - \[Beta]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]]], + \[Beta]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]], $vA], E^((k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]* Tan[2*Sqrt[(-k)*\[Beta]]])/(2*Sqrt[(-k)*\[Beta]]))** Sec[2*Sqrt[(-k)*\[Beta]]]^(1/2 + SuperDagger[\[FormalA]]**\[FormalA])** @@ -393,7 +397,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[Exp[(1/2)*(r/E^(I*\[Theta]))*\[FormalA]**\[FormalA] - - (1/2)*(r*E^(I*\[Theta]))*SuperDagger[\[FormalA]]**SuperDagger[\[FormalA]]], + (1/2)*(r*E^(I*\[Theta]))*SuperDagger[\[FormalA]]**SuperDagger[\[FormalA]]], $vA, Assumptions -> r > 0], E^((-(1/2))*E^(I*\[Theta])*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]*Tanh[r])**Sech[r]^(SuperDagger[\[FormalA]]**\[FormalA] + 1/2)** @@ -405,7 +409,7 @@ VerificationTest[ BosonicExpOrder[ Exp[(1/2)*(r*E^(I*\[Theta]))*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] - (1/2)*(r/E^(I*\[Theta]))* - GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]], Assumptions -> r > 0], + GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]], $vA, Assumptions -> r > 0], E^((1/2)*E^(I*\[Theta])*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]*Tanh[r])**Sech[r]^(1/2 + SuperDagger[\[FormalA]]**\[FormalA])** E^(((-(1/2))*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]*Tanh[r])/E^(I*\[Theta])), @@ -420,13 +424,13 @@ BeginTestSection["BosonicExpOrder - shift rules on exponential-polynomial produc (* Conjugating a polynomial by Exp[alpha a] / Exp[beta a^dagger] shifts the ladder operator it does not commute with: a^dagger -> a^dagger + alpha and a -> a + beta. *) VerificationTest[ - BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]]], + BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**SuperDagger[\[FormalA]], $vA], (\[Alpha] + SuperDagger[\[FormalA]])**E^(\[FormalA]*\[Alpha]), TestID -> "CoherentStateShift" ] VerificationTest[ - BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**(SuperDagger[\[FormalA]]**\[FormalA])], + BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**(SuperDagger[\[FormalA]]**\[FormalA]), $vA], (\[FormalA]*\[Alpha] + SuperDagger[\[FormalA]]**\[FormalA])** E^(\[FormalA]*\[Alpha]), TestID -> "NumberOperatorShift" @@ -434,21 +438,21 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[Exp[\[Alpha]*\[FormalA]]**(SuperDagger[\[FormalA]]** - SuperDagger[\[FormalA]])], + SuperDagger[\[FormalA]]), $vA], (\[Alpha]^2 + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] + 2*\[Alpha]*SuperDagger[\[FormalA]])**E^(\[FormalA]*\[Alpha]), TestID -> "TwoPhotonNormalShift" ] VerificationTest[ - BosonicExpOrder[\[FormalA]**Exp[\[Beta]*SuperDagger[\[FormalA]]]], + BosonicExpOrder[\[FormalA]**Exp[\[Beta]*SuperDagger[\[FormalA]]], $vA], E^(\[Beta]*SuperDagger[\[FormalA]])**(\[FormalA] + \[Beta]), TestID -> "SecondShiftAnnihilation" ] VerificationTest[ BosonicExpOrder[(SuperDagger[\[FormalA]]**\[FormalA])** - Exp[\[Beta]*SuperDagger[\[FormalA]]]], + Exp[\[Beta]*SuperDagger[\[FormalA]]], $vA], E^(\[Beta]*SuperDagger[\[FormalA]])**(SuperDagger[\[FormalA]]**\[FormalA] + \[Beta]*SuperDagger[\[FormalA]]), TestID -> "NumberOperatorShift2" @@ -456,7 +460,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[(SuperDagger[\[FormalA]]**\[FormalA]**\[FormalA])** - Exp[\[Beta]*SuperDagger[\[FormalA]]]], + Exp[\[Beta]*SuperDagger[\[FormalA]]], $vA], E^(\[Beta]*SuperDagger[\[FormalA]])** (2*\[Beta]*SuperDagger[\[FormalA]]**\[FormalA] + SuperDagger[\[FormalA]]** GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2] + @@ -466,7 +470,7 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[(SuperDagger[\[FormalA]]**\[FormalA]**\[FormalA] + y*\[FormalA])** - Exp[\[Beta]*SuperDagger[\[FormalA]]]], + Exp[\[Beta]*SuperDagger[\[FormalA]]], $vA], E^(\[Beta]*SuperDagger[\[FormalA]])**(y*\[FormalA] + y*\[Beta] + 2*\[Beta]*SuperDagger[\[FormalA]]**\[FormalA] + SuperDagger[\[FormalA]]** GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2] + @@ -485,43 +489,43 @@ BeginTestSection["BosonicExpOrder - generalized normal ordering"] VerificationTest[ BosonicExpOrder[ Exp[\[Kappa]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]** - \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 3]]], + \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 3]], $vA], NormalOrdered[ (1/(1 - 7*\[Kappa]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 7])^ (3/7))** E^((-1 + 1/(1 - 7*\[Kappa]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], - 7])^(1/7))**SuperDagger[\[FormalA]]**\[FormalA])], + 7])^(1/7))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedExtraForms1" ] VerificationTest[ BosonicExpOrder[ Exp[2*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]**\[FormalA]** - GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 4]]], + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 4]], $vA], NormalOrdered[ (1/Sqrt[1 - 16*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 8]])** E^((-1 + 1/(1 - 16*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 8])^ - (1/8))**SuperDagger[\[FormalA]]**\[FormalA])], + (1/8))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedExtraForms2" ] VerificationTest[ BosonicExpOrder[ Exp[0.3*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]**\[FormalA]** - GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]], + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA], NormalOrdered[ (1/(1 - 1.5*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5])^(1/5))** E^((-1 + 1/(1 - 1.5*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5])^ - (1/5))**SuperDagger[\[FormalA]]**\[FormalA])], + (1/5))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedExtraFormFloat" ] VerificationTest[ BosonicExpOrder[ Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]**\[FormalA]** - GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]], + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA], NormalOrdered[(1/(1 - k*SuperDagger[\[FormalA]]))** - E^((-1 + 1/(1 - k*SuperDagger[\[FormalA]]))**SuperDagger[\[FormalA]]**\[FormalA])], + E^((-1 + 1/(1 - k*SuperDagger[\[FormalA]]))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "NormalOrderedExtraForms3" ] @@ -536,7 +540,7 @@ BeginTestSection["BosonicExpOrder - series expansions"] VerificationTest[ normalizeIndex[ BosonicExpOrder[Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]** - \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]][ + \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA][ "Series", k], n], NormalOrdered[Inactive[Sum][k^n*SuperDagger[\[FormalA]]^n* DifferenceRoot[Function[{\[FormalY], \[FormalN]}, @@ -544,13 +548,13 @@ VerificationTest[ \[FormalY][2 + \[FormalN]]*(-4 - 3*\[FormalN] - \[FormalA]*SuperDagger[\[FormalA]]) + \[FormalY][1 + \[FormalN]]*(2 + 3*\[FormalN] + \[FormalA]*SuperDagger[\[FormalA]]) == 0, \[FormalY][-1] == 0, \[FormalY][0] == 0, \[FormalY][1] == 1}]][1 + n], - {n, 0, Infinity}]], + {n, 0, Infinity}], $vA], TestID -> "ShowCoefficientGenerator" ] VerificationTest[ BosonicExpOrder[Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]** - \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]][ + \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA][ "Series", k, 3], 1 + k^2*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] + k^3*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 3] + @@ -568,17 +572,17 @@ VerificationTest[ VerificationTest[ BosonicExpOrder[Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]** - \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]][ + \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA][ "Series", k, 3], Activate[BosonicExpOrder[Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], - 1]**\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]][ + 1]**\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA][ "Series", k]] /. Infinity -> 3, TestID -> "ActivateSumEqualsExplicitTruncation" ] VerificationTest[ Collect[BosonicExpOrder[Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], - 2]**\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]]][ + 2]**\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 1]], $vA][ "Series", k, 3], k], 1 + k*(GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] + GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 3]**\[FormalA]) + @@ -603,15 +607,15 @@ BeginTestSection["BosonicExpOrder - vanishing left ladder block"] (* The r = 0 case, Exp[lambda a (a^dagger)^s], and its truncated expansions. *) VerificationTest[ BosonicExpOrder[ - Exp[k*\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]]], + Exp[k*\[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]], $vA], NormalOrdered[(1/(-1 + k*SuperDagger[\[FormalA]])^2)** - E^((-1 + 1/(1 - k*SuperDagger[\[FormalA]]))**SuperDagger[\[FormalA]]**\[FormalA])], + E^((-1 + 1/(1 - k*SuperDagger[\[FormalA]]))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "OtherCaseZeroALeft" ] VerificationTest[ Collect[BosonicExpOrder[Exp[k*\[FormalA]**GeneralizedPower[NonCommutativeMultiply, - SuperDagger[\[FormalA]], 2]]]["Series", k, 2], k], + SuperDagger[\[FormalA]], 2]], $vA]["Series", k, 2], k], 1 + k*(GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]** \[FormalA] + 2*SuperDagger[\[FormalA]]) + k^2*(3*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] + @@ -627,9 +631,9 @@ VerificationTest[ sum reproduces the explicit order-3 truncation. *) VerificationTest[ Activate[BosonicExpOrder[Exp[k*\[FormalA]**GeneralizedPower[NonCommutativeMultiply, - SuperDagger[\[FormalA]], 2]]]["Series", k]] /. Infinity -> 3, + SuperDagger[\[FormalA]], 2]], $vA]["Series", k]] /. Infinity -> 3, BosonicExpOrder[Exp[k*\[FormalA]**GeneralizedPower[NonCommutativeMultiply, - SuperDagger[\[FormalA]], 2]]]["Series", k, 3], + SuperDagger[\[FormalA]], 2]], $vA]["Series", k, 3], TestID -> "ZeroALeftSeriesMatchesTruncation" ] @@ -641,16 +645,16 @@ BeginTestSection["BosonicExpOrder - vanishing right ladder block"] (* The s = 0 case, Exp[lambda (a^dagger)^r a]. *) VerificationTest[ BosonicExpOrder[ - Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]**\[FormalA]]], + Exp[k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]**\[FormalA]], $vA], NormalOrdered[ E^((-1 + 1/(1 - 4*k*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 4])^ - (1/4))**SuperDagger[\[FormalA]]**\[FormalA])], + (1/4))**SuperDagger[\[FormalA]]**\[FormalA]), $vA], TestID -> "OtherCaseZeroARight" ] VerificationTest[ Activate[BosonicExpOrder[Exp[\[Lambda]*GeneralizedPower[NonCommutativeMultiply, - SuperDagger[\[FormalA]], 5]**\[FormalA]]]["Series", \[Lambda]]] /. Infinity -> 3, + SuperDagger[\[FormalA]], 5]**\[FormalA]], $vA]["Series", \[Lambda]]] /. Infinity -> 3, 1 + \[Lambda]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 5]**\[FormalA] + (5/2)*\[Lambda]^2*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 9]**\[FormalA] + (1/2)*\[Lambda]^2* @@ -673,7 +677,7 @@ BeginTestSection["BosonicExpOrder - two modes"] a b^dagger + a^dagger b generator. *) VerificationTest[ BosonicExpOrder[Exp[(r*\[FormalA]**\[FormalB])/E^(I*\[Theta]) - - r*E^(I*\[Theta])*SuperDagger[\[FormalA]]**SuperDagger[\[FormalB]]], Assumptions -> r > 0], + r*E^(I*\[Theta])*SuperDagger[\[FormalA]]**SuperDagger[\[FormalB]]], $vAB, Assumptions -> r > 0], Sech[r]*(E^((-E^(I*\[Theta]))*SuperDagger[\[FormalA]]**SuperDagger[\[FormalB]]*Tanh[r])** Sech[r]^(SuperDagger[\[FormalA]]**\[FormalA] + SuperDagger[\[FormalB]]**\[FormalB])** E^((\[FormalA]**\[FormalB]*Tanh[r])/E^(I*\[Theta]))), @@ -696,10 +700,10 @@ VerificationTest[ exact = MatrixExp[(r E^(-I \[Theta]) am . bm - r E^(I \[Theta]) ConjugateTranspose[am] . ConjugateTranspose[bm]) /. pars][[idx, idx]]; Max[Abs[Normal[ToBosonicOperator[#, {\[FormalA], \[FormalB]}, s]["Matrix"]][[idx, idx]] - exact]] < 10^-12 & /@ { - BosonicExpOrder[Exp[gen], Assumptions -> r > 0] /. pars, - BosonicExpOrder[Exp[gen], Assumptions -> r > 0, "Ordering" -> "Antinormal"] /. pars, - BosonicExpOrder[Exp[gen /. pars]], - BosonicExpOrder[Exp[gen /. pars], "Ordering" -> "Antinormal"] + BosonicExpOrder[Exp[gen], $vAB, Assumptions -> r > 0] /. pars, + BosonicExpOrder[Exp[gen], $vAB, Assumptions -> r > 0, "Ordering" -> "Antinormal"] /. pars, + BosonicExpOrder[Exp[gen /. pars], $vAB], + BosonicExpOrder[Exp[gen /. pars], $vAB, "Ordering" -> "Antinormal"] } ], {True, True, True, True}, @@ -708,7 +712,7 @@ VerificationTest[ VerificationTest[ Simplify[BosonicExpOrder[Exp[\[Alpha]*\[FormalA]**SuperDagger[\[FormalB]] + - \[Beta]*SuperDagger[\[FormalA]]**\[FormalB]]]] /. {Sqrt[\[Alpha]*\[Beta]] -> \[Gamma], + \[Beta]*SuperDagger[\[FormalA]]**\[FormalB]], $vAB]] /. {Sqrt[\[Alpha]*\[Beta]] -> \[Gamma], 1/Sqrt[\[Alpha]*\[Beta]] -> 1/\[Gamma]}, E^((\[Beta]*SuperDagger[\[FormalA]]**\[FormalB]*Tanh[\[Gamma]])/\[Gamma])** Cosh[\[Gamma]]^(-SuperDagger[\[FormalA]]**\[FormalA] + SuperDagger[\[FormalB]]**\[FormalB])** @@ -726,7 +730,7 @@ VerificationTest[ am = Normal[AnnihilationOperator[big]["Matrix"]]; idx = Flatten[Table[s i + j + 1, {i, 0, 2}, {j, 0, 2}]]; ord = BosonicExpOrder[Exp[0.2 \[FormalA]]**Exp[0.3 SuperDagger[\[FormalB]]]** - Exp[-0.25 \[FormalB]]**Exp[0.15 SuperDagger[\[FormalA]]]]; + Exp[-0.25 \[FormalB]]**Exp[0.15 SuperDagger[\[FormalA]]], $vAB]; Max[Abs[Normal[ToBosonicOperator[ord, {\[FormalA], \[FormalB]}, s]["Matrix"]][[idx, idx]] - KroneckerProduct[ (MatrixExp[0.2 am] . MatrixExp[0.15 ConjugateTranspose[am]])[[;; 3, ;; 3]], @@ -741,7 +745,7 @@ VerificationTest[ another, so creators of any mode move left of annihilators of any other at no cost. The ranks are 1 for creator-only factors, 3 for annihilator-only, 2 otherwise. *) VerificationTest[ - BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Gamma] \[FormalB]]], + BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Gamma] \[FormalB]], $vAB], Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Alpha] \[FormalA]]**Exp[\[Gamma] \[FormalB]], TestID -> "TwoModeCreatorsMoveLeft" ] @@ -752,7 +756,7 @@ VerificationTest[ idx = Flatten[Table[s i + j + 1, {i, 0, 2}, {j, 0, 2}]]; rank = Which[FreeQ[#, SuperDagger], 3, FreeQ[# /. SuperDagger[_] -> 1, \[FormalA] | \[FormalB]], 1, True, 2] &; in = Exp[0.2 \[FormalA]]**Exp[0.3 SuperDagger[\[FormalB]]]**Exp[-0.25 \[FormalB]]**Exp[0.15 SuperDagger[\[FormalA]]]; - ord = BosonicExpOrder[in]; + ord = BosonicExpOrder[in, $vAB]; { rank /@ List @@ Replace[ord, c_ m_NonCommutativeMultiply /; FreeQ[c, \[FormalA] | \[FormalB]] :> m], Max[Abs[Normal[ToBosonicOperator[ord, {\[FormalA], \[FormalB]}, s]["Matrix"]][[idx, idx]] - @@ -774,7 +778,7 @@ BeginTestSection["BosonicExpOrder - products of three or more exponentials"] (* The rules repeat until nothing changes, so a reordering that exposes a new adjacent pair is followed through; a single pass left E^(gamma a) to the left of E^(beta a^dagger). *) VerificationTest[ - BosonicExpOrder[Exp[\[Gamma] \[FormalA]]**Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalA]]]], + BosonicExpOrder[Exp[\[Gamma] \[FormalA]]**Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalA]]], $vA], E^(\[Beta] (\[Alpha] + \[Gamma])) Exp[\[Beta] SuperDagger[\[FormalA]]]**Exp[(\[Alpha] + \[Gamma]) \[FormalA]], TestID -> "ThreeFactorProductNormalOrders" ] @@ -783,9 +787,9 @@ VerificationTest[ merge exactly; across modes, and with anything mixed, they stay apart. *) VerificationTest[ { - BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalA]]]**Exp[\[Gamma] \[FormalA]]], - BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Gamma] \[FormalA]]], - BosonicExpOrder[Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Delta] SuperDagger[\[FormalA]]]] + BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalA]]]**Exp[\[Gamma] \[FormalA]], $vA], + BosonicExpOrder[Exp[\[Alpha] \[FormalA]]**Exp[\[Gamma] \[FormalA]], $vA], + BosonicExpOrder[Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Delta] SuperDagger[\[FormalA]]], $vAB] }, { E^(\[Alpha] \[Beta]) Exp[\[Beta] SuperDagger[\[FormalA]]]**Exp[(\[Alpha] + \[Gamma]) \[FormalA]], @@ -801,7 +805,7 @@ VerificationTest[ Module[{size = 60, am, in, ord}, am = Normal[AnnihilationOperator[size]["Matrix"]]; in = NonCommutativeMultiply @@ Table[Exp[0.1 j SuperDagger[\[FormalA]] - 0.05 j \[FormalA]], {j, 8}]; - ord = BosonicExpOrder[in]; + ord = BosonicExpOrder[in, $vA]; { Length[Replace[ord, c_ m_NonCommutativeMultiply /; FreeQ[c, \[FormalA]] :> m]], Max[Abs[Normal[ToBosonicOperator[ord, {\[FormalA]}, size]["Matrix"]][[;; 12, ;; 12]] - @@ -815,15 +819,15 @@ VerificationTest[ (* Exact check, independent of the exponential rules: expand input and output to t^4 and normal-order both with BosonicNormalOrder. *) VerificationTest[ - Module[{vars = {\[FormalA], SuperDagger[\[FormalA]], \[FormalB], SuperDagger[\[FormalB]]}, + Module[{vars = $vAB, pars = {\[Alpha], \[Beta], \[Gamma], \[Delta]}, n = 4, t, nf}, nf[e_] := Module[{x = e /. Thread[pars -> t pars]}, - x = x /. Power[E, g_] /; ! FreeQ[g, Alternatives @@ vars] :> + x = x /. Power[E, g_] /; ! FreeQ[g, Alternatives @@ Flatten[vars]] :> Sum[If[k == 0, 1, NonCommutativeMultiply @@ ConstantArray[g, k]]/k!, {k, 0, n}]; - x = x /. Power[E, c_] /; FreeQ[c, Alternatives @@ vars] && ! FreeQ[c, t] :> Normal[Series[E^c, {t, 0, n}]]; + x = x /. Power[E, c_] /; FreeQ[c, Alternatives @@ Flatten[vars]] && ! FreeQ[c, t] :> Normal[Series[E^c, {t, 0, n}]]; x = Expand[NonCommutativeExpand[x]] /. t^k_Integer /; k > n -> 0; - Expand[BosonicNormalOrder[x, vars, "Scalars" -> Append[pars, t]]] /. t^k_Integer /; k > n -> 0]; - Simplify[Expand[nf[#] - nf[BosonicExpOrder[#]]]] & /@ { + Expand[BosonicNormalOrder[x, vars]] /. t^k_Integer /; k > n -> 0]; + Simplify[Expand[nf[#] - nf[BosonicExpOrder[#, vars]]]] & /@ { Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalA]]]**Exp[\[Gamma] \[FormalA]], Exp[\[Alpha] \[FormalA]]**Exp[\[Beta] SuperDagger[\[FormalB]]]**Exp[\[Gamma] \[FormalB]]**Exp[\[Delta] SuperDagger[\[FormalA]]] } @@ -838,7 +842,7 @@ VerificationTest[ FullSimplify[ BosonicMatrixElement[{1, 0}, Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]]** - Exp[\[Beta] SuperDagger[\[FormalA]] - Conjugate[\[Beta]] \[FormalA]]] - + Exp[\[Beta] SuperDagger[\[FormalA]] - Conjugate[\[Beta]] \[FormalA]], $vA] - Exp[-(\[Alpha] Conjugate[\[Alpha]] + \[Beta] Conjugate[\[Beta]])/2 - Conjugate[\[Alpha]] \[Beta]] (\[Alpha] + \[Beta]) ], 0, @@ -851,8 +855,8 @@ VerificationTest[ With[{d = Exp[\[Alpha] SuperDagger[\[FormalA]] - Conjugate[\[Alpha]] \[FormalA]]** Exp[\[Beta] SuperDagger[\[FormalA]] - Conjugate[\[Beta]] \[FormalA]]}, { - Count[BosonicExpOrder[Exp[\[Lambda] SuperDagger[\[FormalA]]**\[FormalA]]], _NormalOrdered, {0, Infinity}], - BosonicExpOrder[BosonicExpOrder[d]] === BosonicExpOrder[d] + Count[BosonicExpOrder[Exp[\[Lambda] SuperDagger[\[FormalA]]**\[FormalA]], $vA], _NormalOrdered, {0, Infinity}], + BosonicExpOrder[BosonicExpOrder[d, $vA], $vA] === BosonicExpOrder[d, $vA] } ], {1, True}, diff --git a/Tests/SecondQuantization/BosonicExpOrderAntinormal.wlt b/Tests/SecondQuantization/BosonicExpOrderAntinormal.wlt index dfb63544..f3360856 100644 --- a/Tests/SecondQuantization/BosonicExpOrderAntinormal.wlt +++ b/Tests/SecondQuantization/BosonicExpOrderAntinormal.wlt @@ -8,6 +8,9 @@ Needs["Wolfram`QuantumFramework`SecondQuantization`"] normalizeIndex[expr_, s_] := expr /. Inactive[Sum][b_, {i_, lo_, hi_}] :> Inactive[Sum][b /. i -> s, {s, lo, hi}] +$v1 = {{SuperDagger[\[FormalA]]}, {\[FormalA]}}; +$v2 = {{SuperDagger[\[FormalA]], SuperDagger[\[FormalB]]}, {\[FormalA], \[FormalB]}}; + (* The anti-normal rule set is the image of rulesNO under the automorphism a -> a^dagger, a^dagger -> -a, which carries creator-left words to annihilator-left ones and sends a^dagger a to -(a a^dagger + 1). Each expected form below was checked @@ -18,9 +21,9 @@ BeginTestSection["BosonicExpOrder - Ordering option"] (* the default must remain the normal-ordering behaviour that predates the option *) VerificationTest[ - BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]]] === + BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], $v1] === BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], - "Ordering" -> "Normal"], + $v1, "Ordering" -> "Normal"], True, TestID -> "BosonicExpAnti-DefaultIsNormal" ] @@ -29,7 +32,7 @@ VerificationTest[ loudly rather than fall through to one of them *) VerificationTest[ BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], - "Ordering" -> "NotAnOrdering"], + $v1, "Ordering" -> "NotAnOrdering"], $Failed, {BosonicExpOrder::ordering}, TestID -> "BosonicExpAnti-RejectsUnknownOrdering" @@ -44,8 +47,8 @@ BeginTestSection["BosonicExpOrder - anti-normal number-operator exponentials"] Equivalently (1-c)^-(n+1) with c = 1 - e^-l, which is where the sign flip comes from. *) VerificationTest[ BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]], - "Ordering" -> "Antinormal"], - AntinormalOrdered[E^((1 - E^(-\[Lambda]))*\[FormalA]**SuperDagger[\[FormalA]])], + $v1, "Ordering" -> "Antinormal"], + AntinormalOrdered[E^((1 - E^(-\[Lambda]))*\[FormalA]**SuperDagger[\[FormalA]]), $v1], TestID -> "BosonicExpAnti-NumberOperatorAAdag" ] @@ -53,9 +56,9 @@ VerificationTest[ absorbs into the AntinormalOrdered argument *) VerificationTest[ BosonicExpOrder[Exp[\[Lambda]*SuperDagger[\[FormalA]]**\[FormalA]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], AntinormalOrdered[ - E^(-\[Lambda] + (1 - E^(-\[Lambda]))*\[FormalA]**SuperDagger[\[FormalA]])], + E^(-\[Lambda] + (1 - E^(-\[Lambda]))*\[FormalA]**SuperDagger[\[FormalA]]), $v1], TestID -> "BosonicExpAnti-NumberOperatorAdagA" ] @@ -63,7 +66,7 @@ VerificationTest[ VerificationTest[ normalizeIndex[ BosonicExpOrder[Exp[\[Lambda]*\[FormalA]**SuperDagger[\[FormalA]]], - "Ordering" -> "Antinormal"]["Series"], k], + $v1, "Ordering" -> "Antinormal"]["Series"], k], Inactive[Sum][ ((1 - E^(-\[Lambda]))^k*GeneralizedPower[NonCommutativeMultiply, \[FormalA], k]** GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], k])/k!, @@ -79,7 +82,7 @@ BeginTestSection["BosonicExpOrder - anti-normal linear and quadratic rules"] (* Weyl splitting: the Gaussian prefactor flips sign and the factors swap order *) VerificationTest[ BosonicExpOrder[Exp[\[Alpha]*SuperDagger[\[FormalA]] + \[Beta]*\[FormalA]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], E^(\[FormalA]*\[Beta])**E^(\[Alpha]*SuperDagger[\[FormalA]])/E^((\[Alpha]*\[Beta])/2), TestID -> "BosonicExpAnti-WeylSplitting" ] @@ -87,7 +90,7 @@ VerificationTest[ (* the reordering rule matches the opposite input shape to its normal counterpart *) VerificationTest[ BosonicExpOrder[Exp[\[Beta]*SuperDagger[\[FormalA]]]**Exp[\[Alpha]*\[FormalA]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], E^(\[FormalA]*\[Alpha])**E^(\[Beta]*SuperDagger[\[FormalA]])/E^(\[Alpha]*\[Beta]), TestID -> "BosonicExpAnti-ReorderProduct" ] @@ -98,7 +101,7 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Beta]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]]** Exp[\[Alpha]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], E^((\[Alpha]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2])/ (1 - 4*\[Alpha]*\[Beta]))** (1 - 4*\[Alpha]*\[Beta])^(\[FormalA]**SuperDagger[\[FormalA]])** @@ -112,7 +115,7 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Alpha]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2] + \[Beta]*GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], E^((\[Alpha]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]* Tan[2*Sqrt[\[Alpha]*\[Beta]]])/(2*Sqrt[\[Alpha]*\[Beta]]))** Sec[2*Sqrt[\[Alpha]*\[Beta]]]^(1/2 - \[FormalA]**SuperDagger[\[FormalA]])** @@ -132,7 +135,7 @@ VerificationTest[ BosonicExpOrder[ (SuperDagger[\[FormalA]]**SuperDagger[\[FormalA]]**\[FormalA])** Exp[\[Alpha]*\[FormalA]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], E^(\[FormalA]*\[Alpha])**(2*\[Alpha] + \[FormalA]*\[Alpha]^2 + \[FormalA]**GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] - 2*\[Alpha]*\[FormalA]**SuperDagger[\[FormalA]] - 2*SuperDagger[\[FormalA]]), @@ -144,7 +147,7 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Beta]*SuperDagger[\[FormalA]]]** (SuperDagger[\[FormalA]]**\[FormalA]**\[FormalA]), - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], (-2*\[FormalA] + 2*\[Beta] - 2*\[Beta]*\[FormalA]**SuperDagger[\[FormalA]] + GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]**SuperDagger[\[FormalA]] + \[Beta]^2*SuperDagger[\[FormalA]])**E^(\[Beta]*SuperDagger[\[FormalA]]), @@ -164,13 +167,13 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Lambda]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]** SuperDagger[\[FormalA]]**\[FormalA]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], AntinormalOrdered[ (1/Sqrt[1 + 2*\[Lambda]* GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]])** E^((1 - 1/Sqrt[1 + 2*\[Lambda]* GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]])** - \[FormalA]**SuperDagger[\[FormalA]])], + \[FormalA]**SuperDagger[\[FormalA]]), $v1], TestID -> "BosonicExpAnti-Thm44-L2R1" ] @@ -179,11 +182,11 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Lambda]*SuperDagger[\[FormalA]]** GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], AntinormalOrdered[ (1 + \[FormalA]*\[Lambda])^(-2)** E^(((\[FormalA]*\[Lambda])/(1 + \[FormalA]*\[Lambda]))** - \[FormalA]**SuperDagger[\[FormalA]])], + \[FormalA]**SuperDagger[\[FormalA]]), $v1], TestID -> "BosonicExpAnti-Thm44-L0R2" ] @@ -192,10 +195,10 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Lambda]*GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2]** SuperDagger[\[FormalA]]], - "Ordering" -> "Antinormal"], + $v1, "Ordering" -> "Antinormal"], AntinormalOrdered[ E^(((\[FormalA]*\[Lambda])/(1 + \[FormalA]*\[Lambda]))** - \[FormalA]**SuperDagger[\[FormalA]])], + \[FormalA]**SuperDagger[\[FormalA]]), $v1], TestID -> "BosonicExpAnti-Thm44-L2R0" ] @@ -211,7 +214,7 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Alpha]*SuperDagger[\[FormalA]]**\[FormalB] + \[Beta]*\[FormalA]**SuperDagger[\[FormalB]]], - "Ordering" -> "Antinormal"], + $v2, "Ordering" -> "Antinormal"], E^((\[Beta]*\[FormalA]**SuperDagger[\[FormalB]]*Tanh[Sqrt[\[Alpha]*\[Beta]]])/ Sqrt[\[Alpha]*\[Beta]])** Cosh[Sqrt[\[Alpha]*\[Beta]]]^(\[FormalA]**SuperDagger[\[FormalA]] - @@ -226,7 +229,7 @@ VerificationTest[ BosonicExpOrder[ Exp[\[Alpha]*\[FormalA]**\[FormalB] + \[Beta]*SuperDagger[\[FormalA]]**SuperDagger[\[FormalB]]], - "Ordering" -> "Antinormal"], + $v2, "Ordering" -> "Antinormal"], Sec[Sqrt[\[Alpha]*\[Beta]]]*(E^((\[Alpha]*\[FormalA]**\[FormalB]*Tan[Sqrt[\[Alpha]*\[Beta]]])/ Sqrt[\[Alpha]*\[Beta]])** Sec[Sqrt[\[Alpha]*\[Beta]]]^(-\[FormalA]**SuperDagger[\[FormalA]] - @@ -245,7 +248,7 @@ VerificationTest[ am = Normal[AnnihilationOperator[big]["Matrix"]]; idx = Flatten[Table[s i + j + 1, {i, 0, 2}, {j, 0, 2}]]; ord = BosonicExpOrder[Exp[0.15 SuperDagger[\[FormalA]]]**Exp[-0.25 \[FormalB]]** - Exp[0.3 SuperDagger[\[FormalB]]]**Exp[0.2 \[FormalA]], "Ordering" -> "Antinormal"]; + Exp[0.3 SuperDagger[\[FormalB]]]**Exp[0.2 \[FormalA]], $v2, "Ordering" -> "Antinormal"]; Max[Abs[Normal[ToBosonicOperator[ord, {\[FormalA], \[FormalB]}, s]["Matrix"]][[idx, idx]] - KroneckerProduct[ (MatrixExp[0.15 ConjugateTranspose[am]] . MatrixExp[0.2 am])[[;; 3, ;; 3]], @@ -263,7 +266,7 @@ VerificationTest[ idx = Flatten[Table[s i + j + 1, {i, 0, 2}, {j, 0, 2}]]; rank = Which[FreeQ[#, SuperDagger], 3, FreeQ[# /. SuperDagger[_] -> 1, \[FormalA] | \[FormalB]], 1, True, 2] &; in = Exp[0.15 SuperDagger[\[FormalA]]]**Exp[0.3 SuperDagger[\[FormalB]]]**Exp[-0.25 \[FormalB]]**Exp[0.2 \[FormalA]]; - ord = BosonicExpOrder[in, "Ordering" -> "Antinormal"]; + ord = BosonicExpOrder[in, $v2, "Ordering" -> "Antinormal"]; { rank /@ List @@ Replace[ord, c_ m_NonCommutativeMultiply /; FreeQ[c, \[FormalA] | \[FormalB]] :> m], Max[Abs[Normal[ToBosonicOperator[ord, {\[FormalA], \[FormalB]}, s]["Matrix"]][[idx, idx]] - diff --git a/Tests/SecondQuantization/BosonicExpSimplify.wlt b/Tests/SecondQuantization/BosonicExpSimplify.wlt index edbceb27..c2e04c78 100644 --- a/Tests/SecondQuantization/BosonicExpSimplify.wlt +++ b/Tests/SecondQuantization/BosonicExpSimplify.wlt @@ -6,6 +6,7 @@ Needs["Wolfram`QuantumFramework`SecondQuantization`"] $a = \[FormalA]; $ad = SuperDagger[\[FormalA]]; $n = $ad ** $a; +$vars = {{$ad}, {$a}}; (* Displacement generator \[Alpha] a\[Dagger] - Conjugate[\[Alpha]] a. *) $disp = \[Alpha] $ad - Conjugate[\[Alpha]] $a; @@ -23,7 +24,7 @@ BeginTestSection["BosonicExpSimplify - adjacent pair reduction"] (* [\[Alpha] a\[Dagger], \[Beta] a] = -\[Alpha]\[Beta] is a c-number, so the Weyl/BCH shortcut applies. *) VerificationTest[ - BosonicExpSimplify[Exp[\[Alpha] $ad] ** Exp[\[Beta] $a]], + BosonicExpSimplify[Exp[\[Alpha] $ad] ** Exp[\[Beta] $a], $vars], Exp[-\[Alpha] \[Beta]/2] Exp[\[Alpha] $ad + \[Beta] $a], {}, TestID -> "BosonicExpSimplify-WeylPairCentralCommutator" @@ -33,7 +34,7 @@ VerificationTest[ own, so compare the generators rather than their printed form. *) VerificationTest[ sameGeneratorQ[ - BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[\[Gamma] $n]], + BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[\[Gamma] $n], $vars], (\[Beta] + \[Gamma]) $n ], True, @@ -44,7 +45,7 @@ VerificationTest[ (* An exponential times its inverse must collapse to the identity, not to a two-factor product. This is the pre-pass that In[77] needed. *) VerificationTest[ - BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[-\[Beta] $n]], + BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[-\[Beta] $n], $vars], 1, {}, TestID -> "BosonicExpSimplify-InversePairCancels" @@ -54,7 +55,7 @@ VerificationTest[ an adjacent window, not the whole expression. *) VerificationTest[ BosonicExpSimplify[ - Exp[\[Alpha] $ad] ** Exp[\[Beta] $n] ** Exp[-\[Beta] $n] ** Exp[\[Gamma] $a]], + Exp[\[Alpha] $ad] ** Exp[\[Beta] $n] ** Exp[-\[Beta] $n] ** Exp[\[Gamma] $a], $vars], Exp[-\[Alpha] \[Gamma]/2] Exp[\[Alpha] $ad + \[Gamma] $a], {}, TestID -> "BosonicExpSimplify-InversePairInsideLongerProduct" @@ -69,7 +70,7 @@ BeginTestSection["BosonicExpSimplify - conjugation"] VerificationTest[ sameGeneratorQ[ FullSimplify @ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n]], + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n], $vars], \[Alpha] Exp[\[Beta]] $ad - Conjugate[\[Alpha]] Exp[-\[Beta]] $a ], True, @@ -83,7 +84,7 @@ VerificationTest[ sameGeneratorQ[ FullSimplify[ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n]] /. \[Beta] -> -I \[Omega] t], + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n], $vars] /. \[Beta] -> -I \[Omega] t], \[Alpha] Exp[-I \[Omega] t] $ad - Conjugate[\[Alpha]] Exp[I \[Omega] t] $a ], True, @@ -96,7 +97,7 @@ VerificationTest[ so only the per-factor distribution can finish it: e^(\[Alpha] a\[Dagger]) a a e^(-\[Alpha] a\[Dagger]) = (a - \[Alpha])(a - \[Alpha]). *) VerificationTest[ - BosonicExpSimplify[Exp[\[Alpha] $ad] ** $a ** $a ** Exp[-\[Alpha] $ad]], + BosonicExpSimplify[Exp[\[Alpha] $ad] ** $a ** $a ** Exp[-\[Alpha] $ad], $vars], ($a - \[Alpha]) ** ($a - \[Alpha]), {}, TestID -> "BosonicExpSimplify-ConjugationDistributesOverFactors" @@ -106,7 +107,7 @@ VerificationTest[ Flat pattern lets the single-factor rule absorb the run: e^(\[Beta] n) a\[Dagger] a e^(-\[Beta] n) = a\[Dagger] a. *) VerificationTest[ - BosonicExpSimplify[Exp[\[Beta] $n] ** $ad ** $a ** Exp[-\[Beta] $n]], + BosonicExpSimplify[Exp[\[Beta] $n] ** $ad ** $a ** Exp[-\[Beta] $n], $vars], $ad ** $a, {}, TestID -> "BosonicExpSimplify-ConjugationOfNumberOperatorIsFixed" @@ -123,7 +124,7 @@ BeginTestSection["BosonicExpSimplify - four-factor gap"] VerificationTest[ sameGeneratorQ[ FullSimplify @ First @ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n]], + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n], $vars], \[Alpha] Exp[\[Beta]] $ad - Conjugate[\[Alpha]] Exp[-\[Beta]] $a ], True, @@ -133,7 +134,7 @@ VerificationTest[ VerificationTest[ Last @ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n]], + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n], $vars], Exp[\[Beta] $n], {}, TestID -> "BosonicExpSimplify-FourFactorSecondFactorIsNumberExponential" @@ -141,7 +142,7 @@ VerificationTest[ VerificationTest[ Length @ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n]], + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n], $vars], 2, {}, TestID -> "BosonicExpSimplify-FourFactorReducesToTwoFactors" @@ -156,14 +157,14 @@ BeginTestSection["BosonicExpSimplify - declines silently"] claimed. The input must come back untouched and, crucially, with no NonCommutativePolynomialReduce::ncpv leaking out of the internals. *) VerificationTest[ - BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[$disp]], + BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[$disp], $vars], Exp[\[Beta] $n] ** Exp[$disp], {}, TestID -> "BosonicExpSimplify-NonCentralPairReturnsInputSilently" ] VerificationTest[ - BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[$disp] ** Exp[\[Beta] $n]], + BosonicExpSimplify[Exp[\[Beta] $n] ** Exp[$disp] ** Exp[\[Beta] $n], $vars], Exp[\[Beta] $n] ** Exp[$disp] ** Exp[\[Beta] $n], {}, TestID -> "BosonicExpSimplify-NonInverseSandwichReturnsInputSilently" @@ -176,7 +177,7 @@ BeginTestSection["BosonicExpSimplify - polynomial past exponential"] (* a e^(\[Alpha] a\[Dagger]) = e^(\[Alpha] a\[Dagger]) (a + \[Alpha]). *) VerificationTest[ - BosonicExpSimplify[$a ** Exp[\[Alpha] $ad]], + BosonicExpSimplify[$a ** Exp[\[Alpha] $ad], $vars], Exp[\[Alpha] $ad] ** (\[Alpha] + $a), {}, TestID -> "BosonicExpSimplify-PolynomialPastCreationExponential" @@ -201,7 +202,7 @@ VerificationTest[ MatrixExp[(\[Alpha] /. num) ad - Conjugate[\[Alpha] /. num] av]; (* Scalars before matrices, so MatrixExp only sees a numeric matrix. *) expo = FullSimplify @ exponentOf @ First @ BosonicExpSimplify[ - Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n]]; + Exp[\[Beta] $n] ** Exp[$disp] ** Exp[-\[Beta] $n] ** Exp[\[Beta] $n], $vars]; rhs = MatrixExp[expo /. num /. {$ad -> ad, $a -> av}] . MatrixExp[(\[Beta] /. num) nOp]; blk = Normal[#][[;; keep, ;; keep]] &; @@ -226,6 +227,7 @@ $squeeze[z_] := Exp[1/2 Conjugate[z] $a ** $a - 1/2 z $ad ** $ad]; VerificationTest[ BosonicExpSimplify[ $squeeze[-r E^(I \[Theta])] ** $a ** $squeeze[r E^(I \[Theta])], + $vars, Assumptions -> r > 0 && \[Theta] \[Element] Reals ], $a Cosh[r] - E^(I \[Theta]) Sinh[r] $ad, @@ -236,6 +238,7 @@ VerificationTest[ VerificationTest[ BosonicExpSimplify[ $squeeze[-r E^(I \[Theta])] ** $ad ** $squeeze[r E^(I \[Theta])], + $vars, Assumptions -> r > 0 && \[Theta] \[Element] Reals ], $ad Cosh[r] - E^(-I \[Theta]) Sinh[r] $a, @@ -243,24 +246,23 @@ VerificationTest[ TestID -> "BosonicExpSimplify-AssumptionsSqueezedCreation" ] -(* The option must survive the explicit-vars overload alongside "Scalars". *) +(* A WeylAlgebra declares the same ladder operators as the lists, and the option survives it. *) VerificationTest[ BosonicExpSimplify[ $squeeze[-r E^(I \[Theta])] ** $a ** $squeeze[r E^(I \[Theta])], - {$a, $ad}, - "Scalars" -> {r, \[Theta]}, + WeylAlgebra[$vars], Assumptions -> r > 0 && \[Theta] \[Element] Reals ], $a Cosh[r] - E^(I \[Theta]) Sinh[r] $ad, {}, - TestID -> "BosonicExpSimplify-AssumptionsWithExplicitVars" + TestID -> "BosonicExpSimplify-AssumptionsWithWeylAlgebra" ] (* Assumptions are additive only: with none supplied the result must still be the unassumed closed form, equal to the assumed one under Simplify. *) VerificationTest[ Simplify[ - BosonicExpSimplify[$squeeze[-r E^(I \[Theta])] ** $a ** $squeeze[r E^(I \[Theta])]] - + BosonicExpSimplify[$squeeze[-r E^(I \[Theta])] ** $a ** $squeeze[r E^(I \[Theta])], $vars] - ($a Cosh[r] - E^(I \[Theta]) Sinh[r] $ad), r > 0 && \[Theta] \[Element] Reals ], diff --git a/Tests/SecondQuantization/BosonicMatrixElement.wlt b/Tests/SecondQuantization/BosonicMatrixElement.wlt index 4d98054d..3e81917a 100644 --- a/Tests/SecondQuantization/BosonicMatrixElement.wlt +++ b/Tests/SecondQuantization/BosonicMatrixElement.wlt @@ -1,27 +1,28 @@ Needs["Wolfram`QuantumFramework`"] Needs["Wolfram`QuantumFramework`SecondQuantization`"] -{av, adv} = FieldVariables[]; +$v = FieldVariables[]; +{{adv}, {av}} = $v; BeginTestSection["BosonicMatrixElement - Fock basis (default)"] (* = Sqrt[m] Sqrt[n] delta[m-1, n-1], the number operator with symbolic indices *) VerificationTest[ - BosonicMatrixElement[{m, n}, adv ** av], + BosonicMatrixElement[{m, n}, adv ** av, $v], Sqrt[m] Sqrt[n] KroneckerDelta[m - 1, n - 1], TestID -> "BME-Fock-NumberOperator-Symbolic" ] VerificationTest[ - BosonicMatrixElement[{3, 3}, adv ** av], + BosonicMatrixElement[{3, 3}, adv ** av, $v], 3, TestID -> "BME-Fock-NumberOperator-Integer" ] (* a lowers: is nonzero only for m = n - 1 *) VerificationTest[ - BosonicMatrixElement[{m, n}, av], + BosonicMatrixElement[{m, n}, av, $v], Sqrt[n] KroneckerDelta[m, n - 1], TestID -> "BME-Fock-Annihilation" ] @@ -36,7 +37,7 @@ VerificationTest[ (* The canonical commutation relation as a matrix element: = delta[m, n]. Commutator expands to the NonCommutativeMultiply form the reducer expects. *) VerificationTest[ - BosonicMatrixElement[{m, n}, Commutator[av, adv]], + BosonicMatrixElement[{m, n}, Commutator[av, adv], $v], KroneckerDelta[m, n], TestID -> "BME-Fock-CanonicalCommutator" ] @@ -48,7 +49,7 @@ BeginTestSection["BosonicMatrixElement - coherent basis"] (* Coherent states are eigenstates of a, so = alpha and = 1 *) VerificationTest[ - Simplify[BosonicMatrixElement[{\[Alpha], \[Alpha]}, av, "Basis" -> "Coherent"], + Simplify[BosonicMatrixElement[{\[Alpha], \[Alpha]}, av, $v, "Basis" -> "Coherent"], \[Alpha] \[Element] Reals], \[Alpha], TestID -> "BME-Coherent-Annihilation-Diagonal" @@ -63,7 +64,7 @@ VerificationTest[ (* Normal ordering carries over to the coherent basis unchanged *) VerificationTest[ - Simplify[BosonicMatrixElement[{\[Alpha], \[Alpha]}, Commutator[av, adv], "Basis" -> "Coherent"], + Simplify[BosonicMatrixElement[{\[Alpha], \[Alpha]}, Commutator[av, adv], $v, "Basis" -> "Coherent"], \[Alpha] \[Element] Reals], 1, TestID -> "BME-Coherent-CanonicalCommutator" @@ -89,7 +90,7 @@ BeginTestSection["BosonicMatrixElement - cat-code matrix elements"] ClearAll[catRaw, catNorm, catElem, comb, catBlock] catRaw[w1_, w2_, expr_] := Total[Flatten @ Outer[ - Conjugate[#1[[1]]] #2[[1]] BosonicMatrixElement[{#1[[2]], #2[[2]]}, expr, "Basis" -> "Coherent"] &, + Conjugate[#1[[1]]] #2[[1]] BosonicMatrixElement[{#1[[2]], #2[[2]]}, expr, $v, "Basis" -> "Coherent"] &, w1, w2, 1]] catNorm[w_] := Sqrt[catRaw[w, w, 1]] catElem[w1_, w2_, expr_] := FullSimplify[catRaw[w1, w2, expr]/(catNorm[w1] catNorm[w2]), @@ -136,7 +137,7 @@ BeginTestSection["BosonicMatrixElement - exponentials"] (* A function of the number operator is diagonal. This one is the no-jump factor of the photon-loss channel, which is not a polynomial and so had no route before. *) VerificationTest[ - BosonicMatrixElement[{m, k}, \[Eta]^((adv ** av)/2)], + BosonicMatrixElement[{m, k}, \[Eta]^((adv ** av)/2), $v], \[Eta]^(k/2) KroneckerDelta[m, k], TestID -> "BME-Exp-NumberDiagonal" ] @@ -144,8 +145,8 @@ VerificationTest[ (* A wing is an exponential of one operator alone, evaluated as a Taylor coefficient of Exp[P]. A quadratic wing raises two levels at a time, so odd differences vanish. *) VerificationTest[ - {BosonicMatrixElement[{4, 0}, Exp[s adv ** adv]], - BosonicMatrixElement[{3, 0}, Exp[s adv ** adv]]}, + {BosonicMatrixElement[{4, 0}, Exp[s adv ** adv], $v], + BosonicMatrixElement[{3, 0}, Exp[s adv ** adv], $v]}, {Sqrt[6] s^2, 0}, TestID -> "BME-Exp-QuadraticWingParity" ] @@ -153,7 +154,7 @@ VerificationTest[ (* An exponential mixing the two operators is disentangled first. Cross-checked against MatrixExp on a 40-level truncation, which gives 1.8682476751142998. *) VerificationTest[ - Chop[N[BosonicMatrixElement[{6, 2}, Exp[av + adv]]] - 1.8682476751142998], + Chop[N[BosonicMatrixElement[{6, 2}, Exp[av + adv], $v]] - 1.8682476751142998], 0, TestID -> "BME-Exp-MixedDisentangles" ] @@ -162,8 +163,8 @@ VerificationTest[ closed form the SqueezeOperator clause gives for the same operator. *) VerificationTest[ With[{sd = BosonicExpOrder[ - Exp[(Conjugate[\[Xi]] av ** av - \[Xi] adv ** adv)/2], \[Xi] > 0] /. \[Xi] -> 0.4}, - Chop[BosonicMatrixElement[{2, 0}, Evaluate[sd]] - + Exp[(Conjugate[\[Xi]] av ** av - \[Xi] adv ** adv)/2], $v, Assumptions -> \[Xi] > 0] /. \[Xi] -> 0.4}, + Chop[BosonicMatrixElement[{2, 0}, Evaluate[sd], $v] - BosonicMatrixElement[{2, 0}, SqueezeOperator[0.4]]]], 0, TestID -> "BME-Exp-SqueezeMatchesNamed" @@ -174,10 +175,10 @@ VerificationTest[ wrong by the exponential of the commutator. It is declined and then disentangled, so both spellings of the same operator agree. *) VerificationTest[ - With[{no = BosonicExpOrder[Exp[0.7 adv - 0.4 av]], - an = BosonicExpOrder[Exp[0.7 adv - 0.4 av], "Ordering" -> "Antinormal"]}, - Chop[BosonicMatrixElement[{3, 2}, Evaluate[an]] - - BosonicMatrixElement[{3, 2}, Evaluate[no]]]], + With[{no = BosonicExpOrder[Exp[0.7 adv - 0.4 av], $v], + an = BosonicExpOrder[Exp[0.7 adv - 0.4 av], $v, "Ordering" -> "Antinormal"]}, + Chop[BosonicMatrixElement[{3, 2}, Evaluate[an], $v] - + BosonicMatrixElement[{3, 2}, Evaluate[no], $v]]], 0, TestID -> "BME-Exp-AntinormalNotReordered" ] @@ -192,14 +193,14 @@ BeginTestSection["BosonicMatrixElement - vanishing powers at the vacuum"] The whole n = 0 column is at stake: an off-diagonal zero there must not come out as 0^0 times a vanishing Kronecker delta. *) VerificationTest[ - Table[BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-adv ** av]]], {m, 0, 3}, {n, 0, 3}], + Table[BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-adv ** av], $v], $v], {m, 0, 3}, {n, 0, 3}], Table[KroneckerDelta[m, 0] KroneckerDelta[n, 0], {m, 0, 3}, {n, 0, 3}], TestID -> "BME-Vacuum-ProjectorFock" ] (* The closed form for symbolic indices must remain right when the indices reach the vacuum. *) VerificationTest[ - With[{e = BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-adv ** av]]]}, + With[{e = BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-adv ** av], $v], $v]}, {e /. {m -> 0, n -> 0}, e /. {m -> 2, n -> 2}, e /. {m -> 1, n -> 0}}], {1, 0, 0}, TestID -> "BME-Vacuum-ProjectorSymbolicIndex" @@ -208,14 +209,14 @@ VerificationTest[ (* A machine-precision -1. leaves a base of 0. rather than an exact 0, and the elements stay machine numbers. *) VerificationTest[ - Table[BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-1. adv ** av]]], {m, 0, 2}, {n, 0, 2}], + Table[BosonicMatrixElement[{m, n}, NormalOrdered[Exp[-1. adv ** av], $v], $v], {m, 0, 2}, {n, 0, 2}], {{1., 0., 0.}, {0., 0., 0.}, {0., 0., 0.}}, TestID -> "BME-Vacuum-ProjectorMachineCoefficient" ] (* 0^(-ad a) is unbounded off the vacuum: it must not be read as the vacuum projector. *) VerificationTest[ - BosonicMatrixElement[{1, 1}, 0^(-adv ** av)], + BosonicMatrixElement[{1, 1}, 0^(-adv ** av), $v], ComplexInfinity, {Power::infy}, TestID -> "BME-Vacuum-NegativePowerUnbounded" @@ -226,7 +227,7 @@ VerificationTest[ not only the vacuum one, passes through the n = 0 term of the middle sum. *) VerificationTest[ Simplify[ - Table[BosonicMatrixElement[{m, n}, Exp[z adv] ** NormalOrdered[Exp[-adv ** av]] ** Exp[w av]], + Table[BosonicMatrixElement[{m, n}, Exp[z adv] ** NormalOrdered[Exp[-adv ** av], $v] ** Exp[w av], $v], {m, 0, 2}, {n, 0, 2}] - Table[z^m w^n/Sqrt[m! n!], {m, 0, 2}, {n, 0, 2}]], ConstantArray[0, {3, 3}], @@ -236,14 +237,14 @@ VerificationTest[ (* Total loss: the no-jump Kraus operator eta^(ad a/2) of the photon-loss channel at eta = 0 keeps only the vacuum. *) VerificationTest[ - Table[BosonicMatrixElement[{m, n}, 0^((adv ** av)/2)], {m, 0, 2}, {n, 0, 2}], + Table[BosonicMatrixElement[{m, n}, 0^((adv ** av)/2), $v], {m, 0, 2}, {n, 0, 2}], Table[KroneckerDelta[m, 0] KroneckerDelta[n, 0], {m, 0, 2}, {n, 0, 2}], TestID -> "BME-Vacuum-FullLossNoJump" ] (* Between coherent states the projector gives <0|beta>. *) VerificationTest[ - Simplify[BosonicMatrixElement[{\[Alpha], \[Beta]}, NormalOrdered[Exp[-adv ** av]], "Basis" -> "Coherent"] - + Simplify[BosonicMatrixElement[{\[Alpha], \[Beta]}, NormalOrdered[Exp[-adv ** av], $v], $v, "Basis" -> "Coherent"] - Exp[-(Abs[\[Alpha]]^2 + Abs[\[Beta]]^2)/2]], 0, TestID -> "BME-Vacuum-ProjectorCoherent" @@ -253,9 +254,9 @@ VerificationTest[ <0|0><0|beta> = <0|beta>, <0|0><0|0> = 1, and Exp[lambda ad a] fixes the vacuum. *) VerificationTest[ Simplify[{ - BosonicMatrixElement[{0, \[Beta]}, NormalOrdered[Exp[-adv ** av]], "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2], - BosonicMatrixElement[{0, 0}, NormalOrdered[Exp[-adv ** av]], "Basis" -> "Coherent"] - 1, - BosonicMatrixElement[{0, \[Beta]}, Exp[\[Lambda] adv ** av], "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2] + BosonicMatrixElement[{0, \[Beta]}, NormalOrdered[Exp[-adv ** av], $v], $v, "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2], + BosonicMatrixElement[{0, 0}, NormalOrdered[Exp[-adv ** av], $v], $v, "Basis" -> "Coherent"] - 1, + BosonicMatrixElement[{0, \[Beta]}, Exp[\[Lambda] adv ** av], $v, "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2] }], {0, 0, 0}, TestID -> "BME-Vacuum-ProjectorCoherentZeroAmplitude" @@ -266,9 +267,9 @@ VerificationTest[ carries the power 0 for every operator it does not touch. *) VerificationTest[ Simplify[{ - BosonicMatrixElement[{0, \[Beta]}, av, "Basis" -> "Coherent"] - \[Beta] Exp[-Abs[\[Beta]]^2/2], - BosonicMatrixElement[{\[Alpha], 0}, adv, "Basis" -> "Coherent"] - Conjugate[\[Alpha]] Exp[-Abs[\[Alpha]]^2/2], - BosonicMatrixElement[{0, \[Beta]}, 1 + adv ** av, "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2] + BosonicMatrixElement[{0, \[Beta]}, av, $v, "Basis" -> "Coherent"] - \[Beta] Exp[-Abs[\[Beta]]^2/2], + BosonicMatrixElement[{\[Alpha], 0}, adv, $v, "Basis" -> "Coherent"] - Conjugate[\[Alpha]] Exp[-Abs[\[Alpha]]^2/2], + BosonicMatrixElement[{0, \[Beta]}, 1 + adv ** av, $v, "Basis" -> "Coherent"] - Exp[-Abs[\[Beta]]^2/2] }], {0, 0, 0}, TestID -> "BME-Vacuum-CoherentZeroAmplitude" @@ -279,7 +280,7 @@ VerificationTest[ VerificationTest[ With[{b = FieldVariables[{1, 2}]}, Simplify[ - BosonicMatrixElement[{{0, \[Alpha]}, {0, \[Beta]}}, 1 + b[[2]] ** b[[1]] + b[[4]] ** b[[3]], + BosonicMatrixElement[{{0, \[Alpha]}, {0, \[Beta]}}, 1 + b[[1, 1]] ** b[[2, 1]] + b[[1, 2]] ** b[[2, 2]], b, "Basis" -> "Coherent"] - (1 + Conjugate[\[Alpha]] \[Beta]) Exp[Conjugate[\[Alpha]] \[Beta] - (Abs[\[Alpha]]^2 + Abs[\[Beta]]^2)/2]]], 0, @@ -291,40 +292,39 @@ EndTestSection[] BeginTestSection["BosonicMatrixElement - independent modes"] -{b1, bd1, b2, bd2} = FieldVariables[{1, 2}]; +$v2 = FieldVariables[{1, 2}]; +{{bd1, bd2}, {b1, b2}} = $v2; (* Distinct modes commute and the Fock space is their tensor product, so the element of a normally ordered monomial is one single-mode element per mode, multiplied. *) VerificationTest[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1 ** bd2 ** b2], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1 ** bd2 ** b2, $v2], Sqrt[m1] Sqrt[m2] Sqrt[n1] Sqrt[n2] KroneckerDelta[m1 - 1, n1 - 1] KroneckerDelta[m2 - 1, n2 - 1], TestID -> "BME-Modes-NumberProduct" ] VerificationTest[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b2], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b2, $v2], Sqrt[m1] Sqrt[n2] KroneckerDelta[m1 - 1, n1] KroneckerDelta[m2, n2 - 1], TestID -> "BME-Modes-CrossMode" ] -(* Inferred modes are sorted, so index slot 1 belongs to the first label however the - operator happens to be written. *) +(* Index slot k belongs to mode k of vars however the operator happens to be written. *) VerificationTest[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd2 ** b1], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd2 ** b1, $v2], Sqrt[n1] Sqrt[m2] KroneckerDelta[m1, n1 - 1] KroneckerDelta[m2 - 1, n2], TestID -> "BME-Modes-InferredOrderSorted" ] -(* An operator that leaves a mode alone cannot name it, so the modes are declared; the idle - mode then contributes the identity. Declared generators keep the order given. *) +(* A mode the operator leaves alone contributes the identity, and the declared order is kept. *) VerificationTest[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1, "Generators" -> {b1, bd1, b2, bd2}], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1, $v2], Sqrt[m1] Sqrt[n1] KroneckerDelta[m1 - 1, n1 - 1] KroneckerDelta[m2, n2], TestID -> "BME-Modes-IdleModeDeclared" ] VerificationTest[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1, "Generators" -> {b2, bd2, b1, bd1}], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1, {{bd2, bd1}, {b2, b1}}], Sqrt[m2] Sqrt[n2] KroneckerDelta[m1, n1] KroneckerDelta[m2 - 1, n2 - 1], TestID -> "BME-Modes-DeclaredOrderKept" ] @@ -332,9 +332,9 @@ VerificationTest[ (* A product of single-mode operators factorizes into their single-mode elements. *) VerificationTest[ Simplify[ - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, (b1 + bd1) ** (b1 + bd1) ** bd2 ** b2 ** b2] - - BosonicMatrixElement[{m1, n1}, (b1 + bd1) ** (b1 + bd1), "Generators" -> {b1, bd1}] * - BosonicMatrixElement[{m2, n2}, bd2 ** b2 ** b2, "Generators" -> {b2, bd2}] + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, (b1 + bd1) ** (b1 + bd1) ** bd2 ** b2 ** b2, $v2] - + BosonicMatrixElement[{m1, n1}, (b1 + bd1) ** (b1 + bd1), {{bd1}, {b1}}] * + BosonicMatrixElement[{m2, n2}, bd2 ** b2 ** b2, {{bd2}, {b2}}] ], 0, TestID -> "BME-Modes-ProductFactorizes" @@ -351,7 +351,7 @@ VerificationTest[ b2 -> KroneckerProduct[one, low], bd2 -> KroneckerProduct[one, Transpose[low]]}]}, Count[Tuples[Tuples[Range[0, 2], 2], 2], {{i1_, i2_}, {j1_, j2_}} /; - Simplify[BosonicMatrixElement[{{i1, i2}, {j1, j2}}, op] - mat[[i1 d + i2 + 1, j1 d + j2 + 1]]] =!= 0] + Simplify[BosonicMatrixElement[{{i1, i2}, {j1, j2}}, op, $v2] - mat[[i1 d + i2 + 1, j1 d + j2 + 1]]] =!= 0] ] ] ], @@ -362,8 +362,8 @@ VerificationTest[ (* Coherent states factorize too: the overlap is a product of single-mode overlaps. *) VerificationTest[ Simplify[ - BosonicMatrixElement[{{\[Alpha]1, \[Alpha]2}, {\[Beta]1, \[Beta]2}}, b1, - "Basis" -> "Coherent", "Generators" -> {b1, bd1, b2, bd2}] - + BosonicMatrixElement[{{\[Alpha]1, \[Alpha]2}, {\[Beta]1, \[Beta]2}}, b1, $v2, + "Basis" -> "Coherent"] - \[Beta]1 Exp[Conjugate[\[Alpha]1] \[Beta]1 - (Abs[\[Alpha]1]^2 + Abs[\[Beta]1]^2)/2] * Exp[Conjugate[\[Alpha]2] \[Beta]2 - (Abs[\[Alpha]2]^2 + Abs[\[Beta]2]^2)/2] ], @@ -380,9 +380,9 @@ VerificationTest[ (* Operators of different modes commute, and an operator that cancels only once ordered is zero, not a stray term with a negative power. *) VerificationTest[ - {BosonicMatrixElement[{{m1, m2}, {n1, n2}}, Commutator[b1, bd2], "Generators" -> {b1, bd1, b2, bd2}], - BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1 - b1 ** bd1 + 1, "Generators" -> {b1, bd1, b2, bd2}], - BosonicMatrixElement[{m, n}, adv ** av - av ** adv + 1]}, + {BosonicMatrixElement[{{m1, m2}, {n1, n2}}, Commutator[b1, bd2], $v2], + BosonicMatrixElement[{{m1, m2}, {n1, n2}}, bd1 ** b1 - b1 ** bd1 + 1, $v2], + BosonicMatrixElement[{m, n}, adv ** av - av ** adv + 1, $v]}, {0, 0, 0}, TestID -> "BME-Modes-CancellationIsZero" ] @@ -390,11 +390,11 @@ VerificationTest[ (* One mode reads the same with a scalar index, a one-component index vector, or a labelled field variable, on every route: polynomial, wing and closed form. *) VerificationTest[ - {BosonicMatrixElement[{{m}, {n}}, adv ** av], - BosonicMatrixElement[{{2}, {0}}, Exp[z adv]], + {BosonicMatrixElement[{{m}, {n}}, adv ** av, $v], + BosonicMatrixElement[{{2}, {0}}, Exp[z adv], $v], BosonicMatrixElement[{{1}, {0}}, DisplacementOperator[\[Alpha]]], - BosonicMatrixElement[{m, n}, bd1 ** b1], - BosonicMatrixElement[{2, 0}, Exp[z bd1]]}, + BosonicMatrixElement[{m, n}, bd1 ** b1, {{bd1}, {b1}}], + BosonicMatrixElement[{2, 0}, Exp[z bd1], {{bd1}, {b1}}]}, {Sqrt[m] Sqrt[n] KroneckerDelta[m - 1, n - 1], z^2/Sqrt[2], \[Alpha] E^(-Abs[\[Alpha]]^2/2), Sqrt[m] Sqrt[n] KroneckerDelta[m - 1, n - 1], z^2/Sqrt[2]}, TestID -> "BME-Modes-OneModeSpellings" @@ -403,7 +403,7 @@ VerificationTest[ (* Exponentials are still read one mode at a time; several modes stay unevaluated rather than feed an index vector to the single-mode wing formula. *) VerificationTest[ - Head[BosonicMatrixElement[{{2, 1}, {0, 0}}, Exp[z bd1]]], + Head[BosonicMatrixElement[{{2, 1}, {0, 0}}, Exp[z bd1], $v2]], BosonicMatrixElement, TestID -> "BME-Modes-ExponentialUnevaluated" ] diff --git a/Tests/SecondQuantization/ToBosonicOperator.wlt b/Tests/SecondQuantization/ToBosonicOperator.wlt index ebe0ccf9..8ab9531c 100644 --- a/Tests/SecondQuantization/ToBosonicOperator.wlt +++ b/Tests/SecondQuantization/ToBosonicOperator.wlt @@ -1,21 +1,24 @@ Needs["Wolfram`QuantumFramework`"] Needs["Wolfram`QuantumFramework`SecondQuantization`"] +$v = FieldVariables[]; +$vab = FieldVariables[{\[FormalA], \[FormalB]}]; + BeginTestSection["ToBosonicOperator - single mode"] (* a^dagger a (number operator) via ** matches direct composition *) VerificationTest[ With[{a = AnnihilationOperator[6]}, - ToBosonicOperator[SuperDagger[\[FormalA]] ** \[FormalA], 6]["Matrix"] == (SuperDagger[a] @ a)["Matrix"] + ToBosonicOperator[SuperDagger[\[FormalA]] ** \[FormalA], $v, 6]["Matrix"] == (SuperDagger[a] @ a)["Matrix"] ], True, TestID -> "ToBosonicOperator-NumberOperator" ] -(* Only the dagger appears; automatic var detection must still find the mode *) +(* Only the creator appears; it realizes as the adjoint of its mode *) VerificationTest[ - ToBosonicOperator[SuperDagger[\[FormalA]], 6]["Matrix"] == AnnihilationOperator[6]["Dagger"]["Matrix"], + ToBosonicOperator[SuperDagger[\[FormalA]], $v, 6]["Matrix"] == AnnihilationOperator[6]["Dagger"]["Matrix"], True, TestID -> "ToBosonicOperator-OnlyDagger" ] @@ -23,7 +26,7 @@ VerificationTest[ (* (a^dagger)^2 a^2 via repeated ** matches direct repeated composition *) VerificationTest[ With[{a = AnnihilationOperator[]}, - ToBosonicOperator[SuperDagger[\[FormalA]] ** SuperDagger[\[FormalA]] ** \[FormalA] ** \[FormalA], $FockSize]["Matrix"] == + ToBosonicOperator[SuperDagger[\[FormalA]] ** SuperDagger[\[FormalA]] ** \[FormalA] ** \[FormalA], $v, $FockSize]["Matrix"] == (SuperDagger[a] @ SuperDagger[a] @ a @ a)["Matrix"] ], True, @@ -32,7 +35,7 @@ VerificationTest[ (* Explicit size overrides $FockSize *) VerificationTest[ - ToBosonicOperator[SuperDagger[\[FormalA]] ** \[FormalA], {\[FormalA]}, 8]["Matrix"] == + ToBosonicOperator[SuperDagger[\[FormalA]] ** \[FormalA], $v, 8]["Matrix"] == (SuperDagger[AnnihilationOperator[8]] @ AnnihilationOperator[8])["Matrix"], True, TestID -> "ToBosonicOperator-ExplicitSize" @@ -44,6 +47,7 @@ VerificationTest[ ToBosonicOperator[ GeneralizedPower[NonCommutativeMultiply, SuperDagger[\[FormalA]], 2] ** GeneralizedPower[NonCommutativeMultiply, \[FormalA], 2], + $v, 6 ]["Matrix"] == (SuperDagger[a] @ SuperDagger[a] @ a @ a)["Matrix"] ], @@ -55,7 +59,7 @@ VerificationTest[ VerificationTest[ With[{alpha = 0.3 + 0.1 I, a = AnnihilationOperator[6]}, With[{concreteGen = alpha SuperDagger[a] - Conjugate[alpha] a}, - ToBosonicOperator[Exp[concreteGen], 6]["Matrix"] == Exp[concreteGen]["Matrix"] + ToBosonicOperator[Exp[concreteGen], $v, 6]["Matrix"] == Exp[concreteGen]["Matrix"] ] ], True, @@ -71,8 +75,8 @@ BeginTestSection["ToBosonicOperator - two mode"] local names via Module, as FieldVariables[] is typically used throughout this codebase *) VerificationTest[ Module[{a1 = AnnihilationOperator[6, {1}], a2 = AnnihilationOperator[6, {2}], v1, v1dag, v2, v2dag}, - {v1, v1dag, v2, v2dag} = FieldVariables[{1, 2}]; - ToBosonicOperator[v1dag ** v2 + v2dag ** v1, {v1, v2}, 6]["Matrix"] == + {{v1dag, v2dag}, {v1, v2}} = FieldVariables[{1, 2}]; + ToBosonicOperator[v1dag ** v2 + v2dag ** v1, FieldVariables[{1, 2}], 6]["Matrix"] == (SuperDagger[a1] @ a2 + SuperDagger[a2] @ a1)["Matrix"] ], True, @@ -81,7 +85,7 @@ VerificationTest[ VerificationTest[ Module[{a1 = AnnihilationOperator[4, {1}], a2 = AnnihilationOperator[4, {2}]}, - ToBosonicOperator[\[FormalA] ** \[FormalB] + SuperDagger[\[FormalA]], 4]["Matrix"] == + ToBosonicOperator[\[FormalA] ** \[FormalB] + SuperDagger[\[FormalA]], $vab, 4]["Matrix"] == (a1 @ a2 + SuperDagger[a1])["Matrix"] ], True, @@ -91,7 +95,7 @@ VerificationTest[ VerificationTest[ Module[{a1 = AnnihilationOperator[4, {1}], a2 = AnnihilationOperator[4, {2}]}, Chop[Norm[Flatten[ - ToBosonicOperator[Exp[0.1 (\[FormalA] ** \[FormalB] + SuperDagger[\[FormalA]])], 4]["Matrix"] - + ToBosonicOperator[Exp[0.1 (\[FormalA] ** \[FormalB] + SuperDagger[\[FormalA]])], $vab, 4]["Matrix"] - Exp[0.1 (a1 @ a2 + SuperDagger[a1])]["Matrix"] ]]] ], @@ -102,7 +106,8 @@ VerificationTest[ VerificationTest[ With[{a = AnnihilationOperator[6]}, ToBosonicOperator[ - Evaluate @ BosonicNormalOrder[\[FormalA] ** SuperDagger[\[FormalA]] ** \[FormalA], FieldVariables[]], + Evaluate @ BosonicNormalOrder[\[FormalA] ** SuperDagger[\[FormalA]] ** \[FormalA], $v], + $v, 6 ]["Matrix"] == (a + SuperDagger[a] @ a @ a)["Matrix"] ], @@ -122,7 +127,7 @@ BeginTestSection["ToBosonicOperator - exponentials and other wrapping functions" VerificationTest[ Module[{alpha = 0.3 + 0.1 I, a = AnnihilationOperator[6]}, Chop[Norm[Flatten[ - ToBosonicOperator[Exp[alpha SuperDagger[\[FormalA]] - Conjugate[alpha] \[FormalA]], 6]["Matrix"] - + ToBosonicOperator[Exp[alpha SuperDagger[\[FormalA]] - Conjugate[alpha] \[FormalA]], $v, 6]["Matrix"] - MatrixExp[alpha SuperDagger[a] - Conjugate[alpha] a]["Matrix"] ]]] ], @@ -134,7 +139,7 @@ VerificationTest[ VerificationTest[ Module[{alpha = 0.3 + 0.1 I}, Chop[Norm[Flatten[ - ToBosonicOperator[Exp[alpha SuperDagger[\[FormalA]] - Conjugate[alpha] \[FormalA]], 6]["Matrix"] - + ToBosonicOperator[Exp[alpha SuperDagger[\[FormalA]] - Conjugate[alpha] \[FormalA]], $v, 6]["Matrix"] - DisplacementOperator[alpha, 6, "Ordering" -> "Weak"]["Matrix"] ]]] ], @@ -148,7 +153,7 @@ VerificationTest[ Module[{alpha = 0.3 + 0.1 I, a = AnnihilationOperator[6], v = \[FormalA], vdag}, vdag = SuperDagger[v]; Chop[Norm[Flatten[ - ToBosonicOperator[Exp[alpha vdag - Conjugate[alpha] v], {v}, 6]["Matrix"] - + ToBosonicOperator[Exp[alpha vdag - Conjugate[alpha] v], {{vdag}, {v}}, 6]["Matrix"] - Exp[alpha SuperDagger[a] - Conjugate[alpha] a]["Matrix"] ]]] ], @@ -160,7 +165,7 @@ VerificationTest[ VerificationTest[ With[{a = AnnihilationOperator[6]}, Chop[Norm[Flatten[ - ToBosonicOperator[Cos[SuperDagger[\[FormalA]] + \[FormalA]], 6]["Matrix"] - + ToBosonicOperator[Cos[SuperDagger[\[FormalA]] + \[FormalA]], $v, 6]["Matrix"] - Cos[SuperDagger[a] + a]["Matrix"] ]]] ], @@ -172,7 +177,7 @@ VerificationTest[ VerificationTest[ With[{a = AnnihilationOperator[6]}, Chop[Norm[Flatten[ - ToBosonicOperator[2^(SuperDagger[\[FormalA]] + \[FormalA]), 6]["Matrix"] - + ToBosonicOperator[2^(SuperDagger[\[FormalA]] + \[FormalA]), $v, 6]["Matrix"] - MatrixExp[Log[2] (SuperDagger[a] + a)]["Matrix"] ]]] ],