Quantum Notation

Installation

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

Files must be located in the proper file location in order to be able to load the package with the Needs command and to have the documentation in Mathematica's help (Help Browser for version 5.2 or Documentation Center for version 6.0) .

All the files will be located inside the directory specified by the value of Mathematica's variable $UserBaseDirectory. In the computer were this document was generated, this is the value of $UserBaseDirectory  (when you reevaluate the following command, you will get the directory in your computer):

$UserBaseDirectory

In the following image you can see the Windows Explorer opened in the $UserBaseDirectory of my computer. Remember that in your computer it will be a different location, the one that you obtain when you reevaluate $UserBaseDirectory in your Mathematica.

Inside your $UserBaseDirectory there must be an Applications directory, and inside the Applications directory you must create a Quantum directory

SetDirectory[$UserBaseDirectory];
SetDirectory["Applications"];
FileNames[]

You can see the Quantum directory in my computer in the following image:

Inside the Quantum directory there must be the file Notation.m, which has the programs of this package, and the directories Documentation and FrontEnd:

SetDirectory[$UserBaseDirectory];
SetDirectory["Applications"];
SetDirectory["Quantum"];
FileNames[]

Inside the Documentation directory there must be an English directory, and inside that there must be files QuantumNotationDocumentation.nb and BrowserCategories.m:

SetDirectory[$UserBaseDirectory];
SetDirectory["Applications"];
SetDirectory["Quantum"];
SetDirectory["Documentation"];
SetDirectory["English"];
FileNames[]

You can see the English directory in my computer in the following image:

Inside the FrontEnd directory there must be a Palettes directory, and inside that there must be files QuantumNotationPaletteV52.nb and QuantumNotationPaletteV60.nb:

SetDirectory[$UserBaseDirectory];
SetDirectory["Applications"];
SetDirectory["Quantum"];
SetDirectory["FrontEnd"];
SetDirectory["Palettes"];
FileNames[]

You can see the Palettes directory in my computer in the following image:

After having all the files in the proper directories you must restart Mathematica, so that the palette QuantumNotationPalette appears in Mathematica's Palettes menu. 
If you are using Mathematica version 5.2, then in Mathematica's Help menu select Rebuild Help Index. After this, the documentation of the package will appear in the Help Browser, at the end of the Add-ons & Links section.
If you are using Mathematica version 6.0, then the documentation of the package will appear in Mathematica's Help in the Documentation Center, in the Installed Add-ons section.

Dirac Notation

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

First load the Quantum Notation package

Needs["Quantum`Notation`"]

Evaluate SetQuantumAliases[] in order to be able to enter quantum objects in Dirac's notation. 
WARNING: SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER, BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

SetQuantumAliases[]

In order to write a ket in Dirac's notation, place the cursor in a new Mathematica cell and press the keyboard keys:
[ESC]ket[ESC]
The ket template will appear.In order to select and fill in the "place holder" (square) press the keys:
[TAB] z
Finally press at the same time the keys[SHIFT] and[ENTER] to evaluate.
WARNING: [ESC]ket[ESC] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER, BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK BEFORE TYPING [ESC]ket[ESC].

\[VerticalSeparator]z⟩

In order to write the eigenket of operator p with eigenvalue 3, place the cursor in a new Mathematica cell and press the keyboard keys:  
[ESC]eket[ESC]
The eigenket template will appear. Next press the keys:
[TAB]3[TAB]p
Finally press at the same time the keys [SHIFT] and [ENTER] to evaluate:

\[VerticalSeparator]\(3\_p\&^\)⟩

In order to write the operator h acting on its eigenket with eigenvalue 3 press the keys:
[ESC]op[ESC][ESC]on[ESC][ESC]eket[ESC]
The operator and eigenket templates will appear. Next press [TAB] several times till the first place holder (square) is selected. Then press the keys:
h[TAB]3[TAB]h
Finally press at the same time the keys [SHIFT] and [ENTER] to evaluate. The result of the calculation is the same ket multiplied by its eigenvalue:

\(h\&^\)·\[VerticalSeparator]\(3\_h\&^\)⟩

In order to write a ket that is eigenket of two operators press the keys:
[ESC]eeket[ESC]
The corresponding eigenket template will appear. Next press the keys:
[TAB]3[TAB]p[TAB]1[TAB]c
Finally press at the same time the keys [SHIFT] and [ENTER] to evaluate.

\[VerticalSeparator]\(3\_p\&^, 1\_c\&^\)⟩

