def purity_CZ_seq(q0, q1, RO_target='all'): """ Creates the |00> + |11> Bell state and does a partial tomography in order to determine the purity of both qubits. """ filename = join(base_qasm_path, 'purity_CZ_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) tomo_list = ['mX90', 'mY90', 'I'] for p_pulse in tomo_list: # Create a Bell state: |00> + |11> qasm_file.writelines('\ninit_all\n') qasm_file.writelines('mY90 {} | Y90 {} \n'.format(q0, q1)) qasm_file.writelines('CZ {} {} \n'.format(q0, q1)) qasm_file.writelines('mY90 {}\n'.format(q1)) # Perform pulses to measure the purity of both qubits qasm_file.writelines('{} {} | {} {}\n'.format(p_pulse, q0, p_pulse, q1)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def butterfly(qubit_name, initialize=False): """ Initialize adds an exta measurement before state preparation to allow initialization by post-selection The duration of the RO + depletion is specified in the definition of RO """ filename = join(base_qasm_path, 'butterfly_init_{}.qasm'.format(initialize)) qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) if initialize: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('\ninit_all\n') qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def purity_N_CZ_seq(q0: str, q1: str, N: int, RO_target: str = 'all'): """ Creates the |00> + |11> Bell state and does a partial tomography in order to determine the purity of both qubits. """ filename = join(base_qasm_path, 'purity_{}_CZ_seq.qasm'.format(N)) qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) tomo_list = ['mX90', 'mY90', 'I'] for i, p_pulse in enumerate(tomo_list): # Create a Bell state: |00> + |11> qasm_file.writelines('\ninit_all\n') qasm_file.writelines('qwg_trigger_{} {}\n'.format(0, q0)) qasm_file.writelines('mY90 {} | Y90 {} \n'.format(q0, q1)) for n in range(N): qasm_file.writelines('dummy_CZ {} {} \n'.format(q0, q1)) qasm_file.writelines('mY90 {}\n'.format(q1)) # Perform pulses to measure the purity of both qubits qasm_file.writelines('{} {} | {} {}\n'.format(p_pulse, q0, p_pulse, q1)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def AllXY(qubit_name, double_points=False): pulse_combinations = [['I', 'I'], ['X180', 'X180'], ['Y180', 'Y180'], ['X180', 'Y180'], ['Y180', 'X180'], ['X90', 'I'], ['Y90', 'I'], ['X90', 'Y90'], ['Y90', 'X90'], ['X90', 'Y180'], ['Y90', 'X180'], ['X180', 'Y90'], ['Y180', 'X90'], ['X90', 'X180'], ['X180', 'X90'], ['Y90', 'Y180'], ['Y180', 'Y90'], ['X180', 'I'], ['Y180', 'I'], ['X90', 'X90'], ['Y90', 'Y90']] if double_points: pulse_combinations = [val for val in pulse_combinations for _ in (0, 1)] filename = join(base_qasm_path, 'AllXY.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for pulse_comb in pulse_combinations: qasm_file.writelines('\ninit_all\n') if pulse_comb[0] != 'I': qasm_file.writelines('{} {}\n'.format(pulse_comb[0], qubit_name)) if pulse_comb[1] != 'I': qasm_file.writelines('{} {}\n'.format(pulse_comb[1], qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def CZ_restless_state_cycling(q0: str, q1: str, N: int=1): """ Implements a circuit that performs a permutation over all computational states. Expected operation: U (|00>) -> |01> U (|01>) -> |11> U (|10>) -> |00> U (|11>) -> |10> Args: q0 (str): name of qubit q0 q1 (str): name of qubit q1 N (int): number of times to apply U """ filename = join(base_qasm_path, 'CZ_state_cycling_light.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) U = '' U += 'Y90 {} | mY90 {}\n'.format(q0, q1) U += 'CZ {} {}\n'.format(q0, q1) U += 'Y90 {} | Y90 {}\n'.format(q0, q1) U += 'CZ {} {}\n'.format(q0, q1) U += 'Y90 {} | Y90 {}\n'.format(q0, q1) for n in range(N): qasm_file.writelines(U) qasm_file.writelines('RO {}\n'.format(q0))
def test_qasm_function_with_function_arg(self): ext_op_dict = deepcopy(self.operation_dict) def Rx_codeword(amp, min_amp=-.5, max_amp=0.5): """ maps an amp to a codeword, defining a function like this is NOT the responsibility of the qasm compiler """ amp = float(amp) codeword = int((amp-min_amp)/(max_amp - min_amp) * 127) return 'Trigger {:07b}, 2 , \n'.format(codeword) ext_op_dict['Rx'] = { self.qubit_name: {'instruction': Rx_codeword, 'duration': 2}} filename = join(self.base_qasm_path, 'argument.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # test wait argument qasm_file.writelines('I {} 12\n'.format( self.qubit_name)) qasm_file.writelines('I {} 4\n'.format( self.qubit_name)) qasm_file.close() qta.qasm_to_asm(qasm_file.name, ext_op_dict)
def test_qasm_function_with_function_arg(self): ext_op_dict = deepcopy(self.operation_dict) def Rx_codeword(amp, min_amp=-.5, max_amp=0.5): """ maps an amp to a codeword, defining a function like this is NOT the responsibility of the qasm compiler """ amp = float(amp) codeword = int((amp - min_amp) / (max_amp - min_amp) * 127) return 'Trigger {:07b}, 2 \n'.format(codeword) ext_op_dict['Rx'] = { self.qubit_name: { 'instruction': Rx_codeword, 'duration': 2 } } filename = join(self.base_qasm_path, 'argument.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # test wait argument qasm_file.writelines('I {} 12\n'.format(self.qubit_name)) qasm_file.writelines('I {} 4\n'.format(self.qubit_name)) qasm_file.close() qta.qasm_to_asm(qasm_file.name, ext_op_dict)
def extract_required_operations(qasm_filepath): """ Args: qasm_filepath: (str) location of the qasm file to read returns: list containing of all the used operations with args """ filename = splitext(basename(qasm_filepath))[0] asm_filepath = join(base_asm_path, filename+'.asm') asm_file = mopen(asm_filepath, mode='w') asm_file.writelines(preamble) qubits = [] # the qubits that were defined operations = [] with open(qasm_filepath) as qasm_file: for line in qasm_file: # Make lines interpretable line = line.split('#', 1)[0] # remove comments line = line.strip(' \t\n\r') # remove whitespace if (len(line) == 0): # skip empty line and comment continue elts = line.split() # special command: a line that defines a qubit if elts[0] == 'qubit': qubits.append(elts[1]) elif line not in operations: operations.append(line) return operations
def extract_required_operations(qasm_filepath): """ Args: qasm_filepath: (str) location of the qasm file to read returns: list containing of all the used operations with args """ filename = splitext(basename(qasm_filepath))[0] asm_filepath = join(base_asm_path, filename + '.asm') asm_file = mopen(asm_filepath, mode='w') asm_file.writelines(preamble) qubits = [] # the qubits that were defined operations = [] with open(qasm_filepath) as qasm_file: for line in qasm_file: # Make lines interpretable line = line.split('#', 1)[0] # remove comments line = line.strip(' \t\n\r') # remove whitespace if (len(line) == 0): # skip empty line and comment continue elts = line.split() # special command: a line that defines a qubit if elts[0] == 'qubit': qubits.append(elts[1]) elif line not in operations: operations.append(line) return operations
def test_empty_qasm_file(self): filename = join(self.base_qasm_path, 'empty.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) qasm_file.close() asm_file = qta.qasm_to_asm(qasm_file.name, self.operation_dict) asm = Assembler.Assembler(asm_file.name) instructions = asm.convert_to_instructions()
def test_invalid_command(self): filename = join(self.base_qasm_path, 'invalid_command.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) qasm_file.writelines('Xbla {} # invalid cmd\n'.format( self.qubit_name)) qasm_file.close() with self.assertRaises(ValueError): qta.qasm_to_asm(qasm_file.name, self.operation_dict)
def randomized_benchmarking(qubit_name, nr_cliffords, nr_seeds, net_clifford=0, restless=False, label='randomized_benchmarking', cal_points=True, double_curves=True): ''' Input pars: nr_cliffords: list nr_cliffords for which to generate RB seqs nr_seeds: int nr_seeds for which to generate RB seqs net_clifford: int index of net clifford the sequence should perform 0 corresponds to Identity and 3 corresponds to X180 restless: bool, does not initialize if restless is True label: some string that can be used as a label. cal_points: bool whether to replace the last two elements with calibration points, set to False if you want to measure a single element (for e.g. optimization) double_curves: Alternates between net clifford 0 and 3 returns: qasm_file generates a qasm file for single qubit Clifford based randomized benchmarking. ''' net_cliffords = [0, 3] # Exists purely for the double curves mode filename = join(base_qasm_path, label+'.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) i = 0 for seed in range(nr_seeds): for j, n_cl in enumerate(nr_cliffords): if not restless: qasm_file.writelines('init_all \n') if cal_points and (j == (len(nr_cliffords)-4) or j == (len(nr_cliffords)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (j == (len(nr_cliffords)-2) or j == (len(nr_cliffords)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: if double_curves: net_clifford = net_cliffords[i % 2] i += 1 cl_seq = rb.randomized_benchmarking_sequence( n_cl, desired_net_cl=net_clifford) pulse_keys = rb.decompose_clifford_seq(cl_seq) for pulse in pulse_keys: if pulse != 'I': qasm_file.writelines('{} {}\n'.format( pulse, qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def two_qubit_tomo_cardinal(cardinal, q0, q1, RO_target='all'): ''' Cardinal tomography for two qubits. Args: cardinal (int) : index of prep gate q0, q1 (str) : target qubits for the sequence RO_target (str) : target for the RO, can be a qubit name or 'all' ''' tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] tomo_list_q0 = [] tomo_list_q1 = [] for tp in tomo_pulses: tomo_list_q0 += [tp + q0 + '\n'] tomo_list_q1 += [tp + q1 + '\n'] prep_index_q0 = int(cardinal % len(tomo_list_q0)) prep_index_q1 = int(((cardinal - prep_index_q0) / len(tomo_list_q0) % len(tomo_list_q1))) prep_pulse_q0 = tomo_list_q0[prep_index_q0] prep_pulse_q1 = tomo_list_q1[prep_index_q1] filename = join(base_qasm_path, 'two_qubit_tomo_cardinal.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) # Tomography pulses for p_q1 in tomo_list_q1: for p_q0 in tomo_list_q0: qasm_file.writelines('\ninit_all\n') qasm_file.writelines(prep_pulse_q0) qasm_file.writelines(prep_pulse_q1) qasm_file.writelines(p_q0) qasm_file.writelines(p_q1) qasm_file.writelines('RO ' + RO_target + ' \n') cal_pulses = [] # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. for seq in cal_points_2Q: cal_pulses += [[seq[0].format(q0) + seq[1].format(q1) + 'RO {} \n'.format(RO_target)]] for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def single_elt_on(qubit_name): filename = join(base_qasm_path, 'single_elt_on.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) # On qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {} # On \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def Ramsey(qubit_name, times, clock_cycle=5e-9, artificial_detuning=4, cal_points=True): ''' Ramsey sequence for a single qubit. Input pars: times: array of times between (start of) pulses (s) pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters artificial_detuning: int, float or None; if int: number of wiggles if float: artificial_detuning in (Hz) if None: adds no artificial detuning implemented using phase of the second pi/2 pulse (R90_phi), if None it will use X90 as the recovery pulse cal_points: whether to use calibration points or not ''' # if int interpret artificial detuning as desired nr of wiggles if isinstance(artificial_detuning, int): phases = (360*np.arange(len(times))/(len(times)-4*cal_points) * artificial_detuning % 360) # if float interpret it as artificial detuning in Hz elif isinstance(artificial_detuning, float): phases = (artificial_detuning*times % 1)*360 elif artificial_detuning is None: phases = np.zeros(len(times)) clocks = np.round(times/clock_cycle) filename = join(base_qasm_path, 'Ramsey.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for i, cl in enumerate(clocks): qasm_file.writelines('\ninit_all\n') if cal_points and (i == (len(clocks)-4) or i == (len(clocks)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (i == (len(clocks)-2) or i == (len(clocks)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: qasm_file.writelines('X90 {} \n'.format( qubit_name)) qasm_file.writelines('I {} {:d} \n'.format(qubit_name, int(cl))) if artificial_detuning is not None: qasm_file.writelines('R90_phi {} {}\n'.format( qubit_name, phases[i])) else: qasm_file.writelines('X90 {} \n'.format( qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def test_qasm_function_with_string_format_arg(self): ext_op_dict = deepcopy(self.operation_dict) filename = join(self.base_qasm_path, 'argument.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # test wait argument qasm_file.writelines('I {} 12\n'.format(self.qubit_name)) qasm_file.writelines('I {} 4\n'.format(self.qubit_name)) qasm_file.close() qta.qasm_to_asm(qasm_file.name, ext_op_dict)
def Rabi(qubit_name, amps, n=1): filename = join(base_qasm_path, 'Rabi_{}.qasm'.format(n)) qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for amp in amps: qasm_file.writelines('\ninit_all\n') for i in range(n): qasm_file.writelines('Rx {} {} \n'.format(qubit_name, amp)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def chevron_block_seq(q0_name, q1_name, no_of_points, excite_q1=False, wait_after_trigger=40e-9, wait_during_flux=400e-9, clock_cycle=1e-9, RO_target='all', mw_pulse_duration=40e-9, cal_points=True): ''' Sequence for measuring a block of a chevron, i.e. using different codewords for different pulse lengths. Args: q0, q1 (str): names of the addressed qubits. q0 is the pulse that experiences the flux pulse. RO_target (str): can be q0, q1, or 'all' excite_q1 (bool): choose whether to excite q1, thus choosing between the |01> <-> |10> and the |11> <-> |20> swap. wait_after_trigger (float): delay time in seconds after sending the trigger for the flux pulse clock_cycle (float): period of the internal AWG clock wait_time (int): wait time between triggering QWG and RO cal_points (bool): whether to use calibration points or not ''' filename = join(base_qasm_path, 'chevron_block_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0_name, q1_name)) for i in range(no_of_points): qasm_file.writelines('\ninit_all\n') qasm_file.writelines('QWG trigger {}\n'.format(i)) if excite_q1: wait_after_trigger -= mw_pulse_duration qasm_file.writelines( 'I {}\n'.format(int(wait_after_trigger//clock_cycle))) qasm_file.writelines('X180 {}\n'.format(q0_name)) if excite_q1: qasm_file.writelines('X180 {}\n'.format(q1_name)) qasm_file.writelines( 'I {}\n'.format(int(wait_during_flux//clock_cycle))) if excite_q1: # q0 is rotated to ground-state to have better contrast # (|0> and |2> instead of |1> and |2>) qasm_file.writelines('X180 {}\n'.format(q0_name)) qasm_file.writelines('RO {} \n'.format(RO_target)) if cal_points: # Add calibration pulses cal_pulses = [] for seq in cal_points_2Q: cal_pulses += [[seq[0], seq[1], 'RO ' + RO_target + '\n']] qasm_file.close() return qasm_file
def test_too_many_args_command(self): filename = join(self.base_qasm_path, 'too_many_args.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # leaving out the \n prevents the line from breaking qasm_file.writelines('X180 {}'.format(self.qubit_name)) qasm_file.writelines('X180 {}'.format(self.qubit_name)) qasm_file.writelines('Y180 {}'.format(self.qubit_name)) qasm_file.close() with self.assertRaises(ValueError): qta.qasm_to_asm(qasm_file.name, self.operation_dict)
def test_qasm_function_with_string_format_arg(self): ext_op_dict = deepcopy(self.operation_dict) filename = join(self.base_qasm_path, 'argument.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # test wait argument qasm_file.writelines('I {} 12\n'.format( self.qubit_name)) qasm_file.writelines('I {} 4\n'.format( self.qubit_name)) qasm_file.close() qta.qasm_to_asm(qasm_file.name, ext_op_dict)
def SWAPN(q0_name, q1_name, nr_pulses: list, excite_q1=False, RO_target='all', cal_points=True): ''' Args: q0, q1 (str): names of the addressed qubits. q0 is the pulse that experiences the flux pulse. RO_target (str): can be q0, q1, or 'all' excite_q1 (bool): choose whether to excite q1, thus choosing between the |01> <-> |10> and the |11> <-> |20> swap. cal_points (bool): whether to use calibration points or not ''' filename = join(base_qasm_path, 'chevron_block_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0_name, q1_name)) for i, N in enumerate(nr_pulses): qasm_file.writelines('\ninit_all\n') qasm_file.writelines('QWG_trigger_{} {}\n'.format(i, q0_name)) qasm_file.writelines('X180 {}\n'.format(q0_name)) if excite_q1: qasm_file.writelines('X180 {}\n'.format(q1_name)) for n in range(N): qasm_file.writelines('square {} \n'.format(q0_name)) if excite_q1: # q0 is rotated to ground-state to have better contrast # (|0> and |2> instead of |1> and |2>) qasm_file.writelines('X180 {}\n'.format(q0_name)) qasm_file.writelines('RO {} \n'.format(RO_target)) if cal_points: # Add calibration pulses cal_pulses = [] for seq in cal_points_2Q: cal_pulses += [[ seq[0].format(q0_name) + seq[1].format(q1_name) + 'RO {} \n'.format(RO_target) ]] for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def CZ_calibration_seq(q0, q1, RO_target='all', CZ_disabled=False, cases=('no_excitation', 'excitation'), wait_after_trigger=40e-9, wait_during_flux=280e-9, clock_cycle=1e-9, mw_pulse_duration=40e-9): ''' Sequence used to calibrate flux pulses for CZ gates. Timing of the sequence: q0: -- X90 C-Phase Rphi90 -- RO q1: (X180) -- -- -- (X180) RO Args: q0, q1 (str): names of the addressed qubits RO_target (str): can be q0, q1, or 'all' CZ_disabled (bool): disable CZ gate excitations (bool/str): can be True, False, or 'both_cases' clock_cycle (float): period of the internal AWG clock wait_time (int): wait time in seconds after triggering the flux ''' filename = join(base_qasm_path, 'CZ_calibration_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) for case in cases: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('QWG trigger\n') waitTime = wait_after_trigger if case == 'excitation': # Decrease wait time because there is an additional pulse waitTime -= mw_pulse_duration qasm_file.writelines( 'I {}\n'.format(int(waitTime//clock_cycle))) if case == 'excitation': qasm_file.writelines('X180 {}\n'.format(q1)) qasm_file.writelines('X90 {}\n'.format(q0)) qasm_file.writelines( 'I {}\n'.format(int(wait_during_flux//clock_cycle))) qasm_file.writelines('Rphi90 {}\n'.format(q0)) if case == 'excitation': qasm_file.writelines('X180 {}\n'.format(q1)) qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def test_too_many_args_command(self): filename = join(self.base_qasm_path, 'too_many_args.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(self.qubit_name)) # leaving out the \n prevents the line from breaking qasm_file.writelines('X180 {}'.format( self.qubit_name)) qasm_file.writelines('X180 {}'.format( self.qubit_name)) qasm_file.writelines('Y180 {}'.format( self.qubit_name)) qasm_file.close() with self.assertRaises(ValueError): qta.qasm_to_asm(qasm_file.name, self.operation_dict)
def two_qubit_off_on(q0, q1, RO_target='all'): ''' off_on sequence on two qubits. Args: q0, q1 (str) : target qubits for the sequence RO_target (str) : target for the RO, can be a qubit name or 'all' ''' filename = join(base_qasm_path, 'two_qubit_off_on.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) # off - off qasm_file.writelines('\ninit_all\n') if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) # on - off qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {}\n'.format(q0)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) # off - on qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {}\n'.format(q1)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) # on - on qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {}\n'.format(q0)) qasm_file.writelines('X180 {}\n'.format(q1)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def CZ_calibration_seq(q0, q1, RO_target='all', vary_single_q_phase=True, cases=('no_excitation', 'excitation')): ''' Sequence used to calibrate flux pulses for CZ gates. Timing of the sequence: q0: X90 C-Phase Rphi90 RO q1: (X180) -- (X180) RO Args: q0, q1 (str): names of the addressed qubits RO_target (str): can be q0, q1, or 'all' excitations (bool/str): can be True, False, or 'both_cases' ''' filename = join(base_qasm_path, 'CZ_calibration_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) for case in cases: qasm_file.writelines('\ninit_all\n') if case == 'excitation': qasm_file.writelines('X180 {} | '.format(q1)) qasm_file.writelines('X90 {}\n'.format(q0)) # temporary workaround to deal with limitation in the QASM config # qasm_file.writelines('CZ {} \n'.format(q0)) qasm_file.writelines('CZ {} {}\n'.format(q0, q1)) if case == 'excitation': qasm_file.writelines('X180 {} | '.format(q1)) if vary_single_q_phase: qasm_file.writelines('Rphi90 {}\n'.format(q0)) else: qasm_file.writelines('mX90 {}\n'.format(q0)) if 'RO_target' == 'all': qasm_file.writelines('RO {} | RO {} \n'.format(q0, q1)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def MotzoiXY(qubit_name, motzois, cal_points=True): ''' Sequence used for calibrating the motzoi parameter. Consists of Xy and Yx Beware that the elements alternate, if you want to measure both Xy and Yx at each motzoi you need repeating motzoi parameters. This was chosen to be more easily compatible with standard detector functions and sweep pts Input pars: motzois: array of motzoi parameters pulse_pars: dict containing the pulse parameters RO_pars: dict containing the RO parameters cal_points: if True, replaces the last 2*4 segments with calibration points ''' filename = join(base_qasm_path, 'Motzoi_XY.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for i, motzoi in enumerate(motzois): qasm_file.writelines('\ninit_all\n') if cal_points and (i == (len(motzois)-4) or i == (len(motzois)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (i == (len(motzois)-2) or i == (len(motzois)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) if i % 2: qasm_file.writelines( 'X180_Motz {} {} \n'.format(qubit_name, motzoi)) qasm_file.writelines( 'Y90_Motz {} {} \n'.format(qubit_name, motzoi)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: qasm_file.writelines( 'Y180_Motz {} {} \n'.format(qubit_name, motzoi)) qasm_file.writelines( 'X90_Motz {} {} \n'.format(qubit_name, motzoi)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def two_elt_MotzoiXY(qubit_name): ''' Sequence used for calibrating the motzoi parameter. Consists of Xy and Yx needs to reload the points for every data point. ''' filename = join(base_qasm_path, 'Motzoi_XY.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('Y90 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.writelines('\ninit_all\n') qasm_file.writelines('Y180 {} \n'.format(qubit_name)) qasm_file.writelines('X90 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def ramZ_flux_latency(q0_name, wait_after_flux=20): """ Sequence designed to calibrate the delay between the QWG_trigger and the start of the flux pulse Consists of a single point. Intended to change the latency parameter in the configuration that is used in compilation. """ filename = join(base_qasm_path, 'RamZ_latency_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(q0_name)) # simultaneous MW and flux pulse qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X90 {} \n'.format(q0_name)) qasm_file.writelines('square {}\n'.format(q0_name)) qasm_file.writelines('I {}\n'.format(wait_after_flux)) qasm_file.writelines('X90 {}\n'.format(q0_name)) qasm_file.writelines('RO {} \n'.format(q0_name)) qasm_file.close() return qasm_file
def chevron_seq(fluxing_qubit: str, spectator_qubit: str, excite_q1: bool=False, RO_target='all'): ''' Single chevron sequence that does a swap on |01> <-> |10> or |11> <-> |20>. Args: fluxing_qubit (str): name of the qubit that is fluxed/ spectator qubit (str): name of the qubit with which the fluxing qubit interacts. RO_target (str): can be q0, q1, or 'all' excite_q1 (bool): choose whether to excite q1, thus choosing between the |01> <-> |10> and the |11> <-> |20> swap. ''' filename = join(base_qasm_path, 'chevron_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(fluxing_qubit, spectator_qubit)) qasm_file.writelines('\ninit_all\n') if excite_q1: qasm_file.writelines('X180 {} | X180 {}\n'.format(fluxing_qubit, spectator_qubit)) else: qasm_file.writelines('X180 {}\n'.format(fluxing_qubit)) qasm_file.writelines('square {}\n'.format(fluxing_qubit)) if excite_q1: # fluxing_qubit is rotated to ground-state to have better contrast # (|0> and |2> instead of |1> and |2>) qasm_file.writelines('X180 {}\n'.format(fluxing_qubit)) if RO_target == 'all': qasm_file.writelines('RO {} | RO {}\n'.format(fluxing_qubit, spectator_qubit)) else: qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def flipping_seq(qubit_name, number_of_flips, clock_cycle=5e-9, equator=False, cal_points=True): filename = join(base_qasm_path, 'Flipping.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for i, n in enumerate(number_of_flips): qasm_file.writelines('\ninit_all\n') if cal_points and (i == (len(number_of_flips)-4) or i == (len(number_of_flips)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (i == (len(number_of_flips)-2) or i == (len(number_of_flips)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: if equator: qasm_file.writelines('X90 {} \n'.format(qubit_name)) for j in range(n): qasm_file.writelines('X180 {} \n'.format( qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def T1(qubit_name, times, clock_cycle=5e-9, cal_points=True): # clocks = np.round(times/clock_cycle) filename = join(base_qasm_path, 'T1.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(qubit_name)) for i, cl in enumerate(clocks): qasm_file.writelines('\ninit_all\n') if cal_points and (i == (len(clocks)-4) or i == (len(clocks)-3)): qasm_file.writelines('RO {} \n'.format(qubit_name)) elif cal_points and (i == (len(clocks)-2) or i == (len(clocks)-1)): qasm_file.writelines('X180 {} \n'.format(qubit_name)) qasm_file.writelines('RO {} \n'.format(qubit_name)) else: qasm_file.writelines('X180 {} # exciting pi pulse\n'.format( qubit_name)) qasm_file.writelines('I {} {:d} \n'.format(qubit_name, int(cl))) qasm_file.writelines('RO {} \n'.format(qubit_name)) qasm_file.close() return qasm_file
def grover_tomo_seq(q0_name, q1_name, omega, RO_target='all', precompiled_flux=True): ''' Writes the QASM sequence to take a state tomography of the output state of Grover's algorithm on two qubits. Sequence: q0: G0 - - mY90 - - mY90 - RO CZ_ij CZ q1: G1 - - mY90 - - mY90 - RO where (ij) is the binary representation of omega. G0 and G1 are Y90 or Y90, depending on the (ij). Args: q0_name, q1_name (string): Names of the qubits to which the sequence is applied. omega (int): Deterines which (ij) for the CZ_ij. RO_target (string): Readout target. Can be a qubit name or 'all'. precompiled_flux (bool): Determies if the full waveform for the flux pulses is precompiled, thus only needing one trigger at the start, or if every flux pulse should be triggered individually. Returns: qasm_file: a reference to the new QASM file object. ''' if not precompiled_flux: raise NotImplementedError('Currently only precompiled flux pulses ' 'are supported.') tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] tomo_list_q0 = [] tomo_list_q1 = [] for tp in tomo_pulses: tomo_list_q0 += [tp + q0_name] tomo_list_q1 += [tp + q1_name] if omega == 0: G0 = 'Y90' G1 = 'Y90' elif omega == 1: G0 = 'Y90' G1 = 'mY90' elif omega == 2: G0 = 'mY90' G1 = 'Y90' elif omega == 3: G0 = 'mY90' G1 = 'mY90' else: raise ValueError('omega must be in [0, 3]') if RO_target == 'all': RO_line = 'RO {} | RO {}\n'.format(q0_name, q1_name) else: RO_line = 'RO {} \n'.format(RO_target) filename = join(base_qasm_path, 'Grover_tomo_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(q0_name)) qasm_file.writelines('qubit {} \n'.format(q1_name)) for p_q1 in tomo_list_q1: for p_q0 in tomo_list_q0: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('{} {} | {} {}\n'.format( G0, q0_name, G1, q1_name)) qasm_file.writelines('grover_CZ {} {}\n'.format(q0_name, q1_name)) qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, q1_name)) qasm_file.writelines('cz {} {}\n'.format(q0_name, q1_name)) qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, q1_name)) qasm_file.writelines('{} | {}\n'.format(p_q1, p_q0)) qasm_file.writelines(RO_line) # Add calibration pulses cal_pulses = [] # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. for seq in cal_points_2Q: cal_pulses += [[ seq[0].format(q0_name), seq[1].format(q1_name), RO_line ]] * 7 for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def two_qubit_AllXY(q0, q1, RO_target='all', sequence_type='sequential', replace_q1_pulses_X180=False, double_points=False): """ AllXY sequence on two qubits. Has the option of replacing pulses on q1 with pi pulses Args: q0, q1 (str) : target qubits for the sequence RO_target (str) : target for the RO, can be a qubit name or 'all' sequence_type (str) : sequential | interleaved | simultaneous | sandwiched q0|q0|q1|q1 q0|q1|q0|q1 q01|q01 q1|q0|q0|q1 N.B.! simultaneous is currently not possible! describes the order of the AllXY pulses replace_q1_pulses_X180 (bool) : if True replaces all pulses on q1 with X180 pulses. double_points (bool) : if True measures each point in the AllXY twice """ pulse_combinations = [['I', 'I'], ['X180', 'X180'], ['Y180', 'Y180'], ['X180', 'Y180'], ['Y180', 'X180'], ['X90', 'I'], ['Y90', 'I'], ['X90', 'Y90'], ['Y90', 'X90'], ['X90', 'Y180'], ['Y90', 'X180'], ['X180', 'Y90'], ['Y180', 'X90'], ['X90', 'X180'], ['X180', 'X90'], ['Y90', 'Y180'], ['Y180', 'Y90'], ['X180', 'I'], ['Y180', 'I'], ['X90', 'X90'], ['Y90', 'Y90']] pulse_combinations_tiled = pulse_combinations + pulse_combinations if double_points: pulse_combinations = [val for val in pulse_combinations for _ in (0, 1)] if replace_q1_pulses_X180: pulse_combinations_q1 = ['X180' for val in pulse_combinations] pulse_combinations_q0 = pulse_combinations pulse_combinations_q1 = pulse_combinations_tiled filename = join(base_qasm_path, 'two_qubit_AllXY.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) for pulse_comb_q0, pulse_comb_q1 in zip(pulse_combinations_q0, pulse_combinations_q1): qasm_file.writelines('\ninit_all\n') if sequence_type == 'interleaved': qasm_file.writelines('{} {}\n'.format(pulse_comb_q0[0], q0) + '{} {}\n'.format(pulse_comb_q1[0], q1) + '{} {}\n'.format(pulse_comb_q0[1], q0) + '{} {}\n'.format(pulse_comb_q1[1], q1)) elif sequence_type == 'sandwiched': qasm_file.writelines('{} {}\n'.format(pulse_comb_q1[0], q1) + '{} {}\n'.format(pulse_comb_q0[0], q0) + '{} {}\n'.format(pulse_comb_q0[1], q0) + '{} {}\n'.format(pulse_comb_q1[1], q1)) elif sequence_type == 'sequential': qasm_file.writelines('{} {}\n'.format(pulse_comb_q0[0], q0) + '{} {}\n'.format(pulse_comb_q0[1], q0) + '{} {}\n'.format(pulse_comb_q1[0], q1) + '{} {}\n'.format(pulse_comb_q1[1], q1)) elif sequence_type == 'simultaneous': qasm_file.writelines('{} {} |'.format(pulse_comb_q0[0], q0) + '{} {}\n'.format(pulse_comb_q1[0], q1) + '{} {} |'.format(pulse_comb_q0[1], q0) + '{} {}\n'.format(pulse_comb_q1[1], q1)) else: raise ValueError("sequence_type {} ".format(sequence_type) + "['interleaved', 'simultaneous', " + "'sequential', 'sandwiched']") qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def CZ_state_cycling_light(q0: str, q1: str, N: int=1): """ Implements a circuit that performs a permutation over all computational states. This light version performs this experiment for all 4 possible input states. Expected operation: U (|00>) -> |01> U (|01>) -> |11> U (|10>) -> |00> U (|11>) -> |10> Args: q0 (str): name of qubit q0 q1 (str): name of qubit q1 N (int): number of times to apply U """ filename = join(base_qasm_path, 'CZ_state_cycling_light.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) U = '' U += 'Y90 {} | mY90 {}\n'.format(q0, q1) U += 'CZ {} {}\n'.format(q0, q1) U += 'Y90 {} | Y90 {}\n'.format(q0, q1) U += 'CZ {} {}\n'.format(q0, q1) U += 'Y90 {} | Y90 {}\n'.format(q0, q1) # Input |00> qasm_file.writelines('init_all \n') qasm_file.writelines('qwg_trigger_0 {}\n'.format(q0)) for n in range(N): qasm_file.writelines(U) qasm_file.writelines('RO {}\n'.format(q0)) # Input |01> qasm_file.writelines('init_all \n') qasm_file.writelines('qwg_trigger_0 {}\n'.format(q0)) qasm_file.writelines('X180 {}\n'.format(q0)) for n in range(N): qasm_file.writelines(U) qasm_file.writelines('RO {}\n'.format(q0)) # Input |10> qasm_file.writelines('init_all \n') qasm_file.writelines('qwg_trigger_0 {}\n'.format(q0)) qasm_file.writelines('X180 {}\n'.format(q1)) for n in range(N): qasm_file.writelines(U) qasm_file.writelines('RO {}\n'.format(q0)) # Input |11> qasm_file.writelines('init_all \n') qasm_file.writelines('qwg_trigger_0 {}\n'.format(q0)) qasm_file.writelines('X180 {} | X180 {}\n'.format(q0, q1)) for n in range(N): qasm_file.writelines(U) qasm_file.writelines('RO {}\n'.format(q0)) qasm_file.close() return qasm_file
def two_qubit_tomo_bell(bell_state, q0, q1, wait_after_trigger=10e-9, wait_during_flux=260e-9, clock_cycle=1e-9, single_qubit_compiled_phase=False, RO_target='all'): ''' Two qubit bell state tomography. Args: bell_state (int): index of prepared bell state q0, q1 (str): names of the target qubits wait_after_trigger (float): delay time in seconds after sending the trigger for the flux pulse clock_cycle (float): period of the internal AWG clock wait_during_flux (int): wait time during the flux pulse single_qubit_compiled_phase (bool): wether to do single qubit phase correction in the recovery pulse RO_target (str): can be q0, q1, or 'all' ''' tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] tomo_list_q0 = [] tomo_list_q1 = [] for tp in tomo_pulses: tomo_list_q0 += [tp + q0 + '\n'] tomo_list_q1 += [tp + q1 + '\n'] tomo_list_q0[0] = 'I 20\n' tomo_list_q1[0] = 'I 20\n' # Choose a bell state and set the corresponding preparation pulses if bell_state % 10 == 0: # |Phi_m>=|00>-|11> prep_pulse_q0 = 'Y90 {}\n'.format(q0) prep_pulse_q1 = 'Y90 {}\n'.format(q1) elif bell_state % 10 == 1: # |Phi_p>=|00>+|11> prep_pulse_q0 = 'mY90 {}\n'.format(q0) prep_pulse_q1 = 'Y90 {}\n'.format(q1) elif bell_state % 10 == 2: # |Psi_m>=|01>-|10> prep_pulse_q0 = 'Y90 {}\n'.format(q0) prep_pulse_q1 = 'mY90 {}\n'.format(q1) elif bell_state % 10 == 3: # |Psi_p>=|01>+|10> prep_pulse_q0 = 'mY90 {}\n'.format(q0) prep_pulse_q1 = 'mY90 {}\n'.format(q1) else: raise ValueError('Bell state {} is not defined.'.format(bell_state)) # Recovery pulse is the same for all Bell states if single_qubit_compiled_phase == False: after_pulse = 'mY90 {}\n'.format(q1) else: after_pulse = 'recmY90 {}\n'.format(q1) # Disable preparation pulse on one or the other qubit for debugging if bell_state//10 == 1: prep_pulse_q1 = 'I 20' elif bell_state//10 == 2: prep_pulse_q0 = 'I 20' # Define compensation pulses # FIXME: needs to be added print('Warning: not using compensation pulses.') # Write tomo sequence filename = join(base_qasm_path, 'two_qubit_tomo_bell.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) for p_q1 in tomo_list_q1: for p_q0 in tomo_list_q0: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('QWG trigger\n') qasm_file.writelines( 'I {}\n'.format(int(wait_after_trigger//clock_cycle))) qasm_file.writelines(prep_pulse_q0) qasm_file.writelines(prep_pulse_q1) qasm_file.writelines( 'I {}\n'.format(int(wait_during_flux//clock_cycle))) qasm_file.writelines(after_pulse) qasm_file.writelines(p_q1) qasm_file.writelines(p_q0) qasm_file.writelines('RO ' + RO_target + ' \n') # Add calibration pulses cal_pulses = [] # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. for seq in cal_points_2Q: cal_pulses += [[seq[0].format(q0), seq[1].format(q1), 'RO ' + RO_target + '\n']] * 7 for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def grover_test_tomo_seq(q0_name, q1_name, omega, RO_target='all', precompiled_flux=True): ''' Test sequence to debug Grover's algorithm. ''' if not precompiled_flux: raise NotImplementedError('Currently only precompiled flux pulses ' 'are supported.') tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] tomo_list_q0 = [] tomo_list_q1 = [] for tp in tomo_pulses: tomo_list_q0 += [tp + q0_name] tomo_list_q1 += [tp + q1_name] if omega == 0: G0 = 'Y90' G1 = 'Y90' elif omega == 1: G0 = 'Y90' G1 = 'mY90' elif omega == 2: G0 = 'mY90' G1 = 'Y90' elif omega == 3: G0 = 'mY90' G1 = 'mY90' else: raise ValueError('omega must be in [0, 3]') if RO_target == 'all': RO_line = 'RO {} | RO {}\n'.format(q0_name, q1_name) else: RO_line = 'RO {} \n'.format(RO_target) filename = join(base_qasm_path, 'Grover_tomo_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(q0_name)) qasm_file.writelines('qubit {} \n'.format(q1_name)) for p_q1 in tomo_list_q1: for p_q0 in tomo_list_q0: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('{} {} | {} {}\n'.format( G0, q0_name, G1, q1_name)) qasm_file.writelines('grover_cz {} {}\n'.format(q0_name, q1_name)) qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, q1_name)) qasm_file.writelines('cz {} {}\n'.format(q0_name, q1_name)) # qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, # q1_name)) qasm_file.writelines('{} | {}\n'.format(p_q1, p_q0)) qasm_file.writelines(RO_line) # Add calibration pulses cal_pulses = [] # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. for seq in cal_points_2Q: cal_pulses += [[ seq[0].format(q0_name), seq[1].format(q1_name), RO_line ]] * 7 for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def CZ_fast_calibration_seq(q0_name: str, q1_name: str, no_of_points: int, cal_points: bool=True, RO_target: str='all', CZ_disabled: bool=False, cases=('no_excitation', 'excitation'), wait_after_trigger=40e-9, wait_during_flux=280e-9, clock_cycle=1e-9, mw_pulse_duration=40e-9): ''' Sequence used to (numerically) calibrate CZ gate, including single qubit phase corrections. Repeats the sequence below 'no_of_points' times, giving a new trigger instruction QWG trigger 'i' every time, where 'i' is the number of iteration (starting at 0). Timing of the sequence: q0: -- mX90 C-Phase X90 -- RO q1: (X180) -- -- -- (X180) RO Args: q0, q1 (str): names of the addressed qubits RO_target (str): can be q0, q1, or 'all' CZ_disabled (bool): disable CZ gate excitations (bool/str): can be True, False, or 'both_cases' clock_cycle (float): period of the internal AWG clock wait_time (int): wait time in seconds after triggering the flux ''' filename = join(base_qasm_path, 'CZ_fast_calibration_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0_name, q1_name)) for i in range(no_of_points): if cal_points and (i == no_of_points - 4 or i == no_of_points - 3): # Calibration point for |0> qasm_file.writelines('\ninit_all\n') qasm_file.writelines('RO {} \n'.format(RO_target)) pass elif cal_points and (i == no_of_points - 2 or i == no_of_points - 1): # Calibration point for |1> qasm_file.writelines('\ninit_all\n') qasm_file.writelines('X180 {} \n'.format(q0_name)) qasm_file.writelines('X180 {} \n'.format(q1_name)) qasm_file.writelines('RO {} \n'.format(RO_target)) else: for case in cases: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('QWG_trigger_{}\n'.format(i)) waitTime = wait_after_trigger if case == 'excitation': # Decrease wait time because there is an additional pulse waitTime -= mw_pulse_duration qasm_file.writelines( 'I {}\n'.format(int(waitTime//clock_cycle))) if case == 'excitation': qasm_file.writelines('X180 {}\n'.format(q1_name)) qasm_file.writelines('mX90 {}\n'.format(q0_name)) qasm_file.writelines( 'I {}\n'.format(int(wait_during_flux//clock_cycle))) qasm_file.writelines('X90 {}\n'.format(q0_name)) if case == 'excitation': qasm_file.writelines('X180 {}\n'.format(q1_name)) qasm_file.writelines('RO {} \n'.format(RO_target)) qasm_file.close() return qasm_file
def two_qubit_tomo_bell(bell_state, q0, q1, RO_target='all'): ''' Two qubit bell state tomography. Args: bell_state (int): index of prepared bell state 0 : |00>-|11> 1 : |00>+|11> 2 : |01>-|10> 3 : |01>+|10> q0, q1 (str): names of the target qubits RO_target (str): can be q0, q1, or 'all' ''' if RO_target == 'all': # This is a bit of a hack as RO all qubits is the same instruction # as any specific qubit RO_target = q0 tomo_pulses = ['I ', 'X180 ', 'Y90 ', 'mY90 ', 'X90 ', 'mX90 '] tomo_list_q0 = [] tomo_list_q1 = [] for tp in tomo_pulses: tomo_list_q0 += [tp + q0] tomo_list_q1 += [tp + q1] tomo_list_q0[0] = 'I {}'.format(q0) tomo_list_q1[0] = 'I {}'.format(q1) # Choose a bell state and set the corresponding preparation pulses if bell_state % 10 == 0: # |Phi_m>=|00>-|11> prep_pulse_q0 = 'Y90 {}'.format(q0) prep_pulse_q1 = 'Y90 {}'.format(q1) elif bell_state % 10 == 1: # |Phi_p>=|00>+|11> prep_pulse_q0 = 'mY90 {}'.format(q0) prep_pulse_q1 = 'Y90 {}'.format(q1) elif bell_state % 10 == 2: # |Psi_m>=|01>-|10> prep_pulse_q0 = 'Y90 {}'.format(q0) prep_pulse_q1 = 'mY90 {}'.format(q1) elif bell_state % 10 == 3: # |Psi_p>=|01>+|10> prep_pulse_q0 = 'mY90 {}'.format(q0) prep_pulse_q1 = 'mY90 {}'.format(q1) else: raise ValueError('Bell state {} is not defined.'.format(bell_state)) after_pulse = 'mY90 {}\n'.format(q1) # Disable preparation pulse on one or the other qubit for debugging if bell_state // 10 == 1: prep_pulse_q1 = 'I {}'.format(q0) elif bell_state // 10 == 2: prep_pulse_q0 = 'I {}'.format(q1) # Write tomo sequence filename = join(base_qasm_path, 'two_qubit_tomo_bell.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \nqubit {} \n'.format(q0, q1)) for p_q1 in tomo_list_q1: for p_q0 in tomo_list_q0: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('{} | {} \n'.format(prep_pulse_q0, prep_pulse_q1)) qasm_file.writelines('CZ {} {} \n'.format(q0, q1)) qasm_file.writelines(after_pulse) qasm_file.writelines('{} | {}\n'.format(p_q1, p_q0)) qasm_file.writelines('RO ' + RO_target + ' \n') # Add calibration pulses cal_pulses = [] # every calibration point is repeated 7 times. This is copied from the # script for Tektronix driven qubits. I do not know if this repetition # is important or even necessary here. for seq in cal_points_2Q: cal_pulses += [[ seq[0].format(q0), seq[1].format(q1), 'RO ' + RO_target + '\n' ]] * 7 for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file
def qasm_to_asm(qasm_filepath, operation_dict): """ Args: qasm_filepath: (str) location of the qasm file to convert operation_dict: (dict) dictionary containing info required for conversion. *keys* correspond to qasm commands *items* contain dicts with the reuired information. every item should contain the following entries: instruction: (str) or (fun) that defines the translation from qasm to microcode/assembly duration: (int) length of operation expressed in clock cycles prepare_function: (str) str that refers to function used to prepare the operation prepare_function_kwargs: (dict) containing arguments that get passed to the prepare function returns: asm_file suitable for CBox Assembler, intended to be compatible with the central controller in the future. """ filename = splitext(basename(qasm_filepath))[0] asm_filepath = join(base_asm_path, filename + '.qumis') asm_file = mopen(asm_filepath, mode='w') asm_file.writelines(preamble) with open(qasm_filepath) as qasm_file: qubits = [] # the qubits that were defined for line in qasm_file: # Make lines interpretable line = line.split('#', 1)[0] # remove comments line = line.split('map', 1)[0] # remove mapping info if supplied line = line.strip(' \t\n\r') # remove whitespace if (len(line) == 0): # skip empty line and comment continue elts = line.split() # for single qubit gates that have an argument if len(elts) > 1: base_op = elts[0] + ' ' + elts[1] # Interpret qasm elements commands = list(operation_dict.keys()) + ['qubit'] if elts[0] == 'qubit': qubits.append(elts[1]) elif (line in commands): instruction = operation_dict[line]['instruction'] asm_file.writelines(instruction) # two qubit operation or operation with arg elif base_op in commands: # single qubit op with argument if 'instruction' in operation_dict[base_op].keys(): base_ins = operation_dict[base_op]['instruction'] # string formatting is a constraint now but maybe we can # come up with something smarter if isinstance(base_ins, str): instruction = base_ins.format(elts[2]) else: instruction = base_ins(elts[2]) else: # no support yet for multi qubit ops with arguments raise NotImplementedError( 'Multi qubit ops with args: "{}"'.format(line)) asm_file.writelines(instruction) # Identity is a special instruction that is supported as a wait elif elts[0] == 'I' or elts[0] == 'Idx': clock_waits = int(int(elts[1]) // 5) instruction = 'wait {} \n'.format(clock_waits) asm_file.writelines(instruction) else: raise ValueError( 'Command "{}" not recognized, must be in {}'.format( elts[0], commands)) asm_file.writelines(ending) asm_file.close() return asm_file
def qasm_to_asm(qasm_filepath, operation_dict): """ Args: qasm_filepath: (str) location of the qasm file to convert operation_dict: (dict) dictionary containing info required for conversion. *keys* correspond to qasm commands *items* contain dicts with the reuired information. every item should contain the following entries: instruction: (str) or (fun) that defines the translation from qasm to microcode/assembly duration: (int) length of operation expressed in clock cycles prepare_function: (str) str that refers to function used to prepare the operation prepare_function_kwargs: (dict) containing arguments that get passed to the prepare function returns: asm_file suitable for CBox Assembler, intended to be compatible with the central controller in the future. """ filename = splitext(basename(qasm_filepath))[0] asm_filepath = join(base_asm_path, filename+'.qumis') asm_file = mopen(asm_filepath, mode='w') asm_file.writelines(preamble) with open(qasm_filepath) as qasm_file: qubits = [] # the qubits that were defined for line in qasm_file: # Make lines interpretable line = line.split('#', 1)[0] # remove comments line = line.strip(' \t\n\r') # remove whitespace if (len(line) == 0): # skip empty line and comment continue elts = line.split() # for single qubit gates that have an argument if len(elts) > 1: base_op = elts[0]+' '+elts[1] # Interpret qasm elements commands = list(operation_dict.keys()) + ['qubit'] if elts[0] == 'qubit': qubits.append(elts[1]) elif (line in commands): instruction = operation_dict[line]['instruction'] asm_file.writelines(instruction) # two qubit operation or operation with arg elif base_op in commands: # single qubit op with argument if 'instruction' in operation_dict[base_op].keys(): base_ins = operation_dict[base_op]['instruction'] # string formatting is a constraint now but maybe we can # come up with something smarter if isinstance(base_ins, str): instruction = base_ins.format(elts[2]) else: instruction = base_ins(elts[2]) else: # no support yet for multi qubit ops with arguments raise NotImplementedError( 'Multi qubit ops with args: "{}"'.format(line)) asm_file.writelines(instruction) else: raise ValueError( 'Command "{}" not recognized, must be in {}'.format( elts[0], commands)) asm_file.writelines(ending) asm_file.close() return asm_file
def grover_test_seq(q0_name, q1_name, RO_target='all', precompiled_flux=True, cal_points: bool = True): ''' Writes the QASM sequence for Grover's algorithm on two qubits. Sequence: q0: G0 - - mY90 - - mY90 - RO CZ_ij CZ q1: G1 - - mY90 - - mY90 - RO whit all combinations of (ij) = omega. G0 and G1 are Y90 or Y90, depending on the (ij). Args: q0_name, q1_name (string): Names of the qubits to which the sequence is applied. RO_target (string): Readout target. Can be a qubit name or 'all'. precompiled_flux (bool): Determies if the full waveform for the flux pulses is precompiled, thus only needing one trigger at the start, or if every flux pulse should be triggered individually. cal_points (bool): Whether to add calibration points. Returns: qasm_file: a reference to the new QASM file object. ''' if not precompiled_flux: raise NotImplementedError('Currently only precompiled flux pulses ' 'are supported.') filename = join(base_qasm_path, 'Grover_seq.qasm') qasm_file = mopen(filename, mode='w') qasm_file.writelines('qubit {} \n'.format(q0_name)) qasm_file.writelines('qubit {} \n'.format(q1_name)) if RO_target == 'all': RO_line = 'RO {} | RO {}\n'.format(q0_name, q1_name) else: RO_line = 'RO {} \n'.format(RO_target) for G0 in ['Y90', 'mY90']: for G1 in ['Y90', 'mY90']: qasm_file.writelines('\ninit_all\n') qasm_file.writelines('{} {} | {} {}\n'.format( G0, q0_name, G1, q1_name)) qasm_file.writelines('grover_CZ {} {}\n'.format(q0_name, q1_name)) qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, q1_name)) # qasm_file.writelines('cz {} {}\n'.format(q0_name, q1_name)) # qasm_file.writelines('Y90 {} | Y90 {}\n'.format(q0_name, # q1_name)) qasm_file.writelines(RO_line) # Add calibration points if cal_points: cal_pulses = [] for seq in cal_points_2Q: cal_pulses += [[ seq[0].format(q0_name), seq[1].format(q1_name), RO_line ]] for seq in cal_pulses: qasm_file.writelines('\ninit_all\n') for p in seq: qasm_file.writelines(p) qasm_file.close() return qasm_file