Quantum Programming in Python - Quantum 1D Simple Harmonic Oscilla
Quantum Programming in Python - Quantum 1D Simple Harmonic Oscilla
A Senior Project
presented to
In Partial Fulfillment
Bachelor of Science
by
Matthew Hoff
March, 2013
2013
c Matthew Hoff
Table of Contents
Section Page
Abstract 3
Introduction 3
Appendix 52
2
Abstract
Introduction
The goal of SymPy is “to become a full-featured computer algebra system (CAS) while keeping
the code as simple as possible in order to be comprehensible and easily extensible" (“SymPy").
Through SymPy, I have submitted two projects to their library on GitHub, which “is a web-
based hosting service for software development projects that use the Git revision control system"
(“GitHub"). The first project is a Quantum Simple Harmonic Oscillator (QSHO), which is
explained in a sample notebook using an IPython notebook. The goal of coding the QSHO is
to allow others to learn how the simple harmonic oscillator is applied to a quantum system as
well as allowing others to use components of the QSHO in other future projects. The second
project is a Quantum Mapping Gate (QMG), which again is explained in greater detail using
an IPython notebook. The QMG allows for custom creation of logic gates for quantum systems
and can be used in addition to or instead of the current quantum gates. Both projects were
coded using the Python language and have been added to the SymPy library.
Imports
Before examining the Quantum 1D Simple Harmonic Oscillator, the relevant files need to be loaded to create simple
harmonic oscillator states and operators.
Background
For a detailed background on the Quantum Simple Harmonic Oscillator consult Griffith's Introduciton to Quantum
Mechanics or the Wikipedia page "Quantum Harmonic Oscillator"
Components
States
The Quantum 1D Simple Harmonic Oscillator is made up of states which can be expressed as bras and kets. And those
states are acted on by different operators. Looking at the states, there are two types of states that can be made: a generic
state 'n' or numerical states. Passing a string (i.e. 'n') to SHOBra or SHOKet creates a generic bra or ket state, respectively.
And passing an integer to SHOBra or SHOKet creates a numerical bra or ket state.
SHOBra and SHOKet are passed the information from SHOState and from the Bra and Ket classes, respectively. SHOState
contains the information to find the Hilbert Space of the state as well as the energy level. SHOState also has all the
information and properties from State because State is passed into SHOState.
k = SHOKet('k')
k0 = SHOKet(0)
k1 = SHOKet(1)
Printing
There are multiple printing methods in python: LaTeX, Pretty, repr, and srepr.
Bra
In [3]: b
Out[3]: ⟨b∣∣
In [4]: b0
Out[4]: ⟨0∣∣
In [5]: b1
Out[5]: ⟨1∣∣
In [6]: latex(b)
In [7]: latex(b0)
In [8]: latex(b1)
Pretty
In [9]: pprint(b)
⟨b❘
In [10]: pprint(b0)
⟨0❘
In [11]: pprint(b1)
⟨1❘
In [12]: repr(b)
Out[12]: <b|
In [13]: repr(b0)
Out[13]: <0|
In [14]: repr(b1)
Out[14]: <1|
srepr
In [15]: srepr(b)
Out[15]: SHOBra(Symbol('b'))
In [16]: srepr(b0)
Out[16]: SHOBra(Integer(0))
In [17]: srepr(b1)
Out[17]: SHOBra(Integer(1))
Ket
In [18]: k
Out[18]: ∣k⟩
In [19]: k0
Out[19]: ∣0⟩
In [20]: k1
Out[20]: ∣1⟩
In [21]: latex(k)
Out[21]: {\left|k\right\rangle
}
Out[22]: {\left|0\right\rangle
}
In [23]: latex(k1)
Out[23]: {\left|1\right\rangle
}
Pretty
In [24]: pprint(k)
❘k⟩
In [25]: pprint(k0)
❘0⟩
In [26]: pprint(k1)
❘1⟩
repr
In [27]: repr(k)
Out[27]: |k>
In [28]: repr(k0)
Out[28]: |0>
In [29]: repr(k1)
Out[29]: |1>
srepr
In [30]: srepr(k)
Out[30]: SHOKet(Symbol('k'))
In [31]: srepr(k0)
Out[31]: SHOKet(Integer(0))
In [32]: srepr(k1)
Out[32]: SHOKet(Integer(1))
Properites
In [33]: b.hilbert_space
Out[33]: ∞
In [34]: b0.hilbert_space
Out[34]: ∞
In [35]: k.hilbert_space
Out[35]: ∞
In [36]: k0.hilbert_space
Out[36]: ∞
Energy Level
In [37]: b.n
Out[37]: b
In [38]: b0.n
Out[38]: 0
In [39]: b1.n
Out[39]: 1
In [40]: k.n
Out[40]: k
In [41]: k0.n
Out[41]: 0
In [42]: k1.n
Out[42]: 1
Operators
The states are acted upon by operators. There are four operators that act on simple harmonic kets: RaisingOp,
LoweringOp, NumberOp, and Hamiltonian. The operators are created by passing a string 'n' to the operator. They can
also be printed in multiple ways, but only the raising operator has a distinct difference.
Each of the operators are passed the information and properties from SHOOp. SHOOp contains information on the hilbert
space of the operators and how the arguments are evaluated. Each of these operators are limited to one argument. The
In [43]: ad = RaisingOp('a')
a = LoweringOp('a')
N = NumberOp('N')
H = Hamiltonian('H')
Printing
RaisingOp
In [44]: ad
Out[44]: a†
In [45]: latex(ad)
Out[45]: a^{\dag}
In [46]: pprint(ad)
†
a
In [47]: repr(ad)
Out[47]: RaisingOp(a)
In [48]: srepr(ad)
Out[48]: RaisingOp(Symbol('a'))
LoweringOp
In [49]: a
Out[49]: a
In [50]: latex(a)
Out[50]: a
In [51]: pprint(a)
In [52]: repr(a)
Out[52]: a
In [53]: srepr(a)
Out[53]: LoweringOp(Symbol('a'))
In [54]: N
Out[54]: N
In [55]: latex(N)
Out[55]: N
In [56]: pprint(N)
In [57]: repr(N)
Out[57]: N
In [58]: srepr(N)
Out[58]: NumberOp(Symbol('N'))
Hamiltonian
In [59]: H
Out[59]: H
In [60]: latex(H)
Out[60]: H
In [61]: pprint(H)
In [62]: repr(H)
Out[62]: H
In [63]: srepr(H)
Out[63]: Hamiltonian(Symbol('H'))
Properties
Hilbert Space
In [64]: ad.hilbert_space
Out[64]: ∞
Out[65]: ∞
In [66]: N.hilbert_space
Out[66]: ∞
In [67]: H.hilbert_space
Out[67]: ∞
There are a couple properties and operations of a quantum simple harmonic oscillator state that are defined. Taking the
dagger of a bra returns the ket and vice versa. Using the property 'dual' returns the same value as taking the dagger. The
property 'n' as seen in the State Section above returns the argument/energy level of the state, which is used when
operators act on states.
In [68]: Dagger(b)
Out[68]: ∣b⟩
In [69]: Dagger(k)
Out[69]: ⟨k∣∣
In [70]: Dagger(b0)
Out[70]: ∣0⟩
In [71]: Dagger(b0) == k0
Out[71]:
In [72]: Dagger(k1) == b1
Out[72]:
The energy level of the states must be the same for the dagger of the bra to equal the ket
In [73]: Dagger(b1) == k0
Out[73]:
In [74]: k.dual
Out[74]: ⟨k∣∣
Out[75]:
In [76]: Dagger(a)
Out[76]: a†
In [77]: Dagger(ad)
Out[77]: a
In [78]: Dagger(a) == ad
Out[78]:
The operators can be expressed in terms of other operators. Aside from the operators stated above rewriting in terms of the
position (X) and momentum operators (Px) is common. To rewrite the operators in terms of other operators, we pass a
keyword that specifies which operators to rewrite in.
In [79]: ad.rewrite('xp')
In [80]: a.rewrite('xp')
In [81]: N.rewrite('xp')
Out[82]: a† a
In [83]: N.rewrite('H')
Out[83]: 1 H
− +
2 ℏω
In [84]: H.rewrite('xp')
In [85]: H.rewrite('a')
(2 )
Out[85]: 1
ℏω + a† a
In [86]: H.rewrite('N')
(2 )
Out[86]: 1
ℏω +N
Operator Methods
Apply Operators to States: Each of the operators can act on kets using qapply.
The raising operator raises the value of the state by one as well as multiplies the state by the square root of the new state.
In [87]: qapply(ad*k)
Out[87]: + 1‾∣k + 1⟩
√‾k‾‾‾
Two numerical examples with the ground state and first excited state.
In [88]: qapply(ad*k0)
Out[88]: ∣1⟩
In [89]: qapply(ad*k1)
The lowering operator lowers the value of the state by one and multiples the state by the square root of the original state.
When the lowering operator acts on the ground state it returns zero because the state cannot be lowered.
Out[90]: √k∣k − 1⟩
Two numerical examples with the ground state and first excited state.
In [91]: qapply(a*k0)
Out[91]: 0
In [92]: qapply(a*k1)
Out[92]: ∣0⟩
The number operator is defined as the raising operator times the lowering operator. When the number operator acts on a
ket it returns the same state multiplied by the value of the state. This can be checked by applying the lowering operator on
a state then applying the raising operator to the result.
In [93]: qapply(N*k)
Out[93]: k∣k⟩
In [94]: qapply(N*k0)
Out[94]: 0
In [95]: qapply(N*k1)
Out[95]: ∣1⟩
Out[96]: k∣k⟩
When the hamiltonian operator acts on a state it returns the energy of the state, which is equal to hbar*omega times the
value of the state plus one half.
In [97]: qapply(H*k)
Out[97]: 1
ℏkω∣k⟩ + ℏω∣k⟩
2
In [98]: qapply(H*k0)
Out[98]: 1
ℏω∣0⟩
2
In [99]: qapply(H*k1)
Out[99]: 3
ℏω∣1⟩
2
A commutator is defined as [A, B] = A*B - B*A where A and B are both operators. Commutators are used to see if operators
commute, which is an important property in quantum mechanics. If they commute it allows for rearranging the order
operators act on states.
In [100]: Commutator(ad,a).doit()
Out[100]: −1
In [101]: Commutator(ad,N).doit()
Out[101]: −a†
In [102]: Commutator(a,ad).doit()
Out[102]: 1
In [103]: Commutator(a,N).doit()
Out[103]: a
Matrix Representation
The bras and kets can also be represented as a row or column vector, which are then used to create matrix representation
of the different operators. The bras and kets must be numerical states rather than a generic n state
In [104]: represent(b0)
Out[104]:
[1 0 0 0]
In [105]: represent(k0)
[ 00 ]
Out[105]: 1
0
Because these vectors and matrices are mostly zeros there is a different way of creating and storing these vectors/matrices,
that is to use the format scipy.sparse. The default format is sympy and another common format to use is numpy. Along with
specifying the format in which the matrices are created, the dimension of the matrices can also be specified. A dimension of
4 is the default.
⎡0⎤
⎢1⎥
Out[106]:
⎢ 00 ⎥
⎣0⎦
Out[107]: [[
0.]
[
1.]
[
0.]
[
0.]
[
0.]]
Out[108]: (1, 0)
1.0
Operators can be expressed as matrices using the vector representation of the bras and kets.
⟨i|N|j⟩
The operator acts on the ket then the inner product of the bra and the new resulting ket is performed.
⎡0 0⎤
⎢1 0⎥
Out[109]: 0 0
⎢0 0⎥
0 0
⎣0 0⎦
√2 0
0 √3
Out[110]: [[ 0. 0. 0.
0. ]
[ 1. 0. 0.
0. ]
[ 0. 1.41421356 0.
0. ]
[ 0. 0. 1.73205081 0.
]]
Out[111]: (1, 0)
1.0
(2, 1)1.41421356237
(3, 2)1.73205080757
Out[112]: (1, 0)
1.0
(2, 1)1.41421356237
(3, 2)1.73205080757
⎡0 0 ⎤
⎢0 0 ⎥
Out[113]: 1 0
⎢0 √3 ⎥
0 √2
⎣0 0 ⎦
0 0
0 0
In [114]: represent(N)
[ 00 3]
Out[114]: 0 0 0 0
0 1 0 0
0 2 0
0 0
In [115]: represent(H)
⎡ ⎤
⎢ ⎥
Out[115]: 1
ℏω 0 0 0
⎢ 0 ⎥
2
3
⎢ ⎥
0 ℏω 0
⎢
2
0 ⎥
5
0 0 ℏω
⎢ 2
⎥
⎣ ℏω ⎦
7
0 0 0
2
There are some interesting properties that we can test using the matrix representation, like the definition of the Number
Operator.
Out[116]:
Griffiths, David J. Introduction to Quantum Mechanics. Upper Saddle River, NJ: Pearson Prentice Hall, 2005. Print.
http://en.wikipedia.org/wiki/Quantum_harmonic_oscillator
http://en.wikipedia.org/wiki/Harmonic_oscillator#Simple_harmonic_oscillator
In [ ]:
Mapping Gate
Imports
Before examining the Mapping Gate, the relevant files need to be loaded.
Theory/Background
Creating a MappingGate can be very useful in Quantum Computing. Normally one would have to use a combination of
various quantum gates to get the desired input-output state pairings. The Mapping Gate allows for user provided initial and
final state pairings for every state. Then a quantum gate that has the same pairings is created.
The Mapping Gate maps an initial qubits to scalars times final qubits. If no scalar is specified one is assumed. So there are
two or three arguments for the mapping gate.
The qubits can either be strings or qubits. The resulting arguments of the MappingGate are converted to a sympy
dictionary.
There are multiple ways to specify the qubit pairings. All quantum gates have the property of being unitary, which means
only half of the gate needs to be specified and the rest can be assumed and created to preserve the unitary property. When
thinking about the gates as matrices, it is only required to specify half of the matrix. And if an initial state is not paired to a
final state it will return itself like the Identity Gate.
The Mapping Gate can also take a Python or Sympy dictionary as its argument. The dictionary requires qubit objects rather
than strings and the scalars are multiplied with the final states.
{Qubit('initial'):scalar*Qubit('final'), ...}
In [2]: M_all = MappingGate(('00', I, '11'), ('01', exp(I), '10'), ('10', exp(-I), '01'), ('11'
In [3]: M_all.args
Out[3]:
( { ∣00⟩ : ı∣11⟩, ∣01⟩ : eı ∣10⟩, ∣10⟩ : e−ı ∣01⟩, ∣11⟩ : −ı∣00⟩ } )
Another useful way to express a quantum gate is using outer product representation. This takes the form:
ket(final)*bra(initial) + ...
To call this, we use rewrite and pass it a keyword, in this case 'op'.
In [4]: M_all.rewrite('op')
Another common way of expressing a quantum gate is in matrix form. Any term in a matrix can be identified using a bra and
a ket (i.e. (0,1) is the same as bra(0) ket(1)). Using this idea a quantum gate is created by inserting the outer product in
between each identifying bra and ket for each term. If the qubits in the MappingGate return themselves the resulting matrix
is the identity gate.
In [6]: represent(M_test)
[0 1]
Out[6]: 1 0
Now taking a look at the more complex qubit mapping from above, it is clear that the outer product terms are directly
related to the terms of the matrix.
In [7]: represent(M_all)
[ 0ı 0 ]
Out[7]: 0 0 0 −ı
0 0 e−ı 0
eı 0
0 0 0
Specify only half of the states and relying on the unitary property of the gate.
Here, only half of the pairs are specified because the unitary property of the gate can fill the rest. Given that initial = scalar *
final, this implies that final = conjugate(scalar) * initial. This is what allows for only mapping the upper triangle of the matrix.
The idea of only mapping the one triangle will be more easily seen when the gate is represented in matrix form
Out[9]:
( { ∣00⟩ : ı∣11⟩, ∣01⟩ : eı ∣10⟩, ∣10⟩ : e−ı ∣01⟩, ∣11⟩ : −ı∣00⟩ } )
We can check that the mapping for this is the same as the full mapping
Out[10]:
Let's look at the outerproduct representation, it should be the same as above in M_all
In [11]: M_half.rewrite('op')
Using the matrix representation it is clear that we only mapped the terms at (3,0) and (2,1) and the terms at (0,3) and (1,2)
are the conjugates of the mapped terms.
In [12]: represent(M_half)
[ 0ı 0 ]
Out[12]: 0 0 0 −ı
0 0 e−ı 0
eı 0
0 0 0
Here, only some states will be specified and their compliments. Any state not specified returns itself, but is not one of the
arguments of MappingGate.
In [14]: M_some.args
Out[14]:
( { ∣00⟩ : ı∣11⟩, ∣11⟩ : −ı∣00⟩ } )
When using the outer product representation it will be clear that non-specified states return themselves.
In [15]: M_some.rewrite('op')
States that return themselves will yield a 1 along the diaganol like the identity matrix.
In [16]: represent(M_some)
[ 0ı 0 ]
Out[16]: 0 0 0 −ı
0 1 0 0
0 1 0
0 0
The MappingGate can also take dictionaries as its arguments. Passing a dictionary as the argument to MappingGate works
exactly the same as seen above except for the required form of the dictionary. Where as above MappingGate accepts either
strings or qubits, a dictionary must contain qubits. Again if not all states are specified they will return themselves and only
half of the matrix needs to be mapped. MappingGate converts the python dictionary to a sympy dictionary.
In [18]: M_python_dict.args
Out[18]:
( { ∣00⟩ : ı∣11⟩, ∣01⟩ : eı ∣10⟩, ∣10⟩ : e−ı ∣01⟩, ∣11⟩ : −ı∣00⟩ } )
Check that the outer product and matrix are the same as the the previous gates.
In [19]: M_python_dict.rewrite('op')
Out[20]:
In [21]: represent(M_python_dict)
[ 0ı 0 ]
Out[21]: 0 0 0 −ı
0 0 e−ı 0
eı 0
0 0 0
Out[22]:
A sympy dictionary can also be used to specify the qubit mapping. It works the same as the python dictionary.
In [24]: M_sympy_dict.args
Out[24]:
( { ∣00⟩ : ı∣11⟩, ∣01⟩ : eı ∣10⟩, ∣10⟩ : e−ı ∣01⟩, ∣11⟩ : −ı∣00⟩ } )
In [25]: M_sympy_dict.rewrite('op')
[ 0ı 0 ]
Out[26]: 0 0 0 −ı
0 0 e−ı 0
eı 0
0 0 0
Examples
Create an arbitrary qubit mapping and pass it to MappingGate, then check some of its properties
Check the arguments and outer product representation make sure there are 8 terms.
In [28]: M.args
Out[28]:
( { ∣000⟩ : −∣001⟩, ∣001⟩ : −∣000⟩, ∣010⟩ : ı∣101⟩, ∣100⟩ : ıeı ∣111⟩, ∣101⟩ : −ı∣010⟩, ∣111⟩ : −ıe
In [29]: M.rewrite('op')
Out[29]: ∣011⟩⟨011∣ + ∣110⟩⟨110∣ − ∣000⟩⟨001∣ − ∣001⟩⟨000∣ − ı∣010⟩⟨101∣ − ıe−ı ∣100⟩⟨111∣ + ı∣101⟩⟨010∣ + ıeı ∣111
In [30]: M.hilbert_space
2
Out[30]: ⊗3
There are three ways to get the final state from the initial state: get_final_state, mapping, and qapply. get_final_state takes
either strings or qubits where both mapping and qapply require qubits.
In [31]: M.get_final_state('100')
In [32]: M.mapping[Qubit('100')]
In [33]: qapply(M*Qubit('100'))
The MappingGate can also act on individual qubit states or multiple qubit states.
In [35]: qapply(M*q1)
Out[35]: −∣001⟩
In [36]: qapply(M*q2)
In [37]: qapply(M*q3)
There are three formats of the matrix representation that can be used, sympy-default, numpy, and scipy.sparse. For large
matrices (i.e. large number of qubits) it is common to use the scipy.sparse format.
⎡ 0 ⎤
⎢ −1 ⎥
Out[38]: −1 0 0 0 0 0 0
0 0 0 0 0 0 0
⎢ 0 0 0 0 0 −ı 0 0 ⎥
⎢ 00 0 0 1 0 0 0 0 ⎥
⎢ 0 0 0 0 0 0 0 −ıe−ı
⎥
⎢ 0 0 ı 0 0 0 0 0
⎥
⎣ 0 ⎦
0 0 0 0 0 1 0
0 0 0 ıeı 0 0 0
The matrix representation of a quantum gate is a 2^n by 2^n matrix, so even for relatively small states there is a lot of data
stored. An example with states of 5 qubits should use scipy.sparse representation rather than the default sympy
representation.
In [42]: represent(M_large)
Out[42]: ⎡0 −ı 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎤
⎢ 0ı 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0⎥
1
⎢0 0⎥
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
⎢ 00 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0⎥
0
⎢0 0⎥
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
⎢ 00 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0⎥
0
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
⎢ 00 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0⎥
0
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
⎢ 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
⎢ 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0⎥
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
⎢ 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0⎥
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
⎢0 0⎥
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
⎢ 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0⎥
⎣0 0⎦
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Notice that essentially the entire matrix is zeros with ones along the diagonal. Using the scipy.sparse format here will
condense the result.
MappingGate can be used to create any of the common quantum gates by specifying the same mappings. Let's create the
ZGate, XGate, and YGate.
ZGate
In [45]: Z = ZGate(0)
M_Z = MappingGate(('0', '0'), ('1', -1, '1'))
[0 −1 ]
Out[46]: 1 0
In [47]: represent(M_Z)
[0 −1 ]
Out[47]: 1 0
Out[48]:
XGate
In [50]: X = XGate(0)
M_X = MappingGate(('0', '1'))
[1 0]
Out[51]: 0 1
In [52]: represent(M_X)
[1 0]
Out[52]: 0 1
Out[53]:
In [55]: Y = YGate(0)
M_Y = MappingGate(('0', I, '1'))
[ı 0 ]
Out[56]: 0 −ı
[ı 0 ]
Out[57]: 0 −ı
Out[58]:
Griffiths, David J. Introduction to Quantum Mechanics. Upper Saddle River, NJ: Pearson Prentice Hall, 2005. Print.
http://en.wikipedia.org/wiki/Quantum_gate
In [ ]:
Links
The following are the addresses of the two Quantum projects on the GitHub website in the
SymPy directory.
References
“GitHub." <http://en.wikipedia.org/wiki/GitHub>.
Griffiths, David J. Introduction to Quantum Mechanics. Upper Saddle River, NJ: Pearson
Prentice Hall, 2005. Print.
Appendix 52