Another example of an operator acting on its eigenket:
[ESC]op[ESC][ESC]on[ESC][ESC]eeeket[ESC]
The operator and eigenket templates will appear. Next press [TAB] several times till the first place holder (square) is selected. Then press the keys:
b[TAB]2[TAB]c[TAB]3[TAB]a[TAB]4[TAB]b
Finally press at the same time the keys [SHIFT] and [ENTER] to evaluate. The result of the calculation is the same ket multiplied by its eigenvalue:

\(b\&^\)·\[VerticalSeparator]\(2\_c\&^, 3\_a\&^, 4\_b\&^\)⟩

In a similar way you can enter a bra:
[ESC]bra[ESC]
then press [TAB] and fill in the "place holder" (square) with label z:

⟨z\[VerticalSeparator]

In order to enter the bra that corresponds to an eigenket press:
[ESC]ebra[ESC]
then press [TAB] and fill in the first "place holder" (square) with 6. Press [TAB] again and fill in the second "place holder" with m:

⟨\(6\_m\&^\)\[VerticalSeparator]

Next calculation gives one because eigenstates of the same operator are assumed to be orthonormal:
[ESC]ebra[ESC][ESC]on[ESC][ESC]eket[ESC]
Next press [TAB] several times till the first place holder (square) is selected. Then press:
2[TAB]m[TAB]2[TAB]m

