# Defining quantum-mechanical Bra and Ket operations

I have the following ket in the Fock basis: $\vert3, 0 ,1\rangle$, where each entry defines the number of photons in a particular mode and can take any one of the following numbers: 0, 1, 2, 3. As a result I define the following column vectors $0 = (1, 0, 0, 0)^\text{T}$, $1 = (0, 1, 0, 0)^\text{T}$, $2 = (0, 0, 1, 0)^\text{T}$ and $3 = (0, 0, 0, 1)^\text{T}$, where the superscript $\text{T}$ defines the transpose.

I want to be able to define the ket and associate bra terms to evaluate inner products of the form $\langle\alpha, \beta, \gamma \vert\cdot\vert a, b, c\rangle = \delta_{\alpha a}\delta_{\beta b}\delta_{\gamma c}$. Note that the kets $\langle\alpha, \beta, \gamma\vert$ is the Hermitian conjugate of the corresponding bra $\vert \alpha, \beta, \gamma\rangle$.

How could I implement these inner-products in Mathematica? I imagine that the functions KroneckerProduct, Transpose and the KroneckerDelta would be of use here but I am still unsure. I am aware that there is an add-on for quantum mechanical operations for Mathematica (see this page), but I am sure that this problem does not require this.

• You might run into problems with notation, I'm afraid. The "bra" and "ket" seem to be handled by mathematica as parentheses, not as postfix/prefix operators, so they always need to be matched. That means, the product can be defined, but a separate bra or ket - probably not. May 28 '15 at 13:24

The definition of the scalar product in your question assumes that all your kets are orthogonal unit vectors. In that case, the most natural approach would be to use the built-in Bra and Ket as follows:

Ket /: Dot[Bra[x__], Ket[y__]] :=

BraKet[x_, y_] := Bra[x].Ket[y]

Bra[2, 4].Ket[2, 4]

(* ==> 1 *)

BraKet[{0, 3, 4}, {1, 3, 4}]

(* ==> 0 *)


In addition to the dot product, I also defined the short-had BraKet which can be entered as EscbraketEsc. You can similarly enter EscbraEsc and EscketEsc and use the regular dot operation, which I defined using TagSetDelayed.

Therefore, the actual keyboard input for the last line, e.g., would be

$\langle0,3,4\vert 1,3,4\rangle$

A related question is Define an 'inner product' with AngleBracket.

Edit in response to comment

If you want to implement other properties of the scalar product, it's better to use a special symbol that has no built-in meaning. Here is an implementation that starts the same way as above but adds linearity properties:

ClearAll[CircleDot]

Ket /: CircleDot[Bra[x__], Ket[y__]] :=

BraKet[x_, y_] := Bra[x]⊙Ket[y]

CircleDot[e1_, HoldPattern[Plus[e2__]]] :=
Total@Map[CircleDot[e1, #] &, {e2}]

CircleDot[HoldPattern[Plus[e1__]], e2_] :=
Total@Map[CircleDot[#, e2] &, {e1}]

CircleDot[first_, HoldPattern[Times[x__, Ket[y__]]]] :=
Times[x, CircleDot[first, Ket[y]]]

CircleDot[HoldPattern[Times[x__, Bra[y__]]], last_] :=
Times[x, CircleDot[Bra[y], last]]


Here is a test:

(α Bra[a1, a2] - β Bra[b1, b2])⊙(γ Ket[c1, c2] - δ Ket[d1, d2])


$$\alpha \gamma \delta _{\text{a1},\text{c1}} \delta _{\text{a2},\text{c2}}-\alpha \delta \delta _{\text{a1},\text{d1}} \delta _{\text{a2},\text{d2}}-\beta \gamma \delta _{\text{b1},\text{c1}} \delta _{\text{b2},\text{c2}}+\beta \delta\, \delta _{\text{b1},\text{d1}} \delta _{\text{b2},\text{d2}}$$

Here, I used CircleTimes instead of Dot. It can be entered with the shortcut escc. esc. The next thing would be to define a adjoint operation, but this will lead to a larger project.

• Jens, How could I extend this to evaluate the product something like $(\alpha_1 \langle a, b\vert + \alpha_2 \langle c, d\vert)(\beta_1 \vert e, f\rangle + \beta_2 \vert g, h\rangle)$. In practice I have a lot of bra terms and a lot of ket terms which I would like to extend out.
– Sid
May 28 '15 at 15:31
• My, oh my. I looked and looked for the appropriate symbolic operators (mostly searching available prefix and postfix operators), when Bra and Ket were built-in functions all along. +1. ps - apparently, they're undocumented. Hmm... May 28 '15 at 15:36
• @LLlAMnYP Yes, it's true - that notation is so useful and has been around forever, but is impossible to find in the documentation.
– Jens
May 28 '15 at 17:24
• @Sid The additional linear algebra you're asking for would be easier to implement by not using the built-in Dot. I'll update the answer with an approach that works. But ultimately, one has to ask when it stops being worthwhile trying to re-implement all linear-algebra functionality with special notation. Then it may be better to leverage the existing conventional vector algebra and use special notation only for input and output. That's e.g. what I did in this answer.
– Jens
May 28 '15 at 17:28

The relevant topics here are "Operators without built-in meanings" and solving your problem is a matter of assigning meanings to them.

Important to note here: the left and right angle brackets are typed as :esc: < :esc: and :esc: > :esc: and are not the same as the Greater and Less signs, but for brevity I will be typing them simply as < and > in this answer. The same applies to the vertical separator | which is typed as :esc: | :esc:.

The vertical separator is an infix separator. This means that

a|b//FullForm
(* VerticalSeparator[a,b] *)


You unfortunately cannot have the notation you proposed:

<a|*|b>


mathematica is expecting expressions to the left and right of the infix operator of multiplication, not other operators. You can, however write

<a|b>//FullForm
(* AngleBracket[VerticalSeparator[a,b]] *)


and

<a,b,c|d,e,f>//FullForm
(* AngleBracket[a,b,VerticalSeparator[c,d],e,f] *)


now we need to assign a meaning to the vertical separator or to the angle-brackets. Using TagSetDelayed (also search for UpValues):

VerticalSeparator /:
AngleBracket[bra___, VerticalSeparator[b_, k_], ket___] :=
KroneckerDelta[(ConjugateTranspose /@ {bra, b}), {k, ket}]]

\[LeftAngleBracket]a, b, c \[VerticalSeparator] d, e, f\[RightAngleBracket]
(* KroneckerDelta[d, ConjugateTranspose[a]]
KroneckerDelta[e, ConjugateTranspose[b]]
KroneckerDelta[f, ConjugateTranspose[c]] *)


Or we can associate this operation with the angle-brackets using SetDelayed:

Clear[VerticalSeparator]
AngleBracket[bra___, VerticalSeparator[b_, k_], ket___] :=
Times @@ Thread[KroneckerDelta[(ConjugateTranspose /@ {bra, b}), {k, ket}]]


I'm not sure, which is more appropriate in this case.

\[LeftAngleBracket]a, b, c \[VerticalSeparator] d, e, f\[RightAngleBracket]
(* KroneckerDelta[d, ConjugateTranspose[a]]
KroneckerDelta[e, ConjugateTranspose[b]]
KroneckerDelta[f, ConjugateTranspose[c]] *)