1010 global_setup (fontsize = 10 )
1111except :
1212 pass
13+ plt .rcParams .update ({"text.usetex" : False , "font.size" : 10 })
1314from joblib import Parallel , delayed # for parallel simulations
14-
1515import numpy as np
1616from qutip import sigmax , sigmay , sigmaz , basis , qeye , tensor , Qobj , fock_dm
1717from qutip_qip .circuit import QubitCircuit , Gate
18- from qutip_qip .device import ModelProcessor
18+ from qutip_qip .device import ModelProcessor , Model
1919from qutip_qip .compiler import GateCompiler , Instruction
2020from qutip import Options
2121from qutip_qip .noise import Noise
2222
2323
24- class MyProcessor (ModelProcessor ):
25- """Custom processor built using ModelProcessor as the base class.
26-
27- This custom processor will inherit all the methods of the base class
28- such as setting up of the T1 and T2 decoherence rates in the simulations.
29-
30- In addition, it is possible to write your own functions to add control
31- pulses.
32-
33- Args:
34- num_qubits (int): Number of qubits in the processor.
35- t1, t2 (float or list): The T1 and T2 decoherence rates for the
36- qubit. If it is a list, then it is assumed that
37- each element of the list corresponds to the rates
38- for each of the qubits.
39- """
40-
41- def __init__ (self , num_qubits , t1 = None , t2 = None ):
42- super ().__init__ (num_qubits , t1 = t1 , t2 = t2 )
43- self .pulse_mode = "discrete" # set the control pulse as discrete or continuous.
44- self .set_up_ops () # set up the available Hamiltonians.
45- self .dims = [2 ] * num_qubits # dimension of the quantum system.
46- self .num_qubits = num_qubits
47- self .native_gates = ["RX" , "RY" ]
24+ class MyModel (Model ):
25+ """A custom Hamiltonian model with sigmax and sigmay control."""
26+ def get_control (self , label ):
27+ """
28+ Get an avaliable control Hamiltonian.
29+ For instance, sigmax control on the zeroth qubits is labeld "sx0".
4830
49- def set_up_ops (self ):
50- """Sets up the single qubit control operators for each qubit."""
51- for m in range (self .num_qubits ):
52- self .add_control (2 * np .pi * sigmax () / 2 , m , label = "sx" + str (m ))
53- for m in range (self .num_qubits ):
54- self .add_control (2 * np .pi * sigmay () / 2 , m , label = "sy" + str (m ))
31+ Args:
32+ label (str): The label of the Hamiltonian
5533
34+ Returns:
35+ The Hamiltonian and target qubits as a tuple (qutip.Qobj, list).
36+ """
37+ targets = int (label [2 :])
38+ if label [:2 ] == "sx" :
39+ return 2 * np .pi * sigmax () / 2 , [targets ]
40+ elif label [:2 ] == "sy" :
41+ return 2 * np .pi * sigmax () / 2 , [targets ]
42+ else :
43+ raise NotImplementError ("Unknown control." )
5644
5745class MyCompiler (GateCompiler ):
5846 """Custom compiler for generating pulses from gates using the base class
@@ -87,10 +75,11 @@ def generate_pulse(self, gate, tlist, coeff, phase=0.0):
8775 to implement a gate containing the control pulses.
8876 """
8977 pulse_info = [
78+ # (control label, coeff)
9079 ("sx" + str (gate .targets [0 ]), np .cos (phase ) * coeff ),
9180 ("sy" + str (gate .targets [0 ]), np .sin (phase ) * coeff ),
9281 ]
93- return [Instruction (gate , tlist , pulse_info )]
82+ return [Instruction (gate , tlist = tlist , pulse_info = pulse_info )]
9483
9584 def single_qubit_gate_compiler (self , gate , args ):
9685 """Compiles single qubit gates to pulses.
@@ -133,17 +122,19 @@ def rotation_with_phase_compiler(self, gate, args):
133122circuit .add_gate ("RX" , targets = 0 , arg_value = np .pi / 2 )
134123circuit .add_gate ("Z" , targets = 0 )
135124
136- myprocessor = MyProcessor (1 )
125+ myprocessor = ModelProcessor (model = MyModel (num_qubits ))
126+ myprocessor .native_gates = ["RX" , "RY" ]
137127
138128mycompiler = MyCompiler (num_qubits , {"pulse_amplitude" : 0.02 })
139129
140130myprocessor .load_circuit (circuit , compiler = mycompiler )
141131result = myprocessor .run_state (basis (2 , 0 ))
142132
143133fig , ax = myprocessor .plot_pulses (
144- figsize = (LINEWIDTH * 0.7 , LINEWIDTH / 2 * 0.7 ), dpi = 200
134+ figsize = (LINEWIDTH * 0.7 , LINEWIDTH / 2 * 0.7 ), dpi = 200 ,
135+ use_control_latex = False
145136)
146- ax [- 1 ].set_xlabel ("Time " )
137+ ax [- 1 ].set_xlabel ("$t$ " )
147138fig .tight_layout ()
148139fig .savefig ("custom_compiler_pulse.pdf" )
149140fig .show ()
@@ -166,8 +157,8 @@ def get_noisy_dynamics(self, dims=None, pulses=None, systematic_noise=None):
166157 systematic_noise: A Pulse object (not used in this example).
167158 """
168159 for i , pulse in enumerate (pulses ):
169- if "sx" or "sy" not in pulse .label :
170- pass # filter out other pulses, e.g. drift
160+ if "sx" not in pulse . label and "sy" not in pulse .label :
161+ continue # filter out other pulses, e.g. drift
171162 target = pulse .targets [0 ]
172163 if target != 0 : # add pulse to the left neighbour
173164 pulses [i ].add_control_noise (
@@ -197,7 +188,7 @@ def single_crosstalk_simulation(num_gates):
197188 solver methods such as mesolve.
198189 """
199190 num_qubits = 2 # Qubit-0 is the target qubit. Qubit-1 suffers from crosstalk.
200- myprocessor = MyProcessor ( num_qubits )
191+ myprocessor = ModelProcessor ( model = MyModel ( num_qubits ) )
201192 # Add qubit frequency detuning 1.852MHz for the second qubit.
202193 myprocessor .add_drift (2 * np .pi * (sigmaz () + 1 ) / 2 * 1.852 , targets = 1 )
203194 myprocessor .native_gates = None # Remove the native gates
@@ -228,7 +219,6 @@ def single_crosstalk_simulation(num_gates):
228219 return result
229220
230221
231- num_qubits = 2
232222num_sample = 2
233223# num_sample = 1600
234224fidelity = []
@@ -247,31 +237,32 @@ def single_crosstalk_simulation(num_gates):
247237# Recorded result
248238num_gates_list = [250 , 500 , 750 , 1000 , 1250 , 1500 ]
249239data_y = [
250- 0.9577285560461476 ,
251- 0.9384849070716464 ,
252- 0.9230217713086177 ,
253- 0.9062344084919285 ,
254- 0.889009550855518 ,
255- 0.8749290612064392 ,
240+ 0.9566768747558925 ,
241+ 0.9388905075892828 ,
242+ 0.9229470389282218 ,
243+ 0.9075513000339529 ,
244+ 0.8941659320508855 ,
245+ 0.8756519016627652
256246]
247+
257248data_y_error = [
258- 0.000431399017208067 ,
259- 0.0008622091914303468 ,
260- 0.0012216267555118497 ,
261- 0.001537120153687202 ,
262- 0.0018528957172559654 ,
263- 0.0020169257334183596 ,
249+ 0.00042992029265330223 ,
250+ 0.0008339882813741004 ,
251+ 0.0012606632769758602 ,
252+ 0.0014643550337816722 ,
253+ 0.0017695604671714809 ,
254+ 0.0020964978542167617
264255]
265256
266257
267- def linear (x , a ):
258+ def rb_curve (x , a ):
268259 return (1 / 2 + np .exp (- 2 * a * x ) / 2 ) * 0.975
269260
270261
271- pos , cov = curve_fit (linear , num_gates_list , data_y , p0 = [0.001 ])
262+ pos , cov = curve_fit (rb_curve , num_gates_list , data_y , p0 = [0.001 ])
272263
273264xline = np .linspace (0 , 1700 , 200 )
274- yline = linear (xline , * pos )
265+ yline = rb_curve (xline , * pos )
275266
276267fig , ax = plt .subplots (figsize = (LINEWIDTH , 0.65 * LINEWIDTH ), dpi = 200 )
277268ax .errorbar (
0 commit comments