def generate_sequence(self, config): """Generate sequence by adding gates/pulses to waveforms.""" # get parameters n_pulse = int(config['# of pi pulses']) pi_to_q = config['Add pi pulses to Q'] duration = config['Sequence duration'] edge_to_edge = config['Edge-to-edge pulses'] manipulated_qubits = config['Manipulated Qubits'] d = dict( Zero=0, One=1, Two=2, Three=3, Four=4, Five=5, Six=6, Seven=7, Eight=8, Nine=9) if manipulated_qubits=='All': qubit = list(range((self.n_qubit))) else: qubit = [d[manipulated_qubits]-1] # select type of refocusing pi pulse gate_pi = [(gates.Yp if pi_to_q else gates.Xp) for n in range(len(qubit))] gate_X2p = [gates.X2p for n in range(len(qubit))] # always do T1 same way, regardless if edge-to-edge or center-center if n_pulse < 0: self.add_gate(qubit,gate_pi) self.add_gate_to_all(gates.IdentityGate(width=duration), dt=0) elif edge_to_edge: # edge-to-edge pulsing, set pulse separations self.add_gate(qubit,gate_X2p) # for ramsey, just add final pulse if n_pulse == 0: self.add_gate(qubit,gate_X2p, dt=duration) else: dt = duration / n_pulse # add first pi pulse after half duration self.add_gate(qubit,gate_pi, dt=dt/2) # add rest of pi pulses for i in range(n_pulse - 1): self.add_gate(qubit,gate_pi, dt=dt) # add final pi/2 pulse self.add_gate(qubit,gate_X2p, dt=dt/2) else: # center-to-center spacing, set absolute pulse positions self.add_gate(qubit,gate_X2p, t0=0) # add pi pulses at right position for i in range(n_pulse): self.add_gate(qubit,gate_pi, t0=(i + 0.5) * (duration / n_pulse)) # add final pi/2 pulse self.add_gate(qubit,gate_X2p, t0=duration)
def generate_sequence(self, config): """Generate sequence by adding gates/pulses to waveforms.""" # get parameters n_pulse = int(config['# of pi pulses']) pi_to_q = config['Add pi pulses to Q'] duration = config['Sequence duration'] edge_to_edge = config['Edge-to-edge pulses'] if config['Add last pi/2 pulse to Q']: pi2_final = gates.Y2p else: pi2_final = gates.X2p # select type of refocusing pi pulse gate_pi = gates.Yp if pi_to_q else gates.Xp # always do T1 same way, regardless if edge-to-edge or center-center if n_pulse < 0: self.add_gate_to_all(gate_pi) self.add_gate_to_all(gates.IdentityGate(width=duration), dt=0) elif edge_to_edge: # edge-to-edge pulsing, set pulse separations self.add_gate_to_all(gates.X2p) # for ramsey, just add final pulse if n_pulse == 0: self.add_gate_to_all(gates.X2p, dt=duration) else: dt = duration / n_pulse # add first pi pulse after half duration self.add_gate_to_all(gate_pi, dt=dt / 2) # add rest of pi pulses for i in range(n_pulse - 1): self.add_gate_to_all(gate_pi, dt=dt) # add final pi/2 pulse self.add_gate_to_all(pi2_final, dt=dt / 2) else: # center-to-center spacing, set absolute pulse positions self.add_gate_to_all(gates.X2p, t0=0) # add pi pulses at right position for i in range(n_pulse): self.add_gate_to_all(gate_pi, t0=(i + 0.5) * (duration / n_pulse)) # add final pi/2 pulse self.add_gate_to_all(pi2_final, t0=duration)
def generate_sequence(self, config): """ Generate sequence by adding gates/pulses to waveforms. Parameters ---------- config: dict configuration Returns ------- """ # get parameters sequence = config['Sequence'] qubits_to_benchmark = [int(config['Qubits to Benchmark'][0]) - 1, int(config['Qubits to Benchmark'][2]) - 1] # Number of Cliffords to generate N_cliffords = int(config['Number of Cliffords']) randomize = config['Randomize'] interleave = config['Interleave 2-QB Gate'] multi_seq = config.get('Output multiple sequences', False) write_seq = config.get('Write sequence as txt file', False) generator = config.get('Native 2-QB gate', 'CZ') rnd.seed(randomize) if interleave is True: interleaved_gate = config['Interleaved 2-QB Gate'] else: interleaved_gate = np.inf # generate new randomized clifford gates only if configuration changes if (self.prev_sequence != sequence or self.prev_randomize != randomize or self.prev_N_cliffords != N_cliffords or self.prev_interleave != interleave or multi_seq or self.prev_interleaved_gate != interleaved_gate or self.generator != generator): self.prev_randomize = randomize self.prev_N_cliffords = N_cliffords self.prev_interleave = interleave self.prev_sequence = sequence self.generator = generator multi_gate_seq = [] # Generate 2QB RB sequence cliffordSeq1 = [] cliffordSeq2 = [] for j in range(N_cliffords): log.info('Seed number: %d'%(randomize)) rndnum = rnd.randint(0, 11519) # rndnum = rnd.randint(0, 576) #Only applying single qubit gates add_twoQ_clifford(rndnum, cliffordSeq1, cliffordSeq2, generator = generator) # If interleave gate, if interleave is True: self.prev_interleaved_gate = interleaved_gate if interleaved_gate == 'CZ': cliffordSeq1.append(gates.I) cliffordSeq2.append(gates.CZ) elif interleaved_gate == 'CZEcho': # CZEcho is a composite gate, so get each gate gate = gates.CZEcho for g in gate.sequence: cliffordSeq1.append(g[1]) cliffordSeq2.append(g[0]) elif interleaved_gate == 'iSWAP': gate = gates.iSWAP for g in gate.sequence: cliffordSeq1.append(g[1]) cliffordSeq2.append(g[0]) elif interleaved_gate == 'I': # TBA: adjust the duration of I gates? # log.info('Qubits to benchmark: ' + str(qubits_to_benchmark)) # gate = gates.I(width = self.pulses_2qb[qubit]).value I_2QB = gates.IdentityGate(width =config.get('Width, 2QB')) cliffordSeq1.append(I_2QB) cliffordSeq2.append(I_2QB) # cliffordSeq1.append(gates.I) # cliffordSeq2.append(gates.I) # remove redundant Identity gates for cliffordSeq1 index_identity_clifford = [] # find where Identity gates are for p in range(len(cliffordSeq1)): if (cliffordSeq1[p] == gates.I and cliffordSeq2[p] == gates.I): index_identity_clifford.append(p) cliffordSeq1 = [m for n, m in enumerate(cliffordSeq1) if n not in index_identity_clifford] cliffordSeq2 = [m for n, m in enumerate(cliffordSeq2) if n not in index_identity_clifford] # get recovery gate seq (recoverySeq1, recoverySeq2) = self.get_recovery_gate( cliffordSeq1, cliffordSeq2, config, generator = generator) # Remove redundant identity gates in recovery gate seq index_identity_recovery = [] # find where Identity gates are for p in range(len(recoverySeq1)): if (recoverySeq1[p] == gates.I and recoverySeq2[p] == gates.I): index_identity_recovery.append(p) recoverySeq1 = [m for n, m in enumerate(recoverySeq1) if n not in index_identity_recovery] recoverySeq2 = [m for n, m in enumerate(recoverySeq2) if n not in index_identity_recovery] # Construct the total gate sequence. gateSeq1 = [] gateSeq2 = [] gateSeq1.extend(cliffordSeq1) gateSeq1.extend(recoverySeq1) gateSeq2.extend(cliffordSeq2) gateSeq2.extend(recoverySeq2) # Avoid Error: zero-size array to reduction operation maximum which has no identity (05/05/2019) if (gateSeq1 == [] and gateSeq2 == []): gateSeq1.append(gates.I) gateSeq2.append(gates.I) # test the recovery gate psi_gnd = np.matrix('1; 0; 0; 0') # ground state |00> if write_seq == True: import os from datetime import datetime directory = os.path.join(path_currentdir,'2QB_RBseq') if not os.path.exists(directory): os.makedirs(directory) filename = datetime.now().strftime('%Y-%m-%d %H-%M-%S-f')[:-3] + '_N_cliffords=%d_seed=%d.txt'%(N_cliffords,randomize) # filename = datetime.now().strftime('%Y-%m-%d %H-%M-%S-%f')[:-3] + '_N_cliffords=%d_seed=%d.txt'%(N_cliffords,randomize) filepath = os.path.join(directory,filename) log.info('make file: ' + filepath) with open(filepath, "w") as text_file: print('New Sequence', file=text_file) for i in range(len(gateSeq1)): print("Index: %d, Gate: ["%(i) + cliffords.Gate_to_strGate(gateSeq1[i]) + ", " + cliffords.Gate_to_strGate(gateSeq2[i]) +']', file=text_file) for i in range(len(cliffordSeq1)): print("CliffordIndex: %d, Gate: ["%(i) + cliffords.Gate_to_strGate(cliffordSeq1[i]) + ", " + cliffords.Gate_to_strGate(cliffordSeq2[i]) +']', file=text_file) for i in range(len(recoverySeq1)): print("RecoveryIndex: %d, Gate: ["%(i) + cliffords.Gate_to_strGate(recoverySeq1[i]) + ", " + cliffords.Gate_to_strGate(recoverySeq2[i]) +']', file=text_file) psi = np.matmul(self.evaluate_sequence(gateSeq1, gateSeq2), psi_gnd) np.set_printoptions(precision=2) log.info('The matrix of the overall gate sequence:') log.info(self.evaluate_sequence(gateSeq1, gateSeq2)) log.info('--- TESTING THE RECOVERY GATE ---') log.info('The probability amplitude of the final state vector: ' + str(np.matrix(psi).flatten())) log.info('The population of the ground state after the gate sequence: %.4f'%(np.abs(psi[0,0])**2)) log.info('-------------------------------------------') # Assign two qubit gate sequence to where we want # for i in range(qubits_to_benchmark[0] - 1): # multi_gate_seq.append([None] * len(gateSeq1)) multi_gate_seq.append(gateSeq2) multi_gate_seq.append(gateSeq1) # for i in range(self.n_qubit - qubits_to_benchmark[1]): # multi_gate_seq.append([None] * len(gateSeq1)) # transpose list of lists multi_gate_seq = list(map(list, itertools.zip_longest(*multi_gate_seq, fillvalue=gates.I))) # Not to chop # self.add_gates(multi_gate_seq) for gate_seq in multi_gate_seq: if ((gate_seq[0] == gates.CZ) or (gate_seq[0] == gates.iSWAP)): self.add_gate(qubit=qubits_to_benchmark, gate=gate_seq[0]) else: self.add_gate(qubit=qubits_to_benchmark, gate=gate_seq) self.prev_gate_seq = multi_gate_seq else: for gate_seq in self.prev_gate_seq: if gate_seq[0] == gates.CZ: self.add_gate(qubit=qubits_to_benchmark, gate=gate_seq[0]) else: self.add_gate(qubit=qubits_to_benchmark, gate=gate_seq)
def generate_sequence(self, config): """Generate sequence by adding gates/pulses to waveforms.""" # get parameters n_pulse = int(config['# of pi pulses']) pi_to_q = config['Add pi pulses to Q'] duration = config['Sequence duration'] edge_to_edge = config['Edge-to-edge pulses'] measure_2nd = bool(config['Measure T1 for 2nd Excited State']) # select type of refocusing pi pulse if (measure_2nd == True): gate_pi = gates.Yp_12 if pi_to_q else gates.Xp_12 else: gate_pi = gates.Yp if pi_to_q else gates.Xp # always do T1 same way, regardless if edge-to-edge or center-center if n_pulse < 0: self.add_gate_to_all(gates.Xp) if (measure_2nd == True): self.add_gate_to_all(gates.Xp_12) # self.add_gate_to_all(gate_pi) # self.add_gate(qubit=2, gate=gates.Xp_12) self.add_gate_to_all(gates.IdentityGate(width=duration), dt=0) elif edge_to_edge: # edge-to-edge pulsing, set pulse separations if (measure_2nd == True): self.add_gate_to_all(gates.Xp) self.add_gate_to_all(gates.X2p_12) else: self.add_gate_to_all(gates.X2p) # for ramsey, just add final pulse if n_pulse == 0: if (measure_2nd == True): self.add_gate_to_all(gates.X2p_12, dt=duration) else: self.add_gate_to_all(gates.X2p, dt=duration) else: dt = duration / n_pulse # add first pi pulse after half duration self.add_gate_to_all(gate_pi, dt=dt / 2) # add rest of pi pulses for i in range(n_pulse - 1): self.add_gate_to_all(gate_pi, dt=dt) if (measure_2nd == True): # add final pi/2 pulse self.add_gate_to_all(gates.X2p_12, dt=dt / 2) else: # add final pi/2 pulse self.add_gate_to_all(gates.X2p, dt=dt / 2) else: if (measure_2nd == True): self.add_gate_to_all(gates.Xp) # center-to-center spacing, set absolute pulse positions self.add_gate_to_all(gates.X2p_12, t0=0) # add pi pulses at right position for i in range(n_pulse): self.add_gate_to_all(gate_pi, t0=(i + 0.5) * (duration / n_pulse)) # add final pi/2 pulse self.add_gate_to_all(gates.X2p_12, t0=duration) else: # center-to-center spacing, set absolute pulse positions self.add_gate_to_all(gates.X2p, t0=0) # add pi pulses at right position for i in range(n_pulse): self.add_gate_to_all(gate_pi, t0=(i + 0.5) * (duration / n_pulse)) # add final pi/2 pulse self.add_gate_to_all(gates.X2p, t0=duration)