def test_call_gate_and_circuit(self): """Test calling circuit with gates.""" h_control = circuit.QuantumCircuit(2) h_control.h(0) with pulse.build(self.backend) as schedule: with pulse.align_sequential(): # this is circuit, a subroutine stored as Call instruction pulse.call(h_control) # this is instruction, not subroutine pulse.cx(0, 1) # this is macro, not subroutine pulse.measure([0, 1]) # subroutine h_reference = compiler.schedule(compiler.transpile(h_control, self.backend), self.backend) # gate cx_circ = circuit.QuantumCircuit(2) cx_circ.cx(0, 1) cx_reference = compiler.schedule(compiler.transpile(cx_circ, self.backend), self.backend) # measurement measure_reference = macros.measure( qubits=[0, 1], inst_map=self.inst_map, meas_map=self.configuration.meas_map ) reference = pulse.Schedule() reference += pulse.instructions.Call(h_reference) reference += cx_reference reference += measure_reference << reference.duration self.assertScheduleEqual(schedule, reference)
def test_call_with_not_existing_parameter(self): """Test call subroutine with parameter not defined.""" amp = circuit.Parameter('amp1') with pulse.build() as subroutine: pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0)) with self.assertRaises(exceptions.PulseError): with pulse.build(): pulse.call(subroutine, amp=0.1)
def test_call_subroutine_with_parametrized_duration(self): """Test call subroutine containing a parametrized duration.""" dur = circuit.Parameter("dur") with pulse.build() as subroutine: pulse.play(pulse.Constant(dur, 0.1), pulse.DriveChannel(0)) pulse.play(pulse.Constant(dur, 0.2), pulse.DriveChannel(0)) with pulse.build() as main: pulse.call(subroutine) self.assertEqual(len(main.blocks), 1)
def test_subroutine_not_transpiled(self): """Test called circuit is frozen as a subroutine.""" subprogram = circuit.QuantumCircuit(1) subprogram.x(0) transpiler_settings = {"optimization_level": 2} with pulse.build(self.backend, default_transpiler_settings=transpiler_settings) as schedule: pulse.call(subprogram) pulse.call(subprogram) self.assertNotEqual(len(target_qobj_transform(schedule).instructions), 0)
def test_call_circuit_with_cregs(self): """Test calling of circuit wiht classical registers.""" qc = circuit.QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1]) with pulse.build(self.backend) as schedule: pulse.call(qc) reference_qc = compiler.transpile(qc, self.backend) reference = compiler.schedule(reference_qc, self.backend) self.assertEqual(schedule, reference)
def test_deepcopying_subroutine(self): """Test if deepcopying the schedule can copy inline subroutine.""" from copy import deepcopy with pulse.build() as subroutine: pulse.delay(10, pulse.DriveChannel(0)) with pulse.build() as main_prog: pulse.call(subroutine) copied_prog = deepcopy(main_prog) main_call = main_prog.instructions[0][1] copy_call = copied_prog.instructions[0][1] self.assertNotEqual(id(main_call), id(copy_call))
def test_assign_parameters_to_call(self): """Test create schedule by calling subroutine and assign parameters to it.""" init_dict = {self.param1: 0.1, self.param2: 0.5} with pulse.build() as test_sched: pulse.call(self.function) test_sched = test_sched.assign_parameters(value_dict=init_dict) test_sched = inline_subroutines(test_sched) with pulse.build() as ref_sched: pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.5, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) self.assertEqual(test_sched, ref_sched)
def test_call_with_common_parameter(self): """Test call subroutine with parameter that is defined multiple times.""" amp = circuit.Parameter('amp') with pulse.build() as subroutine: pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(320, amp, 80), pulse.DriveChannel(0)) with pulse.build() as main_prog: pulse.call(subroutine, amp=0.1) assigned_sched = inline_subroutines(main_prog) play_0 = assigned_sched.instructions[0][1] play_1 = assigned_sched.instructions[1][1] self.assertEqual(play_0.pulse.amp, 0.1) self.assertEqual(play_1.pulse.amp, 0.1)
def test_call_subroutine_with_different_parameters(self): """Test call subroutines with different parameters in the same schedule.""" init_dict1 = {self.param1: 0.1, self.param2: 0.5} init_dict2 = {self.param1: 0.3, self.param2: 0.7} with pulse.build() as test_sched: pulse.call(self.function, value_dict=init_dict1) pulse.call(self.function, value_dict=init_dict2) with pulse.build() as ref_sched: pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.5, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.3, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.7, 40), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, 0.3, 40), pulse.DriveChannel(0)) self.assertEqual(target_qobj_transform(test_sched), target_qobj_transform(ref_sched))
def test_call_with_parameters(self): """Test call subroutine with parameters.""" amp = circuit.Parameter('amp') with pulse.build() as subroutine: pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0)) with pulse.build() as main_prog: pulse.call(subroutine, amp=0.1) pulse.call(subroutine, amp=0.3) self.assertEqual(main_prog.is_parameterized(), False) assigned_sched = inline_subroutines(main_prog) play_0 = assigned_sched.instructions[0][1] play_1 = assigned_sched.instructions[1][1] self.assertEqual(play_0.pulse.amp, 0.1) self.assertEqual(play_1.pulse.amp, 0.3)
def test_subroutine_not_transformed(self): """Test called schedule is not transformed.""" d0 = pulse.DriveChannel(0) d1 = pulse.DriveChannel(1) subprogram = pulse.Schedule() subprogram.insert(0, pulse.Delay(30, d0), inplace=True) subprogram.insert(10, pulse.Delay(10, d1), inplace=True) with pulse.build() as target: with pulse.align_right(): pulse.delay(10, d1) pulse.call(subprogram) reference = pulse.Schedule() reference.insert(0, pulse.Delay(10, d1), inplace=True) reference.insert(10, pulse.Delay(30, d0), inplace=True) reference.insert(20, pulse.Delay(10, d1), inplace=True) self.assertScheduleEqual(target, reference)
def test_call_schedule(self): """Test calling schedule instruction.""" schedule = pulse.Schedule() d0 = pulse.DriveChannel(0) d1 = pulse.DriveChannel(1) reference = pulse.Schedule() reference = reference.insert(10, instructions.Delay(10, d0)) reference += instructions.Delay(20, d1) with pulse.build() as schedule: with pulse.align_right(): builder.call_schedule(reference) self.assertEqual(schedule, reference) with pulse.build() as schedule: with pulse.align_right(): pulse.call(reference) self.assertEqual(schedule, reference)
def test_call_with_parameter_name_collision(self): """Test call subroutine with duplicated parameter names.""" amp1 = circuit.Parameter('amp') amp2 = circuit.Parameter('amp') sigma = circuit.Parameter('sigma') with pulse.build() as subroutine: pulse.play(pulse.Gaussian(160, amp1, sigma), pulse.DriveChannel(0)) pulse.play(pulse.Gaussian(160, amp2, sigma), pulse.DriveChannel(0)) with pulse.build() as main_prog: pulse.call(subroutine, value_dict={amp1: 0.1, amp2: 0.2}, sigma=40) assigned_sched = inline_subroutines(main_prog) play_0 = assigned_sched.instructions[0][1] play_1 = assigned_sched.instructions[1][1] self.assertEqual(play_0.pulse.amp, 0.1) self.assertEqual(play_0.pulse.sigma, 40) self.assertEqual(play_1.pulse.amp, 0.2) self.assertEqual(play_1.pulse.sigma, 40)
def test_call_partly_with_parameters(self): """Test multiple calls partly with parameters then assign.""" amp = circuit.Parameter("amp") with pulse.build() as subroutine: pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0)) with pulse.build() as main_prog: pulse.call(subroutine, amp=0.1) pulse.call(subroutine) self.assertEqual(main_prog.is_parameterized(), True) main_prog.assign_parameters({amp: 0.5}) self.assertEqual(main_prog.is_parameterized(), False) assigned_sched = target_qobj_transform(main_prog) play_0 = assigned_sched.instructions[0][1] play_1 = assigned_sched.instructions[1][1] self.assertEqual(play_0.pulse.amp, 0.1) self.assertEqual(play_1.pulse.amp, 0.5)
def test_used_in_calls(self): """Test that we can identify schedules by name when calls are present.""" with pulse.build(name="xp") as xp: pulse.play(pulse.Gaussian(160, 0.5, 40), pulse.DriveChannel(1)) with pulse.build(name="xp2") as xp2: pulse.play(pulse.Gaussian(160, 0.5, 40), pulse.DriveChannel(1)) with pulse.build(name="call_xp") as xp_call: pulse.call(xp) with pulse.build(name="call_call_xp") as xp_call_call: pulse.play(pulse.Drag(160, 0.5, 40, 0.2), pulse.DriveChannel(1)) pulse.call(xp_call) self.assertSetEqual(used_in_calls("xp", [xp_call]), {"call_xp"}) self.assertSetEqual(used_in_calls("xp", [xp2]), set()) self.assertSetEqual(used_in_calls("xp", [xp_call, xp_call_call]), {"call_xp", "call_call_xp"}) with pulse.build(name="xp") as xp: pulse.play(pulse.Gaussian(160, 0.5, 40), pulse.DriveChannel(2)) cr_tone_p = pulse.GaussianSquare(640, 0.2, 64, 500) rotary_p = pulse.GaussianSquare(640, 0.1, 64, 500) cr_tone_m = pulse.GaussianSquare(640, -0.2, 64, 500) rotary_m = pulse.GaussianSquare(640, -0.1, 64, 500) with pulse.build(name="cr") as cr: with pulse.align_sequential(): with pulse.align_left(): pulse.play(rotary_p, pulse.DriveChannel(3)) # Rotary tone pulse.play(cr_tone_p, pulse.ControlChannel(2)) # CR tone. pulse.call(xp) with pulse.align_left(): pulse.play(rotary_m, pulse.DriveChannel(3)) pulse.play(cr_tone_m, pulse.ControlChannel(2)) pulse.call(xp) self.assertSetEqual(used_in_calls("xp", [cr]), {"cr"})
# Create two schedules # Ground state schedule with pulse.build(backend=backend, default_alignment='sequential', name='ground state') as gnd_schedule: drive_chan = pulse.drive_channel(qubit) pulse.set_frequency(rough_qubit_frequency, drive_chan) pulse.measure(qubits=[qubit], registers=[pulse.MemorySlot(mem_slot)]) # Excited state schedule with pulse.build(backend=backend, default_alignment='sequential', name='excited state') as exc_schedule: drive_chan = pulse.drive_channel(qubit) pulse.set_frequency(rough_qubit_frequency, drive_chan) pulse.call(pi_pulse) pulse.measure(qubits=[qubit], registers=[pulse.MemorySlot(mem_slot)]) gnd_schedule.draw(backend=backend) exc_schedule.draw(backend=backend) # Execution settings num_shots = 1024 job = backend.run([gnd_schedule, exc_schedule], meas_level=1, meas_return='single', shots=num_shots) job_monitor(job) gnd_exc_results = job.result(timeout=120)
def output(data): print("We have F: ", data.F, " nT") N_delta = 2 N = int(math.log(data.T_2 * 10 ** (-6) / data.t_init) / math.log(2))-N_delta multiplier = 30 # Ramsey experiment parameters detuning_max_MHz = data.const * data.F_max * data.F_degree / (2 * math.pi) / MHz / multiplier detuning_min_MHz = data.const * data.F_min * data.F_degree / (2 * math.pi) / MHz / multiplier detuning_MHz = data.const * data.F * data.F_degree / (2 * math.pi) / MHz / multiplier delta_min_det_MHz = -0.05 - 0.02 - 0.12 - 0.22 delta_max_det_MHz = -0.05 - 0.05 - 0.05 - 0.12 - 0.20 detuning_MHz = (detuning_min_MHz+delta_min_det_MHz) + (detuning_max_MHz+delta_max_det_MHz - (detuning_min_MHz+delta_min_det_MHz))*(detuning_MHz - detuning_min_MHz)/(detuning_max_MHz-detuning_min_MHz) times = [data.t_init*2**(i) for i in range(N)] # Drive parameters # The drive amplitude for pi/2 is simply half the amplitude of the pi pulse drive_amp = pi_amp / 2 # x_90 is a concise way to say pi_over_2; i.e., an X rotation of 90 degrees with pulse.build(backend) as x90_pulse: drive_duration = get_closest_multiple_of_16(pulse.seconds_to_samples(drive_duration_sec)) drive_sigma = pulse.seconds_to_samples(drive_sigma_sec) drive_chan = pulse.drive_channel(qubit) pulse.play(pulse.Gaussian(duration=drive_duration, amp=drive_amp, sigma=drive_sigma, name='x90_pulse'), drive_chan) # create schedules for Ramsey experiment ramsey_schedules = [] ramsey_frequency = round(precise_qubit_freq + detuning_MHz * MHz, 6) # need ramsey freq in Hz for time in times: with pulse.build(backend=backend, default_alignment='sequential', name=f"det = {detuning_MHz} MHz") as ramsey_schedule: drive_chan = pulse.drive_channel(qubit) pulse.set_frequency(ramsey_frequency, drive_chan) pulse.call(x90_pulse) pulse.delay(get_closest_multiple_of_16(pulse.seconds_to_samples(time*multiplier)), drive_chan) pulse.call(x90_pulse) pulse.measure(qubits=[qubit], registers=[pulse.MemorySlot(mem_slot)]) ramsey_schedules.append(ramsey_schedule) # Execution settings num_shots = data.num_of_repetitions job = backend.run(ramsey_schedules, meas_level=1, meas_return='single', shots=num_shots) job_monitor(job) ramsey_results = job.result(timeout=120) ramsey_values = {} for i in range(len(times)): iq_data = ramsey_results.get_memory(i)[:, qubit] * scale_factor ramsey_values[times[i]]=int(round(sum(map(classify, iq_data)) / num_shots)) ''' times = [data.t_init * 2 ** (i) for i in range(N, N+N_delta)] # create schedules for Ramsey experiment ramsey_schedules = [] ramsey_frequency = round(precise_qubit_freq + detuning_MHz * MHz, 6) # need ramsey freq in Hz for time in times: with pulse.build(backend=backend, default_alignment='sequential', name=f"det = {detuning_MHz} MHz") as ramsey_schedule: drive_chan = pulse.drive_channel(qubit) pulse.set_frequency(ramsey_frequency, drive_chan) pulse.call(x90_pulse) pulse.delay(get_closest_multiple_of_16(pulse.seconds_to_samples(time * multiplier)), drive_chan) pulse.call(x90_pulse) pulse.measure(qubits=[qubit], registers=[pulse.MemorySlot(mem_slot)]) ramsey_schedules.append(ramsey_schedule) # Execution settings num_shots = data.num_of_repetitions job = backend.run(ramsey_schedules, meas_level=1, meas_return='single', shots=num_shots) job_monitor(job) ramsey_results = job.result(timeout=120) for i in range(len(times)): iq_data = ramsey_results.get_memory(i)[:, qubit] * scale_factor ramsey_values[times[i]] = int(round(sum(map(classify, iq_data)) / num_shots)) #''' print(ramsey_values) return ramsey_values #print(output(data))
def update_u_gates(drag_params, pi2_pulse_schedules=None, qubits=None, inst_map=None, drives=None): """Update the cmd_def with new single qubit gate values Will update U2, U3 Args: drag_params (list): list of drag params pi2_pulse_schedules (list): list of new pi/2 gate as a pulse schedule will use the drag_params if this is None. qubits (list): list of qubits to update inst_map (InstructionScheduleMap): InstructionScheduleMap providing circuit instruction to schedule definitions. drives (list): List of drive chs """ # pylint: disable = invalid-name # U2 is -P1.Y90p.-P0 # U3 is -P2.X90p.-P0.X90m.-P1 for qubit in qubits: drive_ch = drives[qubit] if pi2_pulse_schedules is None: x90_pulse = pulse_lib.drag(**drag_params[qubit]) x90_sched = Schedule() x90_sched += Play(x90_pulse, drive_ch).shift(0) else: x90_sched = pi2_pulse_schedules[qubit] # find channel dependency for u2 for _u2_group in _find_channel_groups('u2', qubits=qubit, inst_map=inst_map): if drive_ch in _u2_group: break else: _u2_group = (drive_ch, ) # find channel dependency for u3 for _u3_group in _find_channel_groups('u3', qubits=qubit, inst_map=inst_map): if drive_ch in _u3_group: break else: _u3_group = (drive_ch, ) # add commands to schedule # u2 with pulse.build(name=f"u2_{qubit}", default_alignment="sequential") as u2_sched: P0 = Parameter("P0") P1 = Parameter("P1") for ch in _u2_group: pulse.shift_phase(-P1 + np.pi / 2, ch) pulse.call(x90_sched) for ch in _u2_group: pulse.shift_phase(-P0 - np.pi / 2, ch) # u3 with pulse.build(name=f"u3_{qubit}", default_alignment="sequential") as u3_sched: P0 = Parameter("P0") P1 = Parameter("P1") P2 = Parameter("P2") for ch in _u3_group: pulse.shift_phase(-P2, ch) pulse.call(x90_sched) for ch in _u3_group: pulse.shift_phase(-P0 - np.pi, ch) pulse.call(x90_sched) for ch in _u3_group: pulse.shift_phase(-P1 + np.pi, ch) inst_map.add('u2', qubits=qubit, schedule=u2_sched) inst_map.add('u3', qubits=qubit, schedule=u3_sched)