def test_delay(self): """Test delay.""" delay = Delay(10, DriveChannel(0), name='test_name') self.assertEqual(delay.name, "test_name") self.assertEqual(delay.duration, 10) self.assertEqual(delay.operands, [10, DriveChannel(0)])
def test_set_phase_rwa(self): """Test SetPhase command using an RWA approximate solution.""" omega_0 = 5.123 r = 0.01 system_model = self._system_model_1Q(omega_0, r) sched = Schedule() sched += SetPhase(np.pi / 2, DriveChannel(0)) sched += Play(Waveform(np.ones(100)), DriveChannel(0)) sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration y0 = np.array([1., 1.]) / np.sqrt(2) pulse_sim = PulseSimulator(system_model=system_model, initial_state=y0) qobj = assemble([sched], backend=pulse_sim, meas_level=2, meas_return='single', meas_map=[[0]], qubit_lo_freq=[omega_0], memory_slots=2, shots=1) results = pulse_sim.run(qobj).result() pulse_sim_yf = results.get_statevector() #run independent simulation phases = np.exp( (-1j * 2 * np.pi * omega_0 * np.array([1, -1]) / 2) * 100) approx_yf = phases * (expm(-1j * (np.pi / 2) * self.Y) @ y0) self.assertGreaterEqual(state_fidelity(pulse_sim_yf, approx_yf), 0.99)
def test_rzx_calibration_builder(self): """Test whether RZXCalibrationBuilderNoEcho scales pulses correctly.""" # Define a circuit with one RZX gate and an angle theta. theta = pi / 3 rzx_qc = circuit.QuantumCircuit(2) rzx_qc.rzx(theta / 2, 1, 0) # Verify that there are no calibrations for this circuit yet. self.assertEqual(rzx_qc.calibrations, {}) # apply the RZXCalibrationBuilderNoEcho. pass_ = RZXCalibrationBuilderNoEcho(self.backend) cal_qc = PassManager(pass_).run(rzx_qc) rzx_qc_duration = schedule(cal_qc, self.backend).duration # Check that the calibrations contain the correct instructions # and pulses on the correct channels. # pylint: disable=no-member rzx_qc_instructions = cal_qc.calibrations["rzx"][((1, 0), (theta / 2, ))].instructions self.assertEqual(rzx_qc_instructions[0][1].channel, DriveChannel(0)) self.assertTrue(isinstance(rzx_qc_instructions[0][1], Play)) self.assertTrue( isinstance(rzx_qc_instructions[0][1].pulse, GaussianSquare)) self.assertEqual(rzx_qc_instructions[1][1].channel, DriveChannel(1)) self.assertTrue(isinstance(rzx_qc_instructions[1][1], Delay)) self.assertEqual(rzx_qc_instructions[2][1].channel, ControlChannel(1)) self.assertTrue(isinstance(rzx_qc_instructions[2][1], Play)) self.assertTrue( isinstance(rzx_qc_instructions[2][1].pulse, GaussianSquare)) # Calculate the duration of one scaled Gaussian square pulse from the CX gate. cx_sched = self.inst_map.get("cx", qubits=(1, 0)) crs = [] for time, inst in cx_sched.instructions: # Identify the CR pulses. if isinstance(inst, Play) and not isinstance(inst, ShiftPhase): if isinstance(inst.channel, ControlChannel): crs.append((time, inst)) pulse_ = crs[0][1].pulse amp = pulse_.amp width = pulse_.width sigma = pulse_.sigma n_sigmas = (pulse_.duration - width) / sigma sample_mult = 16 gaussian_area = abs(amp) * sigma * np.sqrt(2 * np.pi) * erf(n_sigmas) area = gaussian_area + abs(amp) * width target_area = abs(theta) / (np.pi / 2.0) * area width = (target_area - gaussian_area) / abs(amp) duration = ceil((width + n_sigmas * sigma) / sample_mult) * sample_mult # Check whether the durations of the RZX pulse and # the scaled CR pulse from the CX gate match. self.assertEqual(rzx_qc_duration, duration)
def create_excited_freq_sweep_program(self, freqs, amp): if len(freqs) > 75: raise ValueError("You can only run 75 schedules at a time.") base_12_pulse = pulse_lib.gaussian(duration=self.drive_samples, sigma=self.drive_sigma, amp=amp, name='base_12_pulse') schedules = [] for jj, freq in enumerate(freqs): freq_sweep_12_pulse = self.apply_sideband(base_12_pulse, freq) schedule = pulse.Schedule(name="Frequency = {}".format(freq)) schedule |= self.sched_x schedule |= pulse.Play(freq_sweep_12_pulse, DriveChannel( self.qubit)) << schedule.duration schedule |= self.sched_meas << schedule.duration # 駆動パルスの後に測定をシフト schedules.append(schedule) excited_freq_sweep_program = assemble( schedules, backend=self.backend, meas_level=1, meas_return='avg', shots=self.shots, schedule_los=[{ DriveChannel(self.qubit): self.default_qubit_freq }] * len(freqs)) return excited_freq_sweep_program
def create_ground_freq_sweep_program(self, freqs, amp): if len(freqs) > 75: raise ValueError("You can only run 75 schedules at a time.") # Define the drive pulse ground_sweep_drive_pulse = pulse_lib.gaussian( duration=self.drive_samples, sigma=self.drive_sigma, amp=amp, name='ground_sweep_drive_pulse') # Create the base schedule schedule = pulse.Schedule( name='Frequency sweep starting from ground state.') schedule |= pulse.Play(ground_sweep_drive_pulse, DriveChannel(self.qubit)) schedule |= self.sched_meas << schedule.duration # define frequencies for the sweep schedule_freqs = [{DriveChannel(self.qubit): freq} for freq in freqs] # assemble the program ground_freq_sweep_program = assemble(schedule, backend=self.backend, meas_level=1, meas_return='avg', shots=self.shots, schedule_los=schedule_freqs) return ground_freq_sweep_program
def _1Q_frame_change_schedule(self, phi, fc_phi, total_samples, dur_drive1, dur_drive2): """Creates schedule for frame change test. Does a pulse w/ phase phi of duration dur_drive1, then frame change of phase fc_phi, then another pulse of phase phi of duration dur_drive2. The different durations for the pulses allow manipulation of rotation angles on Bloch sphere Args: phi (float): drive phase (phi in Hamiltonian) fc_phi (float): phase for frame change total_samples (int): length of pulses dur_drive1 (int): duration of first pulse dur_drive2 (int): duration of second pulse Returns: schedule (pulse schedule): schedule for frame change test """ phase = np.exp(1j * phi) drive_pulse_1 = SamplePulse(phase * np.ones(dur_drive1), name='drive_pulse_1') drive_pulse_2 = SamplePulse(phase * np.ones(dur_drive2), name='drive_pulse_2') # add commands to schedule schedule = Schedule(name='fc_schedule') schedule |= Play(drive_pulse_1, DriveChannel(0)) schedule += ShiftPhase(fc_phi, DriveChannel(0)) schedule += Play(drive_pulse_2, DriveChannel(0)) schedule |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0)) << schedule.duration return schedule
def check(self, pi_pulse_12): # 基底状態のスケジュール zero_schedule = pulse.Schedule(name="zero schedule") zero_schedule |= self.sched_meas # 励起状態のスケジュール one_schedule = pulse.Schedule(name="one schedule") one_schedule |= self.sched_x one_schedule |= self.sched_meas << one_schedule.duration # 励起状態のスケジュール two_schedule = pulse.Schedule(name="two schedule") two_schedule |= self.sched_x two_schedule |= pulse.Play(pi_pulse_12, DriveChannel( self.qubit)) << two_schedule.duration two_schedule |= self.sched_meas << two_schedule.duration # プログラムにスケジュールを組み込みます IQ_012_program = assemble( [zero_schedule, one_schedule, two_schedule], backend=self.backend, meas_level=1, meas_return='single', shots=self.shots, schedule_los=[{ DriveChannel(self.qubit): self.default_qubit_freq }] * 3) IQ_012_job = self.backend.run(IQ_012_program) job_monitor(IQ_012_job) IQ_012_data = self.get_job_data(IQ_012_job, average=False) return IQ_012_data
def test_freq(self): """Test set frequency basic functionality.""" set_freq = SetFrequency(4.5e9, DriveChannel(1), name='test') self.assertIsInstance(set_freq.id, int) self.assertEqual(set_freq.duration, 0) self.assertEqual(set_freq.frequency, 4.5e9) self.assertEqual(set_freq.operands, (4.5e9, DriveChannel(1))) self.assertEqual(set_freq, SetFrequency(4.5e9, DriveChannel(1), name='test')) self.assertNotEqual(set_freq, SetFrequency(4.5e8, DriveChannel(1), name='test')) self.assertEqual(repr(set_freq), "SetFrequency(4500000000.0, DriveChannel(1), name='test')")
def test_default(self): """Test basic ShiftPhase.""" shift_phase = ShiftPhase(1.57, DriveChannel(0)) self.assertIsInstance(shift_phase.id, int) self.assertEqual(shift_phase.name, None) self.assertEqual(shift_phase.duration, 0) self.assertEqual(shift_phase.phase, 1.57) self.assertEqual(shift_phase.operands, (1.57, DriveChannel(0))) self.assertEqual(shift_phase, ShiftPhase(1.57, DriveChannel(0), name='test')) self.assertNotEqual(shift_phase, ShiftPhase(1.57j, DriveChannel(0), name='test')) self.assertEqual(repr(shift_phase), "ShiftPhase(1.57, DriveChannel(0))")
def test_delay(self): """Test delay.""" delay = Delay(10, DriveChannel(0), name='test_name') self.assertIsInstance(delay.id, int) self.assertEqual(delay.name, 'test_name') self.assertEqual(delay.duration, 10) self.assertEqual(delay.operands, (10, DriveChannel(0))) self.assertEqual(delay, Delay(10, DriveChannel(0))) self.assertNotEqual(delay, Delay(11, DriveChannel(1))) self.assertEqual(repr(delay), "Delay(10, DriveChannel(0), name='test_name')")
def setUp(self): """Setup some schedules.""" super().setUp() with pulse.build(name="xp") as xp: pulse.play(Drag(duration=160, amp=0.208519, sigma=40, beta=0.0), DriveChannel(0)) with pulse.build(name="x90p") as x90p: pulse.play(Drag(duration=160, amp=0.208519, sigma=40, beta=0.0), DriveChannel(0)) self.x_plus = xp self.x_90_plus = x90p
def test_shift_frequency(self): """Test that the frequency is properly taken into account.""" sched = Schedule() sched += ShiftFrequency(1.0, DriveChannel(0)) sched += Play(Constant(duration=10, amp=1.0), DriveChannel(0)) converter = InstructionToSignals(dt=0.222, carriers=[5.0]) signals = converter.get_signals(sched) for idx in range(10): self.assertEqual(signals[0].samples[idx], np.exp(2.0j * idx * np.pi * 1.0 * 0.222))
def test_shift_phase_to_signals(self): """Test that a shift phase gives negative envelope.""" gaussian = Gaussian(duration=20, amp=0.5, sigma=4) sched = Schedule(name="Schedule") sched += ShiftPhase(np.pi, DriveChannel(0)) sched += Play(gaussian, DriveChannel(0)) converter = InstructionToSignals(dt=1, carriers=None) signals = converter.get_signals(sched) self.assertTrue(signals[0].samples[10] < 0) self.assertTrue(gaussian.get_waveform().samples[10] > 0)
def test_pulse_gates(self): """Test scheduling calibrated pulse gates.""" q = QuantumRegister(2) qc = QuantumCircuit(q) qc.append(U2Gate(0, 0), [q[0]]) qc.barrier(q[0], q[1]) qc.append(U2Gate(0, 0), [q[1]]) qc.add_calibration('u2', [0], Schedule(Play(Gaussian(28, 0.2, 4), DriveChannel(0))), [0, 0]) qc.add_calibration('u2', [1], Schedule(Play(Gaussian(28, 0.2, 4), DriveChannel(1))), [0, 0]) sched = schedule(qc, self.backend) expected = Schedule( Play(Gaussian(28, 0.2, 4), DriveChannel(0)), (28, Schedule(Play(Gaussian(28, 0.2, 4), DriveChannel(1))))) self.assertEqual(sched.instructions, expected.instructions)
def amp_sweep(self, drive_durations, amp_times, sched_cx, init_state): duration_schedules = [] for cr_duration in drive_durations: sched = pulse.Schedule() sched_cx_copy = copy.deepcopy(sched_cx) if (init_state == 1) or (init_state == 2): sched += self.sched_x if init_state == 2: sched += pulse.Play(self.pi_pulse_12, DriveChannel(self.ctr_q2)) new_cx = pulse.Schedule() for index, instruction in enumerate(sched_cx_copy.instructions): child = instruction[1] if type(child.pulse) != pulse_lib.GaussianSquare: new_cx += child else: mini_pulse = child.pulse mini_pulse._width = mini_pulse.width * cr_duration / mini_pulse.duration mini_pulse.duration = cr_duration mini_pulse._amp = amp_times * mini_pulse._amp new_cx = new_cx.insert(new_cx.duration, child) sched |= new_cx << sched.duration sched |= self.sched_meas_tar_q << sched.duration # 駆動パルスの後に測定をシフト duration_schedules.append(sched) return duration_schedules
def test_pass_alive_with_dcx_ish(self): """Test if the pass is not terminated by error with direct CX input.""" cx_sched = Schedule() # Fake direct cr cx_sched.insert(0, Play(GaussianSquare(800, 0.2, 64, 544), ControlChannel(1)), inplace=True) # Fake direct compensation tone # Compensation tone doesn't have dedicated pulse class. # So it's reported as a waveform now. compensation_tone = Waveform(0.1 * np.ones(800, dtype=complex)) cx_sched.insert(0, Play(compensation_tone, DriveChannel(0)), inplace=True) inst_map = InstructionScheduleMap() inst_map.add("cx", (1, 0), schedule=cx_sched) theta = pi / 3 rzx_qc = circuit.QuantumCircuit(2) rzx_qc.rzx(theta, 1, 0) pass_ = RZXCalibrationBuilder(instruction_schedule_map=inst_map) with self.assertWarns(UserWarning): # User warning that says q0 q1 is invalid cal_qc = PassManager(pass_).run(rzx_qc) self.assertEqual(cal_qc, rzx_qc)
def _schedule_2Q_interaction(self, total_samples): """Creates schedule for testing two qubit interaction. Specifically, do a pi pulse on qub 0 so it starts in the `1` state (drive channel) and then apply constant pulses to each qubit (on control channel 1). This will allow us to test a swap gate. Args: total_samples (int): length of pulses Returns: schedule (pulse schedule): schedule for 2q experiment """ # create acquire schedule acq_sched = Schedule(name='acq_sched') acq_sched |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0)) acq_sched += Acquire(total_samples, AcquireChannel(1), MemorySlot(1)) # set up const pulse const_pulse = SamplePulse(np.ones(total_samples), name='const_pulse') # add commands to schedule schedule = Schedule(name='2q_schedule') schedule |= Play(const_pulse, DriveChannel(0)) schedule += Play(const_pulse, ControlChannel(1)) << schedule.duration schedule |= acq_sched << schedule.duration return schedule
def test_default(self): """Test basic ShiftPhase.""" shift_phase = ShiftPhase(1.57, DriveChannel(0)) self.assertEqual(shift_phase.phase, 1.57) self.assertEqual(shift_phase.duration, 0) self.assertTrue(shift_phase.name.startswith('shiftphase'))
def _simple_1Q_schedule(self, phi, total_samples, shape="square", gauss_sigma=0): """Creates schedule for single pulse test Args: phi (float): drive phase (phi in Hamiltonian) total_samples (int): length of pulses shape (str): shape of the pulse; defaults to square pulse gauss_sigma (float): std dev for gaussian pulse if shape=="gaussian" Returns: schedule (pulse schedule): schedule for this test """ # set up pulse command phase = np.exp(1j * phi) drive_pulse = None if shape == "square": const_pulse = np.ones(total_samples) drive_pulse = SamplePulse(phase * const_pulse, name='drive_pulse') if shape == "gaussian": times = 1.0 * np.arange(total_samples) gaussian = np.exp(-times**2 / 2 / gauss_sigma**2) drive_pulse = SamplePulse(phase * gaussian, name='drive_pulse') # add commands into a schedule for first qubit schedule = Schedule(name='drive_pulse') schedule |= Play(drive_pulse, DriveChannel(0)) schedule |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0)) << schedule.duration return schedule
def test_scheduling_with_calibration(self): """Test if calibrated instruction can update node duration.""" qc = QuantumCircuit(2) qc.x(0) qc.cx(0, 1) qc.x(1) qc.cx(0, 1) xsched = Schedule(Play(Constant(300, 0.1), DriveChannel(0))) qc.add_calibration("x", (0, ), xsched) durations = InstructionDurations([("x", None, 160), ("cx", None, 600)]) pm = PassManager([ASAPScheduleAnalysis(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(2) expected.x(0) expected.delay(300, 1) expected.cx(0, 1) expected.x(1) expected.delay(160, 0) expected.cx(0, 1) expected.add_calibration("x", (0, ), xsched) self.assertEqual(expected, scheduled)
def test_play(self): """Test basic play instruction.""" duration = 64 pulse = pulse_lib.SamplePulse([1.0] * duration, name='test') play = Play(pulse, DriveChannel(1)) self.assertEqual(play.name, pulse.name) self.assertEqual(play.duration, duration)
def test_copy_empty_like_circuit(self): """Test copy_empty_like method makes a clear copy.""" qr = QuantumRegister(2) cr = ClassicalRegister(2) qc = QuantumCircuit(qr, cr, global_phase=1.0, name="qc", metadata={"key": "value"}) qc.h(qr[0]) qc.measure(qr[0], cr[0]) qc.measure(qr[1], cr[1]) sched = Schedule(Play(Gaussian(160, 0.1, 40), DriveChannel(0))) qc.add_calibration("h", [0, 1], sched) copied = qc.copy_empty_like() qc.clear() self.assertEqual(qc, copied) self.assertEqual(qc.global_phase, copied.global_phase) self.assertEqual(qc.name, copied.name) self.assertEqual(qc.metadata, copied.metadata) self.assertEqual(qc.calibrations, copied.calibrations) copied = qc.copy_empty_like("copy") self.assertEqual(copied.name, "copy")
def test_alap_aligns_end(self): """Test that ALAP always acts as though there is a final global barrier.""" q = QuantumRegister(2) c = ClassicalRegister(2) qc = QuantumCircuit(q, c) qc.u3(0, 0, 0, q[0]) qc.u2(0, 0, q[1]) sched = schedule(qc, self.backend, method='alap') expected_sched = Schedule(self.inst_map.get('u2', [1], 0, 0), (26, self.inst_map.get('u3', [0], 0, 0, 0))) for actual, expected in zip(sched.instructions, expected_sched.instructions): self.assertEqual(actual[0], expected[0]) self.assertEqual(actual[1], expected[1]) self.assertEqual(sched.ch_duration(DriveChannel(0)), expected_sched.ch_duration(DriveChannel(1)))
def build_sample_pulse_schedule(number_of_unique_pulses, number_of_channels): rng = np.random.RandomState(42) sched = Schedule() for _ in range(number_of_unique_pulses): for channel in range(number_of_channels): sched.append(Play(Waveform(rng.random(50)), DriveChannel(channel))) return sched
def amp(self, rabi_freq, amp_med): if amp_med == None: drive_amp_min = 0 drive_amp_max = 0.5 drive_amps = np.linspace(drive_amp_min, drive_amp_max, self.times) else: drive_amps = np.linspace(0, amp_med + 0.1, self.times) # スケジュールの作成 rabi_12_schedules = [] # すべての駆動振幅をループします for ii, drive_amp in enumerate(drive_amps): base_12_pulse = pulse_lib.gaussian(duration=self.drive_samples, sigma=self.drive_sigma, amp=drive_amp, name='base_12_pulse') # 1->2の周波数においてサイドバンドを適用 rabi_12_pulse = self.apply_sideband(base_12_pulse, rabi_freq) # スケジュールにコマンドを追加 sched = pulse.Schedule(name='Rabi Experiment at drive amp = %s' % drive_amp) sched |= self.sched_x # 0->1 sched |= pulse.Play(rabi_12_pulse, DriveChannel( self.qubit)) << sched.duration # 1->2のラビパルス sched |= self.sched_meas << sched.duration # 駆動パルスの後に測定をシフト rabi_12_schedules.append(sched) rabi_12_expt_program = assemble( rabi_12_schedules, backend=self.backend, meas_level=1, meas_return='avg', shots=self.shots, schedule_los=[{ DriveChannel(self.qubit): self.default_qubit_freq }] * len(drive_amps)) rabi_12_job = self.backend.run(rabi_12_expt_program) job_monitor(rabi_12_job) rabi_12_data = self.get_job_data(rabi_12_job, average=True) return rabi_12_data, drive_amps
def build_parametric_pulse_schedule(number_of_unique_pulses, number_of_channels): sched = Schedule() for _ in range(number_of_unique_pulses): for channel in range(number_of_channels): sched.append( Play(Gaussian(duration=25, sigma=4, amp=0.5j), DriveChannel(channel))) return sched
def test_parametric_input(self): """Test that scheduling works with parametric pulses as input.""" qr = QuantumRegister(1) qc = QuantumCircuit(qr) qc.append(Gate("gauss", 1, []), qargs=[qr[0]]) custom_gauss = Schedule(Play(Gaussian(duration=25, sigma=4, amp=0.5j), DriveChannel(0))) self.inst_map.add("gauss", [0], custom_gauss) sched = schedule(qc, self.backend, inst_map=self.inst_map) self.assertEqual(sched.instructions[0], custom_gauss.instructions[0])
def test_default(self): """Test default snapshot.""" snapshot = Snapshot(label='test_name', snapshot_type='state') self.assertIsInstance(snapshot.id, int) self.assertEqual(snapshot.name, 'test_name') self.assertEqual(snapshot.type, 'state') self.assertEqual(snapshot.duration, 0) self.assertNotEqual(snapshot, Delay(10, DriveChannel(0))) self.assertEqual(repr(snapshot), "Snapshot(test_name, state, name='test_name')")
def test_scheduler_with_params_not_bound(self): """Test scheduler with parameters defined but not bound""" x = Parameter("amp") qc = QuantumCircuit(2) qc.append(Gate("pulse_gate", 1, [x]), [0]) with build() as expected_schedule: play(Gaussian(duration=160, amp=x, sigma=40), DriveChannel(0)) qc.add_calibration(gate="pulse_gate", qubits=[0], schedule=expected_schedule, params=[x]) sched = schedule(qc, self.backend) self.assertEqual(sched, transforms.target_qobj_transform(expected_schedule))
def test_gaussian_drive(self): """Test gaussian drive pulse using meas_level_2. Set omega_d0=omega_0 (drive on resonance), phi=0, omega_a = pi/time """ # set omega_0, omega_d0 equal (use qubit frequency) -> drive on resonance total_samples = 100 omega_0 = 1. omega_d = omega_0 # Require omega_a*time = pi to implement pi pulse (x gate) # num of samples gives time r = np.pi / total_samples # initial state and seed y0 = np.array([1., 0.]) seed = 9000 # Test gaussian drive results for a few different sigma gauss_sigmas = [total_samples / 6, total_samples / 3, total_samples] # set up pulse simulator pulse_sim = PulseSimulator(system_model=self._system_model_1Q(omega_0, r)) for gauss_sigma in gauss_sigmas: with self.subTest(gauss_sigma=gauss_sigma): times = 1.0 * np.arange(total_samples) gaussian_samples = np.exp(-times**2 / 2 / gauss_sigma**2) drive_pulse = Waveform(gaussian_samples, name='drive_pulse') # construct schedule schedule = Schedule() schedule |= Play(drive_pulse, DriveChannel(0)) schedule |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << schedule.duration qobj = assemble([schedule], backend=pulse_sim, meas_level=2, meas_return='single', meas_map=[[0]], qubit_lo_freq=[omega_d], memory_slots=2, shots=1) result = pulse_sim.run(qobj, initial_state=y0, seed=seed).result() pulse_sim_yf = result.get_statevector() # run independent simulation yf = simulate_1q_model(y0, omega_0, r, np.array([omega_d]), gaussian_samples, 1.) # Check fidelity of statevectors self.assertGreaterEqual(state_fidelity(pulse_sim_yf, yf), 1 - (10**-5))