⟨\(2\_m\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(2\_m\&^\)⟩

Next calculation gives zero because eigenstates of the same operator are assumed to be orthonormal:

⟨\(3\_m\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(2\_m\&^\)⟩

This calculation gives a KroneckerDelta because eigenstates of the same operator are assumed to be orthonormal:

⟨\(a\_m\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(b\_m\&^\)⟩

Eigenstates of different operators are assumed to "live" in different subspaces (the operators are assumed to commute). This is very useful for writting operators "made of" simpler subspace-operators. 
[ESC]ebra[ESC][ESC]on[ESC][ESC]eket[ESC]
Next press [TAB] several times till the first place holder (square) is selected. Then press:
2[TAB]m[TAB]3[TAB]p

⟨\(2\_m\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(3\_p\&^\)⟩

Eigenstates of different operators are assumed to "live" in different subspaces (the operators are assumed to commute).This is very useful for writting operators "made of" simpler subspace-operators.
[ESC]eebra[ESC][ESC]on[ESC][ESC]eeket[ESC]

⟨\(3\_p\&^, 2\_q\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(4\_r\&^, 6\_s\&^\)⟩

Eigenstates of different operators are assumed to "live" in different subspaces (the operators are assumed to commute).This is very useful for writting operators "made of" simpler subspace-operators.
[ESC]eeebra[ESC][ESC]on[ESC][ESC]eeket[ESC]

⟨\(\(-2\_p\&^\), 2\_q\&^, 3\_r\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(\(-7\_s\&^\), 8\_t\&^\)⟩

Here is a braket:
[ESC]braket[ESC]
[TAB]a[TAB]b

⟨a\[VerticalSeparator]b⟩

Here is a braket made of eigenstates
[ESC]eebraket[ESC]
[TAB]2[TAB]p[TAB]3[TAB]c[TAB]2[TAB]p[TAB]3[TAB]c

⟨\(2\_p\&^, 3\_c\&^\)\[VerticalSeparator]\(2\_p\&^, 3\_c\&^\)⟩

In order to write a tensor product of kets press the keys:
[ESC]eket[ESC][ESC]on[ESC][ESC]eket[ESC]
Next press[TAB] several times till the first place holder (square) is selected.Then press:
3[TAB]p[TAB]1[TAB]c

\[VerticalSeparator]\(3\_p\&^\)⟩·\[VerticalSeparator]\(1\_c\&^\)⟩

Using tensor products you can generate a ket of any length:

\[VerticalSeparator]\(5\_v\&^, 8\_r\&^, 9\_t\&^\)⟩·\[VerticalSeparator]\(5\_a\&^, 6\_c\&^\)⟩·\[VerticalSeparator]\(3\_w\&^, \(-7\_z\&^\), a\_f\&^\)⟩

You must use [ESC]on[ESC]. If you just write one ket after the other, Mathematica will interpret a commutative multiplication, which is undefined for quantum objects. In order to see this error, press the keys
[ESC]eket[ESC][ESC]eket[ESC]
Next press [TAB] several times till the first place holder (square) is selected. Then press:
3[TAB]p[TAB]1[TAB]c
Finally press at the same time the keys [SHIFT] and [ENTER] to evaluate and see the error message:

\[VerticalSeparator]\(3\_p\&^\)⟩\[VerticalSeparator]\(1\_c\&^\)⟩

You can apply an operator in a subspace to a ket of the space:
[ESC]eket[ESC][ESC]on[ESC][ESC]ebra[ESC][ESC]on[ESC][ESC]eeket[ESC]
Next press[TAB] several times till the first place holder (square) is selected.Then press:
a[TAB]p[TAB]j[TAB]p[TAB]0[TAB]c[TAB]j[TAB]p
and press at the same time[SHIFT]-[ENTER]

\[VerticalSeparator]\(a\_p\&^\)⟩·⟨\(j\_p\&^\)\[VerticalSeparator]·\[VerticalSeparator]\(0\_c\&^, j\_p\&^\)⟩

In order to calculate the Hermitian Conjugate of a ket press the keys:
[ESC]her[ESC][TAB][ESC]ket[ESC][TAB]a
and press at the same time [SHIFT]-[ENTER]

(SuperDagger[(\[VerticalSeparator]a⟩)])

In order to calculate the Hermitian Conjugate of an expresion press the following keys (Notice that the imaginary i is entered with two ii between two [ESC]):
[ESC]her[ESC][TAB]
(8+9[ESC]ii[ESC])*[ESC]eeket[ESC]+(5+7[ESC]ii[ESC])*[ESC]eeket[ESC]
Next press [TAB] several times till the first place holder (square) is selected. Then press:
0[TAB]c[TAB]3[TAB]p[TAB]1[TAB]c[TAB]-5[TAB]p
and press at the same time [SHIFT]-[ENTER]

(SuperDagger[((8 + 9  I)*\[VerticalSeparator]\(0\_c\&^, 3\_p\&^\)⟩+(5 + 7  I)*\[VerticalSeparator]\(1\_c\&^, \(-5\_p\&^\)\)⟩)])

It also works in symbolic expressions
[ESC]her[ESC][TAB]
a[SPACE][ESC]ket[ESC]+[ESC]con[ESC][SPACE][ESC]ket[ESC]
Next press [TAB] several times till the first place holder (square) is selected. Then press:
x[TAB]b[TAB]y
and press at the same time [SHIFT]-[ENTER]

(SuperDagger[(a \[VerticalSeparator]x⟩+\(\((b)\)\^*\) \[VerticalSeparator]y⟩)])

This is the way to define a ket. It is necessary to use the symbol /: in order to assign the definition to the symbol psi instead of assigning to the internal representation of ket. The greek letters can be entered with aliases [ESC]psi[ESC], [ESC]a[ESC], [ESC]b[ESC], etc.

ψ /: \[VerticalSeparator]ψ⟩ = α\[VerticalSeparator]\(1\_q\&^\)⟩+β\[VerticalSeparator]\(2\_q\&^\)⟩+γ\[VerticalSeparator]\(3\_q\&^\)⟩+δ\[VerticalSeparator]\(4\_q\&^\)⟩+ξ\[VerticalSeparator]\(5\_q\&^\)⟩

Here we define the dual (bra) of the ket that we created:

ψ /: ⟨ψ\[VerticalSeparator]=(SuperDagger[(\[VerticalSeparator]ψ⟩)])

The internal product of a ket with its dual is a real number (norm):

⟨ψ\[VerticalSeparator]·\[VerticalSeparator]ψ⟩

The external product with its dual is an operator (matrix):

\[VerticalSeparator]ψ⟩·⟨ψ\[VerticalSeparator]

Here we apply the "base" operator q to the ket. Notice that q is inside the operator template [ESC]op[ESC]

\(q\&^\)·\[VerticalSeparator]ψ⟩

This is one way to define another operator. Notice that p is not inside the operator template:

p= a \[VerticalSeparator]\(1\_q\&^\)⟩·⟨\(2\_q\&^\)\[VerticalSeparator]+b \[VerticalSeparator]\(2\_q\&^\)⟩·⟨\(4\_q\&^\)\[VerticalSeparator]

Now the operator and ket that were defined can be used. Notice that p is not inside the operator template:

p·\[VerticalSeparator]ψ⟩

Notice that p is not inside the operator template, but base operator q is inside the template:

p·\(q\&^\)·\[VerticalSeparator]ψ⟩

(((p))^†)

(((p))^†)·\[VerticalSeparator]ψ⟩

Notice that p is not inside the operator template, but base operator q is inside the template:

⟨ψ\[VerticalSeparator]·p·\[VerticalSeparator]ψ⟩

⟨ψ\[VerticalSeparator]·\(q\&^\)·\[VerticalSeparator]ψ⟩

This is one way to define another operator that depends on a parameter t. Notice that w is not inside the operator template:

w[t_]:=\[VerticalSeparator]\(t\_q\&^\)⟩·⟨\(2\_q\&^\)\[VerticalSeparator]

Notice that w is not inside the operator template:

w[3]

Notice that w is not inside the operator template:

w[4]

Notice that w is not inside the operator template, but base operator q is inside the template:

w[4]·\(q\&^\)·\[VerticalSeparator]ψ⟩

Clear[p, w, ψ]

WARNING:SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER,BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

Quantum Random Walk (naive approach)

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

The quantum random walker (Y. Aharonov, L. Davidovich, and N. Zagury "Quantum random walks" Phys. Rev. A 48, 1687 - 1690 (1993)) is made of a "coin" and a "walker", each one with its own state-space, which will make a composite system with the coin and the walker in entanglement. A unitary operator will be defined to "flip the coin", while another unitary operator will be defined to "move the walker" based on coin's result. The second operator produces entanglement between coin and walker.

First load the Quantum Notation package

Needs["Quantum`Notation`"]

Evaluate SetQuantumAliases[] in order to be able to enter quantum objects in Dirac's notation

WARNING:SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER,BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

SetQuantumAliases[]

We will simulate ten steps of a quantum random walker. More steps are not practical with the naive approach that will be used in this section. A more efficient approach will be shown in the next section.

steps = 20

The coin C can have only two states, 0 and 1 (head and tail), while the walker P can be in any (discrete) position from -steps to steps. The coin is inially in state 0 and the walker is initially at the origin 0:

w/: \[VerticalSeparator]w[0]⟩=\[VerticalSeparator]\(0\_c\&^\)⟩·\[VerticalSeparator]\(0\_p\&^\)⟩

Here we define the "fliping coin" operator, which in this case is a Hadamard operator, but it could be any unitary operator that acts only in the coin C. The coin can have only two states, 0 and 1 (head and tail)

h  =(1/(Sqrt[2]))(\[VerticalSeparator]\(0\_c\&^\)⟩·⟨\(0\_c\&^\)\[VerticalSeparator]+\[VerticalSeparator]\(0\_c\&^\)⟩·⟨\(1\_c\&^\)\[VerticalSeparator]+\[VerticalSeparator]\(1\_c\&^\)⟩·⟨\(0\_c\&^\)\[VerticalSeparator]-\[VerticalSeparator]\(1\_c\&^\)⟩·⟨\(1\_c\&^\)\[VerticalSeparator])

Here we define the "move the walker" operator. Its interpretation is very simple, the walker P moves to the left j-1 if the coin is in state 0, and it moves to the right j+1 if the coin is in state 1. This is one of the "naive" parts of this implementation, it looks nice because it is exactly the same way you would do it by hand, but it is not computationally efficient to define the operator this way:

s=\[VerticalSeparator]\(0\_c\&^\)⟩·⟨\(0\_c\&^\)\[VerticalSeparator]·(∑_(j = -steps)^steps)(\[VerticalSeparator]\(\((j - 1)\)\_p\&^\)⟩·⟨\(j\_p\&^\)\[VerticalSeparator])+\[VerticalSeparator]\(1\_c\&^\)⟩·⟨\(1\_c\&^\)\[VerticalSeparator]·(∑_(j = -steps)^steps)(\[VerticalSeparator]\(\((j + 1)\)\_p\&^\)⟩·⟨\(j\_p\&^\)\[VerticalSeparator]);

This is the evolution of the composite system of coin and walker: flip the coin with the operator h and then move the walker with operator s. This process is repeated "steps" times

Do[w/:\[VerticalSeparator]w[k]⟩=s·(h·\[VerticalSeparator]w[k - 1]⟩),{k, 1, steps, 1}]

We define bras as the hermitian conjugates of corresponding kets

w/:⟨w[k_Integer]\[VerticalSeparator]:=(SuperDagger[(\[VerticalSeparator]w[k]⟩)])

Here we define the position projector for each position of the walker:

positionProjector[j_]:=\[VerticalSeparator]\(0\_c\&^, j\_p\&^\)⟩·⟨\(0\_c\&^, j\_p\&^\)\[VerticalSeparator]+\[VerticalSeparator]\(1\_c\&^, j\_p\&^\)⟩·⟨\(1\_c\&^, j\_p\&^\)\[VerticalSeparator]

Here we calculate the probabilities for each walker position. This is another "naive" part of this implementation. It is not computationally efficient.

probabilities=Table[{j,⟨w[steps]\[VerticalSeparator]·positionProjector[j]·\[VerticalSeparator]w[steps]⟩},{j, -steps, steps}]

Here is a plot of the probabilities for each position of the walker.

ListPlot[probabilities, PlotRange -> All, 
      If[$VersionNumber ≥ 6.0, Filling -> Axis, 
        PlotJoined -> True]]

Clear[c, h, j, k, p, positionProjector, probabilities, s, steps, 
      w]

WARNING:SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER,BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

Quantum Random Walk ( a more efficient approach)

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/

This is a more efficient implementation of the quantum random walk. The price is that is less "elegant", in the sense that some operators are not defined the way you do it in a handwritten calculation.

The quantum random walker (Y. Aharonov, L. Davidovich, and N. Zagury "Quantum random walks" Phys. Rev. A 48, 1687 - 1690 (1993)) is made of a "coin" and a "walker", each one with its own state-space, which will make a composite system with the coin and the walker in entanglement. A unitary operator will be defined to "flip the coin", while another unitary operator will be defined to "move the walker" based on coin's result. The second operator produces entanglement between coin and walker.

First load the Quantum Notation package

Needs["Quantum`Notation`"]

Evaluate SetQuantumAliases[] in order to be able to enter quantum objects in Dirac's notation.

WARNING:SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER,BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

SetQuantumAliases[]

The coin C can have only two states, 0 and 1 (head and tail), while the walker P can be in any (discrete) position from -steps to steps. The coin is inially in state 0 and the walker is initially at the origin 0:

cew/: \[VerticalSeparator]cew[0]⟩=\[VerticalSeparator]\(0\_c\&^\)⟩·\[VerticalSeparator]\(0\_p\&^\)⟩

Here we define the "fliping coin" operator, which in this case is a Hadamard operator, but it could be any unitary operator that acts only in the coin C. The coin can have only two states, 0 and 1 (head and tail)

h =(1/(Sqrt[2]))(\[VerticalSeparator]\(0\_c\&^\)⟩·⟨\(0\_c\&^\)\[VerticalSeparator]+\[VerticalSeparator]\(0\_c\&^\)⟩·⟨\(1\_c\&^\)\[VerticalSeparator]+\[VerticalSeparator]\(1\_c\&^\)⟩·⟨\(0\_c\&^\)\[VerticalSeparator]-\[VerticalSeparator]\(1\_c\&^\)⟩·⟨\(1\_c\&^\)\[VerticalSeparator])

This is one of the "effcient" parts of this implementation: After "flipping the coin" the walker is moved using the ReplaceAll[] command:

steps = 20;
Do[
cew/:\[VerticalSeparator]cew[k]⟩=Expand[ReplaceAll[h·\[VerticalSeparator]cew[k - 1]⟩,{\[VerticalSeparator]\(0\_c\&^, j_\_p\&^\)⟩->\[VerticalSeparator]\(0\_c\&^, \((j - 1)\)\_p\&^\)⟩,\[VerticalSeparator]\(1\_c\&^, j_\_p\&^\)⟩->\[VerticalSeparator]\(1\_c\&^, \((j + 1)\)\_p\&^\)⟩}]],{k, 1, steps, 1}
]

We define bras as the hermitian conjugates of corresponding kets

cew/:⟨cew[k_Integer]\[VerticalSeparator]:=(SuperDagger[(\[VerticalSeparator]cew[k]⟩)])

Here we calculate the probabilities for each walker position. This is another "efficient" part of this implementation.

prob=Table[
{j,
ketList=Cases[\[VerticalSeparator]cew[steps]⟩,x_*\[VerticalSeparator]\(y_\_c\&^, j\_p\&^\)⟩];
braList=Cases[⟨cew[steps]\[VerticalSeparator],x_*⟨\(y_\_c\&^, j\_p\&^\)\[VerticalSeparator]];
productList = 
                    MapThread[#1·#2 &, {braList, ketList}];
Apply[Plus, productList]},
{j, -steps, steps}
];

ListPlot[prob, PlotRange -> All, 
      If[$VersionNumber ≥ 6.0, Filling -> Axis, 
        PlotJoined -> True]]

Clear[braList, c, cew, h, j, k, ketList, p, prob, productList, steps, 
      x, y]

WARNING:SetQuantumAliases[] MIGHT NOT WORK IN THE DOCUMENTS IN THE HELP BROWSER,BUT IT DOES WORK IN A NORMAL MATHEMATICA DOCUMENT (NOTEBOOK). REMEMBER THAT SetQuantumAliases[] MUST BE RE-EXECUTED INSIDE EACH NEW NOTEBOOK.

Author: Jose Luis Gomez-Munoz
With improvements based on the work of Francisco Delgado Cepeda
jose.luis.gomez@itesm.mx
http://homepage.cem.itesm.mx/lgomez/