Author: Anubhav Vardhan (anubhavvardhan@gmail.com)
Numerical simulation added by Boxi Li (etamin1201@gmail.com)
For more information about QuTiP see http://qutip.org
In [1]:
%matplotlib inline
In [2]:
from qutip.qip.circuit import QubitCircuit
from qutip.qip.operations import gate_sequence_product
import numpy as np
If your qutip version is lower than 4.4.1 please run the following cell
In [ ]:
from qutip.qip.models.spinchain import CircularSpinChain
from qutip.qip.models.spinchain import LinearSpinChain
Otherwise please run this cell
In [3]:
from qutip.qip.device import CircularSpinChain, LinearSpinChain
from qutip.qip.noise import RandomNoise
$\displaystyle H = - \frac{1}{2}\sum_n^N h_n \sigma_z(n) - \frac{1}{2} \sum_n^{N-1} [ J_x^{(n)} \sigma_x(n) \sigma_x(n+1) + J_y^{(n)} \sigma_y(n) \sigma_y(n+1) +J_z^{(n)} \sigma_z(n) \sigma_z(n+1)]$
The linear and circular spin chain models employing the nearest neighbor interaction can be implemented using the SpinChain class.
In [4]:
N = 3
qc = QubitCircuit(N)
qc.add_gate("CNOT", targets=[0], controls=[2])
The non-adjacent interactions are broken into a series of adjacent ones by the program automatically.
In [5]:
U_ideal = gate_sequence_product(qc.propagators())
U_ideal
Out[5]:
In [6]:
p1 = CircularSpinChain(N, correct_global_phase=True)
U_list = p1.run(qc)
U_physical = gate_sequence_product(U_list)
U_physical.tidyup(atol=1e-5)
Out[6]:
In [7]:
(U_ideal - U_physical).norm()
Out[7]:
The results obtained from the physical implementation agree with the ideal result.
In [8]:
p1.qc0.gates
Out[8]:
The gates are first convert to gates with adjacent interactions moving in the direction with the least number of qubits in between.
In [9]:
p1.qc1.gates
Out[9]:
They are then converted into the basis [ISWAP, RX, RZ]
In [10]:
p1.qc2.gates
Out[10]:
The time for each applied gate:
In [11]:
p1.get_full_tlist()
Out[11]:
The pulse can be plotted as:
In [12]:
p1.plot_pulses();
In [13]:
p2 = LinearSpinChain(N, correct_global_phase=True)
U_list = p2.run(qc)
U_physical = gate_sequence_product(U_list)
U_physical.tidyup(atol=1e-5)
Out[13]:
In [14]:
(U_ideal - U_physical).norm()
Out[14]:
The results obtained from the physical implementation agree with the ideal result.
In [15]:
p2.qc0.gates
Out[15]:
The gates are first convert to gates with adjacent interactions moving in the direction with the least number of qubits in between.
In [16]:
p2.qc1.gates
Out[16]:
They are then converted into the basis [ISWAP, RX, RZ]
In [17]:
p2.qc2.gates
Out[17]:
The time for each applied gate:
In [18]:
p2.get_full_tlist()
Out[18]:
The pulse can be plotted as:
In [19]:
p2.plot_pulses();
From QuTiP 4.5, we also add the possibility to allow numerical simulation of SpinChain
-based quantum computing. One needs only to add an option analytical=False
in run_state
to use one of the QuTiP solvers to simulate the state evolution instead of direct matrix product. Under numerical simulation, one can go beyond simulation with perfect gate operations. All the noise defined for the class Processor
can also be used for SpinChain
here.
In [23]:
from qutip import basis, fidelity
N = 1
plus_state = (basis(2,0) + basis(2,1)).unit()
qc = QubitCircuit(N=N)
qc.add_gate("SNOT", targets=0)
processor = LinearSpinChain(N=N)
processor.load_circuit(qc)
end_state = processor.run_state(init_state=basis(2, 0), analytical=False).states[-1]
fidelity(end_state, plus_state)
Out[23]:
In [24]:
processor.add_noise(RandomNoise(rand_gen=np.random.normal, dt=0.1, loc=0.1, scale=0.2))
end_state = processor.run_state(init_state=basis(2, 0), analytical=False).states[-1]
fidelity(end_state, plus_state)
Out[24]:
As the control noise is coherent noise, the result of this noise is still a pure state. Therefore, we can visualize it on a Bloch sphere.
In [25]:
from qutip.bloch import Bloch
b = Bloch()
b.add_states([end_state, plus_state])
b.make_sphere()
In [25]:
from qutip.ipynbtools import version_table
version_table()
Out[25]:
In [ ]: