def test_gauss_square_samples(self): """Test that the gaussian square samples match the formula.""" duration = 125 sigma = 4 amp = 0.5j # formulaic times = np.array(range(25), dtype=np.complex_) times = times - (25 / 2) + 0.5 gauss = amp * np.exp(-(times / sigma)**2 / 2) # command command = GaussianSquare(duration=duration, sigma=sigma, amp=amp, width=100) samples = command.get_sample_pulse().samples np.testing.assert_almost_equal(samples[50], amp) np.testing.assert_almost_equal(samples[100], amp) np.testing.assert_almost_equal(samples[:10], gauss[:10])
def test_repr(self): """Test the repr methods for parametric pulses.""" gaus = Gaussian(duration=25, amp=0.7, sigma=4) self.assertEqual(repr(gaus), 'Gaussian(duration=25, amp=(0.7+0j), sigma=4)') gaus_square = GaussianSquare(duration=20, sigma=30, amp=1.0, width=3) self.assertEqual(repr(gaus_square), 'GaussianSquare(duration=20, amp=(1+0j), sigma=30, width=3)') drag = Drag(duration=5, amp=0.5, sigma=7, beta=1) self.assertEqual(repr(drag), 'Drag(duration=5, amp=(0.5+0j), sigma=7, beta=1)') const = ConstantPulse(duration=150, amp=0.1 + 0.4j) self.assertEqual(repr(const), 'ConstantPulse(duration=150, amp=(0.1+0.4j))')
def test_param_validation(self): """Test that parametric pulse parameters are validated when initialized.""" with self.assertRaises(PulseError): Gaussian(duration=25, sigma=0, amp=0.5j) with self.assertRaises(PulseError): GaussianSquare(duration=150, amp=0.2, sigma=8, width=160) with self.assertRaises(PulseError): ConstantPulse(duration=150, amp=0.9 + 0.8j) with self.assertRaises(PulseError): Drag(duration=25, amp=0.2 + 0.3j, sigma=-7.8, beta=4) with self.assertRaises(PulseError): Drag(duration=25, amp=0.2 + 0.3j, sigma=7.8, beta=4j)
def test_gauss_square_extremes(self): """Test that the gaussian square pulse can build a gaussian.""" duration = 125 sigma = 4 amp = 0.5j gaus_square = GaussianSquare(duration=duration, sigma=sigma, amp=amp, width=0) gaus = Gaussian(duration=duration, sigma=sigma, amp=amp) np.testing.assert_almost_equal(gaus_square.get_sample_pulse().samples, gaus.get_sample_pulse().samples) gaus_square = GaussianSquare(duration=duration, sigma=sigma, amp=amp, width=121) const = ConstantPulse(duration=duration, amp=amp) np.testing.assert_almost_equal(gaus_square.get_sample_pulse().samples[2:-2], const.get_sample_pulse().samples[2:-2])
def cr_drive_experiments(drive_idx, target_idx, flip_drive_qubit = False, #cr_drive_amps=np.linspace(0, 0.9, 16), #cr_drive_samples=800, #cr_drive_sigma=4, #pi_drive_samples=128, #pi_drive_sigma=16 #meas_amp = Dims/128*0.025/2 #meas_width = int(rows/128*1150/2) cr_drive_amps=np.linspace(0, 0.9, meas_width**2), cr_drive_samples=sum(label1[:] == label2[:]), cr_drive_sigma=meas_sigma, pi_drive_samples=sum((label1[:] ==1)*(label2[:] ==1)), #label1[:] ==1 and label2[:] ==1 pi_drive_sigma=cr_drive_sigma**2): """Generate schedules corresponding to CR drive experiments. Args: drive_idx (int): label of driven qubit target_idx (int): label of target qubit flip_drive_qubit (bool): whether or not to start the driven qubit in the ground or excited state cr_drive_amps (array): list of drive amplitudes to use cr_drive_samples (int): number samples for each CR drive signal cr_drive_sigma (float): standard deviation of CR Gaussian pulse pi_drive_samples (int): number samples for pi pulse on drive pi_drive_sigma (float): standard deviation of Gaussian pi pulse on drive Returns: list[Schedule]: A list of Schedule objects for each experiment """ # Construct measurement commands to be used for all schedules #meas_amp = 0.025 #meas_samples = 1200 #meas_sigma = 4 #meas_width = 1150 meas_amp = 0.025 meas_sigma = 4 ni = int(np.ceil(cols/meas_sigma)) print(ni) meas_samples = rows*ni meas_width = int(rows*ni*23/24) meas_pulse = GaussianSquare(duration=meas_samples, amp=meas_amp/np.linalg.norm(meas_amp), sigma=meas_sigma, width=meas_width) acq_sched = pulse.Acquire(meas_samples, pulse.AcquireChannel(0), pulse.MemorySlot(0)) acq_sched += pulse.Acquire(meas_samples, pulse.AcquireChannel(1), pulse.MemorySlot(1)) # create measurement schedule measure_sched = (pulse.Play(meas_pulse, pulse.MeasureChannel(0)) | pulse.Play(meas_pulse, pulse.MeasureChannel(1))| acq_sched) # Create schedule schedules = [] for ii, cr_drive_amp in enumerate(cr_drive_amps): # pulse for flipping drive qubit if desired pi_pulse = Gaussian(duration=pi_drive_samples, amp=pi_amps[drive_idx], sigma=pi_drive_sigma) # cr drive pulse cr_width = cr_drive_samples - 2*cr_drive_sigma*4 cr_rabi_pulse = GaussianSquare(duration=cr_drive_samples, amp=cr_drive_amp/np.linalg.norm(cr_drive_amp), sigma=cr_drive_sigma, width=cr_width) # add commands to schedule schedule = pulse.Schedule(name='cr_rabi_exp_amp_%s' % cr_drive_amp) #schedule = pulse.Schedule(name='cr_rabi_exp_amp_%s' % cr_drive_amp/np.linalg.norm(cr_drive_amp)) # flip drive qubit if desired if flip_drive_qubit: schedule += pulse.Play(pi_pulse, pulse.DriveChannel(drive_idx)) # do cr drive # First, get the ControlChannel index for CR drive from drive to target cr_idx = two_qubit_model.control_channel_index((drive_idx, target_idx)) schedule += pulse.Play(cr_rabi_pulse, pulse.ControlChannel(cr_idx)) << schedule.duration schedule += measure_sched << schedule.duration schedules.append(schedule) return schedules
dt=dt) #calibrate pi pulse on each qubit using Ihnis(default GaussianSquare) #4.1 Constructing the schedules # list of qubits to be used throughout the notebook qubits = [0, 1] # Construct a measurement schedule and add it to an InstructionScheduleMap meas_amp = 0.025 meas_sigma = 4 ni = int(np.ceil(cols/meas_sigma)) print(ni) meas_samples = rows*ni meas_width = int(rows*ni*23/24) meas_pulse = GaussianSquare(duration=meas_samples, amp=meas_amp, sigma=meas_sigma, width=meas_width) acq_sched = pulse.Acquire(meas_samples, pulse.AcquireChannel(0), pulse.MemorySlot(0)) acq_sched += pulse.Acquire(meas_samples, pulse.AcquireChannel(1), pulse.MemorySlot(1)) measure_sched = pulse.Play(meas_pulse, pulse.MeasureChannel(0)) | pulse.Play(meas_pulse, pulse.MeasureChannel(1)) | acq_sched inst_map = pulse.InstructionScheduleMap() inst_map.add('measure', qubits, measure_sched) #Rabi schedules #recall: Rabii oscillation # The magnetic moment is thus {\displaystyle {\boldsymbol {\mu }}={\frac {\hbar }{2}}\gamma {\boldsymbol {\sigma }}}{\boldsymbol {\mu }}={\frac {\hbar }{2}}\gamma {\boldsymbol {\sigma }}. # The Hamiltonian of this system is then given by {H} =-{{\mu }}\cdot{B} =-{\frac {\hbar }{2}}\omega _{0}\sigma _{z}-{\frac {\hbar }{2}}\omega _{1}(\sigma _{x}\cos \omega t-\sigma _{y}\sin \omega t)}\mathbf {H} =-{\boldsymbol {\mu }}\cdot \mathbf {B} =-{\frac {\hbar }{2}}\omega _{0}\sigma _{z}-{\frac {\hbar }{2}}\omega _{1}(\sigma _{x}\cos \omega t-\sigma _{y}\sin \omega t) where {\displaystyle \omega _{0}=\gamma B_{0}}\omega _{0}=\gamma B_{0} and {\displaystyle \omega _{1}=\gamma B_{1}}\omega _{1}=\gamma B_{1} # Now, let the qubit be in state {\displaystyle |0\rangle }{\displaystyle |0\rangle } at time {\displaystyle t=0}t=0. Then, at time {\displaystyle t}t, the probability of it being found in state {\displaystyle |1\rangle }|1\rangle is given by {\displaystyle P_{0\to 1}(t)=\left({\frac {\omega _{1}}{\Omega }}\right)^{2}\sin ^{2}\left({\frac {\Omega t}{2}}\right)}{\displaystyle P_{0\to 1}(t)=\left({\frac {\omega _{1}}{\Omega }}\right)^{2}\sin ^{2}\left({\frac {\Omega t}{2}}\right)} where {\displaystyle \Omega ={\sqrt {(\omega -\omega _{0})^{2}+\omega _{1}^{2}}}}\Omega ={\sqrt {(\omega -\omega _{0})^{2}+\omega _{1}^{2}}} # the qubit oscillates between the {\displaystyle |0\rangle }|0\rang and {\displaystyle |1\rangle }|1\rangle states.
qregs = QuantumRegister(config.n_qubits) circuit = QuantumCircuit(qregs) circuit.append(cr1_gate, qargs = [qregs[1], qregs[0]]) qpt_circuits = process_tomography_circuits(circuit, [qregs[0], qregs[1]]) #Create the QPT pulse scchedules qpt_circuits = transpile(qpt_circuits, backend, basis_gates) #qpt_schedules = schedule(qpt_circuits, backend, inst_map) #Local rotation angles for CNOT(1,0) determined during optimization+ local_rotations10 = [[1.45, 1.91, 1.64],[1.56, 3.08, 2.45],[-2.79, -3.05, -2.79],[2.16, -3.12, 0.02]] #Local rotation angles for CNOT(1,0) determined during optimization+ local_rotations01 = [[-1.68, 3.04, 1.66],[1.57, 2.28, -0.06],[1.48, -0.46, 3.14],[1.60, -3.14, 0.98]] #ceate the CR1 schedule cr1_pulse = GaussianSquare(meas_duration,meas_amp, meas_sigma, meas_square_width) sched = Schedule() sched += Play(cr1_pulse, ControlChannel(0)) #Add the CR1 instruction to basis_gates and inst_map basis_gates += ['cr1'] inst_map.add(gate_name, [1,0], sched) #Create a quantum gate to reference the CR1 pulse schedule cr1_gate = Gate(gate_name, 2, []) #Generate RB circuits (2Q RB) #number of qubits nQ=2 rb_opts = {} #Number of Cliffords in the sequence
def test_construction(self): """Test that parametric pulses can be constructed without error.""" Gaussian(duration=25, sigma=4, amp=0.5j) GaussianSquare(duration=150, amp=0.2, sigma=8, width=140) ConstantPulse(duration=150, amp=0.1 + 0.4j) Drag(duration=25, amp=0.2 + 0.3j, sigma=7.8, beta=4)