def test_qasm_wait_timing_trigger_T1(self): # Tests the timing of the qasm sequences using a T1 sequence # 'q1' contains "trigger" instructions qasm_file = sqqs.T1('q1', self.times) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "T1_xf.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() instrs = compiler.qumis_instructions self.assertEqual(instrs[2], 'Exp_Start: ') wait_instrs = instrs[7:-4:6] # -4 in slicing exists to take out the calibration points for clock, wait_instr in zip(self.clocks[:-4], wait_instrs[:-4]): exp_wait = clock + 4 # +4 includes the length of the pulse instr_wait = int(wait_instr.split()[1]) self.assertEqual(instr_wait, exp_wait) init_instrs = instrs[3:-4:6] init_time = 200e-6 / 5e-9 - 1 # -1 is for the prepare codeword clock RO_time = 300e-9 / 5e-9 self.assertEqual(init_instrs[0], 'wait {:d}'.format(int(init_time))) for init_instr in init_instrs[1:-4]: self.assertEqual(init_instr, 'wait {:d}'.format(int(init_time + RO_time))) self.assertEqual(instrs[-1], self.jump_to_start)
def test_qwg_swapN(self): nr_pulses = [1, 3, 5, 11] qasm_file = qwfs.SWAPN('q0', 'q1', RO_target='q0', nr_pulses=nr_pulses) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) qumis = compiler.qumis_instructions m = open(compiler.qumis_fn).read() qumis_from_file = m.splitlines() self.assertEqual(qumis, qumis_from_file) self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) for i in range(3): time_pts = get_timepoints_from_label( target_label='square', timing_grid=compiler.timing_grid, start_label='qwg_trigger_{}'.format(i), end_label='ro') self.assertEqual(len(time_pts['target_tps']), nr_pulses[i]) time_pts = get_timepoints_from_label(target_label='ro', timing_grid=compiler.timing_grid) self.assertEqual(len(time_pts['target_tps']), len(nr_pulses) + 4) # finally test that it can be converted into valid instructions asm = Assembler(qumis_fn) asm.convert_to_instructions()
def test_converting_triggers_to_qumis(self): qasm_fn = join(self.test_file_dir, 'single_op.qasm') qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=0) compiler.compile(qasm_fn, qumis_fn) qumis = compiler.qumis_instructions x180_q1 = [qumis[15], qumis[17]] y180_q1 = [qumis[19], qumis[21]] x90_q1 = [qumis[23], qumis[25]] y90_q1 = [qumis[27], qumis[29]] mx90_q1 = [qumis[31], qumis[33]] my90_q1 = [qumis[35], qumis[37]] self.assertEqual(x180_q1[0], 'trigger 0100000, 1') self.assertEqual(x180_q1[1], 'trigger 1100000, 2') self.assertEqual(y180_q1[0], 'trigger 0010000, 1') self.assertEqual(y180_q1[1], 'trigger 1010000, 2') self.assertEqual(x90_q1[0], 'trigger 0110000, 1') self.assertEqual(x90_q1[1], 'trigger 1110000, 2') self.assertEqual(y90_q1[0], 'trigger 0001000, 1') self.assertEqual(y90_q1[1], 'trigger 1001000, 2') self.assertEqual(mx90_q1[0], 'trigger 0101000, 1') self.assertEqual(mx90_q1[1], 'trigger 1101000, 2') self.assertEqual(my90_q1[0], 'trigger 0011000, 1') self.assertEqual(my90_q1[1], 'trigger 1011000, 2')
def test_loading_config(self): compiler = qcx.QASM_QuMIS_Compiler() self.assertEqual(compiler.config_filename, '') self.assertNotEqual(compiler.config_filename, self.config_fn) compiler.load_config(self.config_fn) self.assertEqual(compiler.config_filename, self.config_fn) hardware_spec_keys = { 'qubit list', 'init time', 'cycle time', 'qubit_cfgs' } self.assertEqual(set(compiler.hardware_spec.keys()), hardware_spec_keys) self.assertEqual(compiler.qubit_map, { 'q0': 0, 'q1': 1, 'ql': 0, 'qr': 1 }) self.assertEqual(len(compiler.luts), 2) # MW and Flux allowed_single_q_ops = { 'i', 'x180', 'x90', 'y180', 'y90', 'mx90', 'my90' } self.assertEqual(set(compiler.luts[0].keys()), allowed_single_q_ops) # MW and Flux
def test_methods_of_compiler(self): compiler = qcx.QASM_QuMIS_Compiler() c_methods = set(dir(compiler)) printing_methods = { 'print_hw_timing_grid', 'print_program_lines', 'print_raw_lines', 'print_op_dict', 'print_qumis', 'print_raw_events', 'print_timing_events', 'print_timing_grid' } self.assertTrue(printing_methods.issubset(c_methods))
def compile_and_upload(self, qasm_fn, config): if self.upload: self.CBox.trigger_source('internal') qasm_folder, fn = os.path.split(qasm_fn) base_fn = fn.split('.')[0] qumis_fn = os.path.join(qasm_folder, base_fn + ".qumis") self.compiler = qcx.QASM_QuMIS_Compiler( verbosity_level=self.verbosity_level) self.compiler.compile(qasm_fn, qumis_fn=qumis_fn, config=config) if self.upload: self.CBox.load_instructions(qumis_fn) return self.compiler
def test_qasm_seq_echo(self): for q_name in ['q0', 'q1']: qasm_file = sqqs.echo(q_name, times=self.times) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "echo_{}.qumis".format(q_name)) compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=0) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start)
def test_equivalent_maps_custom_qubit_name(self): # generate the same qasm and compile using two qubit names that # refer to the same qubit_cfg in the hardware spec qumis_instrs = [[], []] for i, q_name in enumerate(['q0', 'ql']): qasm_file = sqqs.AllXY(q_name) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "allxy_{}.qumis".format(q_name)) compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=0) compiler.compile(qasm_fn, qumis_fn) qumis_instrs[i] = compiler.qumis_instructions self.assertEqual(qumis_instrs[0], qumis_instrs[1])
def test_qasm_seq_randomized_benchmarking(self): ncl = [2, 4, 6, 20] nr_seeds = 10 for q_name in ['q0', 'q1']: qasm_file = sqqs.randomized_benchmarking(q_name, ncl, nr_seeds) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "randomized_benchmarking_{}.qumis".format(q_name)) compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=0) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start)
def test_qasm_seq_butterfly(self): for q_name in ['q1', 'q1']: qasm_file = sqqs.butterfly(q_name, initialize=True) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "butterfly_{}.qumis".format(q_name)) compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) # The sequence should contain 6 RO instructions self.assertEqual( compiler.qumis_instructions.count('trigger 0000001, 3'), 6)
def test_get_timepoints(self): qasm_file = qwfs.chevron_block_seq('q0', 'q1', RO_target='q0', no_of_points=5) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) time_pts = get_timepoints_from_label(compiler.timing_grid, 'cz', start_label='qwg_trigger_1', end_label='ro') time_pts_ns = get_timepoints_from_label(compiler.timing_grid, 'cz', start_label='qwg_trigger_1', end_label='ro', convert_clk_to_ns=True) self.assertEqual(time_pts['start_tp'].absolute_time * 5, time_pts_ns['start_tp'].absolute_time) for tp, tp_ns in zip(time_pts['target_tps'], time_pts_ns['target_tps']): self.assertEqual(tp.absolute_time * 5, tp_ns.absolute_time) self.assertEqual(time_pts['end_tp'].absolute_time * 5, time_pts_ns['end_tp'].absolute_time) cz_pts = time_pts['target_tps'] self.assertEqual(len(cz_pts), 1) t_cz = cz_pts[0].absolute_time # Time of time points is in clocks # 500ns specified self.assertEqual(cz_pts[0].following_waiting_time, 100) t_ro = time_pts['end_tp'].absolute_time self.assertEqual(t_ro - t_cz, 100) t_trigg = time_pts['start_tp'].absolute_time self.assertEqual(t_cz - t_trigg, 7) time_pts = get_timepoints_from_label(target_label='cz', timing_grid=compiler.timing_grid, start_label=None, end_label=None) self.assertEqual(len(time_pts['target_tps']), 5)
def test_two_qubit_off_on(self): for RO_target in ['q0', 'q1', 'all']: qasm_file = mqqs.two_qubit_off_on('q0', 'q1', RO_target='all') qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "TwoQ_off_on.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) self.assertEqual( compiler.qumis_instructions.count('trigger 0000001, 3'), 4)
def test_compiler_example(self): qasm_fn = join(self.test_file_dir, 'dev_test.qasm') qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=6) compiler.compile(qasm_fn, qumis_fn) qumis = compiler.qumis_instructions m = open(compiler.qumis_fn).read() qumis_from_file = m.splitlines() self.assertEqual(qumis, qumis_from_file) self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') # Test that the final wait after the last instruction is not trimmed self.assertEqual(compiler.qumis_instructions[-2], 'wait 60') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) # finally test that it can be converted into valid instructions asm = Assembler(qumis_fn) asm.convert_to_instructions()
def test_converting_CBox_pulses_to_qumis(self): qasm_fn = join(self.test_file_dir, 'single_op.qasm') qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.config_fn, verbosity_level=6) compiler.compile(qasm_fn, qumis_fn) qumis = compiler.qumis_instructions x180_q0 = qumis[3] y180_q0 = qumis[5] x90_q0 = qumis[7] y90_q0 = qumis[9] mx90_q0 = qumis[11] my90_q0 = qumis[13] self.assertEqual(x180_q0, 'pulse 0000, 0000, 1001') self.assertEqual(y180_q0, 'pulse 0000, 0000, 1010') self.assertEqual(x90_q0, 'pulse 0000, 0000, 1011') self.assertEqual(y90_q0, 'pulse 0000, 0000, 1100') self.assertEqual(mx90_q0, 'pulse 0000, 0000, 1101') self.assertEqual(my90_q0, 'pulse 0000, 0000, 1110')
def test_qwg_chevron(self): qasm_file = qwfs.chevron_block_seq('q0', 'q1', RO_target='q0', no_of_points=5) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=6) compiler.compile(qasm_fn, qumis_fn) qumis = compiler.qumis_instructions m = open(compiler.qumis_fn).read() qumis_from_file = m.splitlines() self.assertEqual(qumis, qumis_from_file) self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) # finally test that it can be converted into valid instructions asm = Assembler(qumis_fn) asm.convert_to_instructions()
def test_time_tuples_since_event(self): nr_pulses = [1, 3, 5, 11] qasm_file = qwfs.SWAPN('q0', 'q1', RO_target='q0', nr_pulses=nr_pulses) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "output.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=2) compiler.compile(qasm_fn, qumis_fn) for i in range(3): time_tuples, end_time = get_timetuples_since_event( start_label='qwg_trigger_{}'.format(i), target_labels=['square', 'cz'], timing_grid=compiler.timing_grid, end_label='ro') self.assertEqual(len(time_tuples), nr_pulses[i]) for time_tuple in time_tuples: self.assertEqual(time_tuple[1], 'square') self.assertGreater(time_tuple[0], 0)
def test_chevron_block_seq(self): qasm_file = qwfs.chevron_block_seq('q0', 'q1', RO_target='q0', no_of_points=5) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "chevron_block.qumis") compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=6) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) self.assertEqual( compiler.qumis_instructions.count('trigger 0000001, 3'), 5) compiler.timing_event_list
def test_restless_RB_seq(self): ncl = [10] nr_seeds = 15 for q_name in ['q0', 'q1']: qasm_file = sqqs.randomized_benchmarking(q_name, ncl, nr_seeds, restless=True, cal_points=False) qasm_fn = qasm_file.name qumis_fn = join(self.test_file_dir, "randomized_benchmarking_{}.qumis".format(q_name)) compiler = qcx.QASM_QuMIS_Compiler(self.simple_config_fn, verbosity_level=0) compiler.compile(qasm_fn, qumis_fn) asm = Assembler(qumis_fn) asm.convert_to_instructions() self.assertEqual(compiler.qumis_instructions[2], 'Exp_Start: ') self.assertEqual(compiler.qumis_instructions[-1], self.jump_to_start) self.assertEqual( compiler.qumis_instructions.count('trigger 0000001, 3'), 15)
def measure_grover_1Q_phase( self, Z_amps, correction_qubit=None, spectator_qubit=None, QWG_codeword: int = 0, wait_during_flux='auto', # span: float=0.04, num: int=31, msmt_suffix: str = None, MC=None) -> bool: ''' Measure the single qubit phase error of the second CZ pulse in Grover's algorithm. This assumes that the first CZ is calibrated properly. Measured values are cos(phi). The sequence is mX90 -- CZ -- wait -- CZ2 -- X90 such that the minimum of the curve corresponds to zero phase error. Args: Z_amps (list of floats): Sweep points; amplitudes for the single qubit phase correction Z-pulse of the second CZ. correction_qubit (obj): Qubit object representing the qubit to which the phase correction is applied. spectator_qubit (obj): Qubit object representing the other qubit involved in the CZ. QWG_codeword (int): Codeword which is used for the composite flux pulse. wait_during_flux (float or 'auto'): Delay between the two pi-half pulses. If this is 'auto', the time is automatically picked based on the duration of a microwave and flux pulses (in the Grover sequence ther is one microwave pulse between the flux pulses). ''' if MC is None: MC = qc.station.components['MC'] if msmt_suffix is None: msmt_suffix = self.msmt_suffix CBox = self.central_controller.get_instr() if correction_qubit is None: correction_qubit = self.qubits()[0] if spectator_qubit is None: spectator_qubit = self.qubits()[1] f_lutman_spect = spectator_qubit.flux_LutMan.get_instr() f_lutman_corr = correction_qubit.flux_LutMan.get_instr() spectator_qubit.prepare_for_timedomain() spectator_qubit.prepare_for_fluxing() correction_qubit.prepare_for_timedomain() correction_qubit.prepare_for_fluxing(reset=False) cfg = deepcopy(correction_qubit.qasm_config()) mw_dur = cfg['operation dictionary']['y90']['duration'] # Waveform for correction qubit std_CZ = deepcopy(f_lutman_corr.standard_waveforms()['adiabatic_Z']) zero_samples = 4 * int( np.round(mw_dur * 1e-9 * f_lutman_corr.sampling_rate())) def wave_func(val): wf1 = std_CZ f_lutman_corr.Z_amp_grover(val) wf2 = deepcopy( f_lutman_corr.standard_waveforms()['adiabatic_Z_grover']) return np.concatenate([wf1, np.zeros(zero_samples), wf2]) # Waveform for spectator qubit spect_CZ = deepcopy(f_lutman_spect.standard_waveforms()['adiabatic_Z']) wf_spect = np.concatenate([spect_CZ, np.zeros(zero_samples), spect_CZ]) f_lutman_spect.load_custom_pulse_onto_AWG_lookuptable( waveform=wf_spect, pulse_name='square_0', codeword=QWG_codeword) # Set the delay between the pihalf pulses to be long enough to fit the # flux pulse max_len = len(wave_func(0.1)) if wait_during_flux == 'auto': # Round to the next integer multiple of qubit pulse modulation # period and add two periods as buffer T_pulsemod = np.abs(1 / correction_qubit.f_pulse_mod()) wait_between = (np.ceil(max_len / f_lutman_corr.sampling_rate() / T_pulsemod) + 2) * T_pulsemod print('Autogenerated wait between pi-halfs: {} ns'.format( np.round(wait_between * f_lutman_corr.sampling_rate()))) else: wait_between = wait_during_flux cfg['luts'][1]['square_0'] = QWG_codeword cfg["operation dictionary"]["square_0"] = { "parameters": 1, "duration": int(np.round(wait_between * f_lutman_corr.sampling_rate())), "type": "flux", "matrix": [] } # Compile sequence CBox.trigger_source('internal') qasm_file = sqqs.Ram_Z(qubit_name=correction_qubit.name, no_of_points=1, cal_points=False, rec_Y90=False) qasm_folder, qasm_fn = os.path.split(qasm_file.name) qumis_fn = os.path.join(qasm_folder, qasm_fn.split('.')[0] + '.qumis') compiler = qcx.QASM_QuMIS_Compiler(verbosity_level=0) compiler.compile(qasm_file.name, qumis_fn=qumis_fn, config=cfg) CBox.load_instructions(qumis_fn) d = self.get_integrated_average_detector() metadata_dict = {'Z_amps': Z_amps} MC.set_sweep_function( swf.QWG_lutman_custom_wave_chunks(LutMan=f_lutman_corr, wave_func=wave_func, sweep_points=Z_amps, chunk_size=1, codewords=[QWG_codeword], param_name='Z_amp', param_unit='V')) MC.set_sweep_points(Z_amps) MC.set_detector_function(d) MC.run('Grover_1Q_phase_fine{}'.format(msmt_suffix), exp_metadata=metadata_dict) ma.MeasurementAnalysis(label='Grover_1Q_phase_fine')
def measure_chevron(self, amps, lengths, fluxing_qubit=None, spectator_qubit=None, wait_during_flux='auto', excite_q1: bool = True, MC=None): ''' Measures chevron for the two qubits of the device. The qubit that is fluxed is q0, so the order of the qubit matters! Args: fluxing_qubit (Instr): Qubit object representing the qubit which is fluxed. spectator_qubit (Instr): Qubit object representing the qubit with which the fluxing qubit interacts. amps (array of floats): Flux pulse amplitude sweep points (in V) -> x-axis lengths (array of floats): Flux pulse length sweep points (in s) -> y-axis fluxing_qubit (str): name of the qubit that is fluxed/ spectator qubit (str): name of the qubit with which the fluxing qubit interacts. wait_during_flux (float or 'auto'): Delay during the flux pulse. If this is 'auto', the time is automatically picked based on the maximum of the sweep points. excite_q1 (bool): False: measure |01> - |10> chevron. True: measure |11> - |02> chevron. MC (Instr): Measurement control instrument to use for the experiment. ''' if MC is None: MC = qc.station.components['MC'] CBox = self.central_controller.get_instr() if fluxing_qubit is None: fluxing_qubit = self.qubits()[0] if spectator_qubit is None: spectator_qubit = self.qubits()[1] q0 = self.find_instrument(fluxing_qubit) q1 = self.find_instrument(spectator_qubit) self.prepare_for_timedomain() # only prepare q0 for fluxing, because this is the only qubit that # gets a flux pulse. q0.prepare_for_fluxing() # Use flux lutman from q0, since this is the qubit being fluxed. QWG_flux_lutman = q0.flux_LutMan.get_instr() QWG = QWG_flux_lutman.QWG.get_instr() # Set the wait time during the flux pulse to be long enough to fit the # longest flux pulse if wait_during_flux == 'auto': # Round to the next integer multiple of qubit pulse modulation # period and add two periods as buffer T_pulsemod = np.abs(1 / q0.f_pulse_mod()) wait_during_flux = (np.ceil(max(lengths) / T_pulsemod) + 2) \ * T_pulsemod cfg = deepcopy(self.qasm_config()) cfg['operation dictionary']['square']['duration'] = int( np.round(wait_during_flux * 1e9)) qasm_file = mqqs.chevron_seq(fluxing_qubit=q0.name, spectator_qubit=q1.name, excite_q1=excite_q1, RO_target='all') CBox.trigger_source('internal') qasm_folder, fn = os.path.split(qasm_file.name) base_fn = fn.split('.')[0] qumis_fn = os.path.join(qasm_folder, base_fn + '.qumis') compiler = qcx.QASM_QuMIS_Compiler(verbosity_level=1) compiler.compile(qasm_file.name, qumis_fn=qumis_fn, config=cfg) CBox.load_instructions(qumis_fn) CBox.start() # Set the wave dict unit to frac, because we take care of the proper # scaling in the sweep function oldWaveDictUnit = QWG_flux_lutman.wave_dict_unit() QWG_flux_lutman.wave_dict_unit('frac') s1 = swf.QWG_flux_amp(QWG=QWG, channel=QWG_flux_lutman.F_ch(), frac_amp=QWG_flux_lutman.F_amp()) s2 = swf.QWG_lutman_par(QWG_flux_lutman, QWG_flux_lutman.F_length) MC.set_sweep_function(s1) MC.set_sweep_function_2D(s2) MC.set_sweep_points(amps) MC.set_sweep_points_2D(lengths) d = self.get_integrated_average_detector() MC.set_detector_function(d) MC.run('Chevron_{}_{}'.format(q0.name, q1.name), mode='2D') # Restore the old wave dict unit. QWG_flux_lutman.wave_dict_unit(oldWaveDictUnit)