def test_partial_exchange(self): qubit_1 = 0 qubit_2 = 1 qasm_1 = QasmUtils.qasm_header(2) qasm_1 += 'x q[{}];\n'.format(qubit_1) qasm_2 = QasmUtils.qasm_header(2) qasm_2 += 'x q[{}];\n'.format(qubit_2) angles = [0, numpy.pi / 4, numpy.pi / 3, numpy.pi / 2, numpy.pi] for angle in angles: statevector_1 = QiskitSimBackend.\ statevector_from_qasm(qasm_1 + QasmUtils.partial_exchange(angle, qubit_1, qubit_2)).round(3) expected_statevector_1 = numpy.array( [0, numpy.cos(angle), -numpy.sin(angle), 0]) expected_statevector_1 = expected_statevector_1.round(3) for i in range(len(statevector_1)): self.assertEqual(statevector_1[i], expected_statevector_1[i]) statevector_2 = QiskitSimBackend.\ statevector_from_qasm(qasm_2 + QasmUtils.partial_exchange(angle, qubit_1, qubit_2)).round(3) expected_statevector_2 = numpy.array( [0, numpy.sin(angle), numpy.cos(angle), 0]) expected_statevector_2 = expected_statevector_2.round(3) for i in range(len(statevector_2)): self.assertEqual(statevector_2[i], expected_statevector_2[i])
def test_double_exchange_extended(self): angles = [-0.2, 0.2] for angle in angles: qasm = [''] qasm.append(QasmUtils.qasm_header(6)) # qasm_1.append('x q[3];\n') qasm.append('h q[4];\n') qasm.append('x q[2];\n') qasm.append('x q[0];\n') qasm.append( DFExc([0, 2], [3, 5], rescaled_parameter=True, parity_dependence=True).get_qasm([angle])) statevector = QiskitSimBackend.statevector_from_qasm(''.join(qasm)) self.assertEqual(statevector[56].real.round(5), -statevector[40].real.round(5)) qasm = [''] qasm.append(QasmUtils.qasm_header(6)) # qasm_1.append('x q[3];\n') qasm.append('h q[4];\n') qasm.append('x q[2];\n') qasm.append('x q[0];\n') qasm.append( DFExc([0, 2], [3, 5], rescaled_parameter=True).get_qasm([angle])) statevector = QiskitSimBackend.statevector_from_qasm(''.join(qasm)) self.assertEqual(statevector[56].real.round(5), statevector[40].real.round(5))
def statevector_from_ansatz(ansatz, var_parameters, n_qubits, n_electrons, init_state_qasm=None): assert n_electrons < n_qubits qasm = [''] qasm.append(QasmUtils.qasm_header(n_qubits)) # initial state if init_state_qasm is None: qasm.append(QasmUtils.hf_state(n_electrons)) else: qasm.append(init_state_qasm) ansatz_qasm = QiskitSimBackend.qasm_from_ansatz(ansatz, var_parameters) qasm += ansatz_qasm # Get a circuit of SWAP gates to reverse the order of qubits. This is required in order the statevector to # match the reversed order of qubits used by openfermion when obtaining the Hamiltonian Matrix. qasm.append(QasmUtils.reverse_qubits_qasm(n_qubits)) qasm = ''.join(qasm) statevector = QiskitSimBackend.statevector_from_qasm(qasm) # print(qasm) return statevector
def test_pauli_gates_circuit_statevector(self): qubit_operator = openfermion.QubitOperator('X0 Y1') qasm_circuit = QasmUtils.qasm_header(2) qasm_circuit += QasmUtils.pauli_word_qasm(qubit_operator) statevector = QiskitSimBackend.statevector_from_qasm(qasm_circuit) expected_statevector = numpy.array([0, 0, 0, 1j]) self.assertEqual(len(expected_statevector), len(statevector)) for i in range(len(statevector)): self.assertEqual(statevector[i], expected_statevector[i])
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 qasm = QasmUtils.eff_s_f_exc_qasm(var_parameters[0], self.qubits[0][0], self.qubits[1][0]) if {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[0], *self.complement_qubits[1]} and \ {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[1], *self.complement_qubits[0]}: qasm += QasmUtils.eff_s_f_exc_qasm(var_parameters[0], self.complement_qubits[0][0], self.complement_qubits[1][0]) return qasm
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 qasm = QasmUtils.partial_exchange(-var_parameters[0], self.qubits[0][0], self.qubits[1][0]) if {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[0], *self.complement_qubits[1]} and \ {*self.qubits[0], *self.qubits[1]} != {*self.complement_qubits[1], *self.complement_qubits[0]}: qasm += QasmUtils.partial_exchange(-self.sign * var_parameters[0], self.complement_qubits[0][0], self.complement_qubits[1][0]) return qasm
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 parameter_1 = var_parameters[0] qasm = QasmUtils.d_q_exc_qasm(parameter_1, self.qubits[0], self.qubits[1]) if [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[0]), set(self.complement_qubits[1])] and \ [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[1]), set(self.complement_qubits[0])]: qasm += QasmUtils.d_q_exc_qasm(self.sign * parameter_1, self.complement_qubits[0], self.complement_qubits[1]) return qasm
def test_hf_states(self): n_qubits = 5 n_electrons = 3 qasm = QasmUtils.qasm_header(n_qubits) qasm += QasmUtils.hf_state(n_electrons) qasm += QasmUtils.reverse_qubits_qasm(n_qubits) qiskit_statevector = QiskitSimBackend.statevector_from_qasm(qasm) sparse_statevector = scipy.sparse.csr_matrix( openfermion.utils.jw_hartree_fock_state(n_electrons, n_qubits)) array_statevector = numpy.array(sparse_statevector.todense())[0] for i in range(len(qiskit_statevector)): self.assertEqual(qiskit_statevector[i], array_statevector[i])
def test_controlled_y_gate_1(self): control = 0 target = 1 # case 1 qasm = QasmUtils.qasm_header(2) qasm += 'x q[{}];\n'.format(control) qasm += QasmUtils.controlled_y_rotation(numpy.pi / 2, control, target) statevector = QiskitSimBackend.statevector_from_qasm(qasm).round(3) expected_statevector = numpy.array([0, 1, 0, 1]) / numpy.sqrt(2) expected_statevector = expected_statevector.round(3) for i in range(len(statevector)): self.assertEqual(statevector[i], expected_statevector[i])
def test_exponent_statevector(self): exp_operator = ((0, 'X'), (1, 'Z'), (2, 'Z')) qasm = QasmUtils.qasm_header(3) qasm += QasmUtils.exponent_qasm(exp_operator, -numpy.pi / 2) statevector = QiskitSimBackend.statevector_from_qasm(qasm) expected_statevector = numpy.zeros(8) expected_statevector[1] = 1 self.assertEqual(len(expected_statevector), len(statevector)) for i in range(len(statevector)): self.assertEqual(statevector[i].round(3), expected_statevector[i].round(3))
def get_statevector(self, ansatz, var_parameters, init_state_qasm=None): assert len(var_parameters) == len(ansatz) if self.var_parameters is not None and var_parameters == self.var_parameters: # this condition is not neccessarily sufficient assert self.sparse_statevector is not None else: if self.init_sparse_statevector is not None: sparse_statevector = self.init_sparse_statevector.transpose( ).conj() else: if init_state_qasm is not None: # TODO check qasm = QasmUtils.qasm_header( self.n_qubits) + init_state_qasm statevector = QiskitSimBackend.statevector_from_qasm(qasm) else: statevector = self.hf_statevector() sparse_statevector = scipy.sparse.csr_matrix( statevector).transpose().conj() for i, excitation in enumerate(ansatz): parameter = var_parameters[i] excitation_matrices = self.get_ansatz_element_excitations_matrices( excitation, parameter) excitation_matrix = self.identity for exc_matrix in excitation_matrices[:: -1]: # the first should be the right most (confusing) excitation_matrix *= exc_matrix sparse_statevector = excitation_matrix.dot(sparse_statevector) self.sparse_statevector = sparse_statevector.transpose().conj() self.var_parameters = var_parameters return self.sparse_statevector
def custom_double_excitation(angle, qubit_pair_1, qubit_pair_2): qasm = [''] # determine tha parity of the two qubit pairs qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_1)) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_2)) # perform partial single qubit exchange on q0 and q2, controlled by q1 = |0> and q3 = |0> qasm.append('x q[{}];\n'.format(qubit_pair_1[1])) qasm.append('x q[{}];\n'.format(qubit_pair_2[1])) # TODO add parity dependence qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_1[0])) qasm.append( QasmUtils.n_controlled_y_rotation( angle=angle, controls=[*qubit_pair_1, qubit_pair_2[1]], target=qubit_pair_2[0])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_1[0])) qasm.append('x q[{}];\n'.format(qubit_pair_1[1])) qasm.append('x q[{}];\n'.format(qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_1)) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_2)) return ''.join(qasm)
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 qasm = '' for excitation_generator in self.excitations_generators: qasm += QasmUtils.excitation_qasm(excitation_generator, var_parameters[0]) return qasm
def get_qasm(self, var_parameters): assert len(var_parameters) == self.n_var_parameters var_parameters_cycle = itertools.cycle(var_parameters) qasm = [''] for block in range(self.n_blocks): unoccupied_orbitals = list(range(self.n_electrons, self.n_orbitals)) for occupied_orbital in reversed(range(0, self.n_electrons)): if len(unoccupied_orbitals) == 0: break if occupied_orbital == self.n_electrons - 1: virtual_orbital = self.n_electrons + block else: virtual_orbital = min(unoccupied_orbitals) unoccupied_orbitals.remove(virtual_orbital) # add a phase rotation for the excited orbitals only angle = var_parameters_cycle.__next__() qasm.append('rz({}) q[{}];\n'.format(angle, virtual_orbital)) angle = var_parameters_cycle.__next__() qasm.append( QasmUtils.partial_exchange(angle, occupied_orbital, virtual_orbital)) # TODO add exchanges between the last unoccupied orbitals? return ''.join(qasm)
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 parameter_1 = var_parameters[0] qasm = QasmUtils.eff_d_f_exc_qasm(parameter_1, self.qubits[0], self.qubits[1]) # if the spin complement is different, add a qasm for it if [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[0]), set(self.complement_qubits[1])] and \ [set(self.qubits[0]), set(self.qubits[1])] != [set(self.complement_qubits[1]), set(self.complement_qubits[0])]: qasm += QasmUtils.eff_d_f_exc_qasm(parameter_1, self.complement_qubits[0], self.complement_qubits[1]) return qasm
def gate_count_from_ansatz(ansatz, n_qubits, var_parameters=None): n_var_parameters = sum([x.n_var_parameters for x in ansatz]) if var_parameters is None: var_parameters = numpy.zeros(n_var_parameters) else: assert n_var_parameters == len(var_parameters) qasm = backends.QiskitSimBackend.qasm_from_ansatz(ansatz, var_parameters) return QasmUtils.gate_count_from_qasm(qasm, n_qubits)
def elements_individual_vqe_energy_reductions(vqe_runner, ansatz_elements, elements_parameters=None, ansatz=None, ansatz_parameters=None, excited_state=0, global_cache=None): if ansatz is None: ansatz = [] ansatz_parameters = [] # TODO this will work only if the ansatz element has 1 var. par. if elements_parameters is None: elements_parameters = list(numpy.zeros(len(ansatz_elements))) if vqe_runner.backend == backends.QiskitSimBackend: ansatz_qasm = QasmUtils.hf_state(vqe_runner.q_system.n_electrons) ansatz_qasm += vqe_runner.backend.qasm_from_ansatz(ansatz, ansatz_parameters) else: ansatz_qasm = None def get_thread_cache(element): if global_cache is not None: init_sparse_statevector = global_cache.get_statevector(ansatz, ansatz_parameters) return global_cache.single_par_vqe_thread_cache(element, init_sparse_statevector) else: return None if config.multithread: elements_results = [] chunk_size = config.multithread_chunk_size if chunk_size is None: chunk_size = len(ansatz_elements) n_chunks = int(len(ansatz_elements) / chunk_size) + 1 for i in range(n_chunks): # logging.info('Calculating commutators, patch No: {}'.format(i)) ansatz_elements_chunk = ansatz_elements[i * chunk_size:][:chunk_size] ray.init(num_cpus=config.ray_options['n_cpus'], object_store_memory=config.ray_options['object_store_memory']) elements_ray_ids = [ [element, vqe_runner.vqe_run_multithread.remote(self=vqe_runner, ansatz=[element], init_state_qasm=ansatz_qasm, init_guess_parameters=[elements_parameters[i]], excited_state=excited_state, cache=get_thread_cache(element)) ] # TODO this will work only if the ansatz element has 1 var. par. for i, element in enumerate(ansatz_elements_chunk) ] elements_results += [[element_ray_id[0], ray.get(element_ray_id[1])] for element_ray_id in elements_ray_ids] ray.shutdown() else: # use thread cache even if not multithreading since it contains the precalculated init_sparse_statevector elements_results = [ [element, vqe_runner.vqe_run(ansatz=[element], init_guess_parameters=[elements_parameters[i]], excited_state=excited_state, init_state_qasm=ansatz_qasm, cache=get_thread_cache(element)) ] for i, element in enumerate(ansatz_elements) ] return elements_results
def test_exponent_statevectors(self): qubit_operators = [] # only symetric qubit operators will works, because qiskit and openfermion use different qubit orderings qubit_operators.append(openfermion.QubitOperator('Z0 Y1 Z2')) qubit_operators.append(openfermion.QubitOperator('X0 Y1 X2')) qubit_operators.append(openfermion.QubitOperator('Y0 X1 X2 Y3')) for qubit_operator in qubit_operators: qubit_operator_tuple = list(qubit_operator.terms.keys())[0] n_qubits = len(qubit_operator_tuple) for angle in range(10): angle = 2 * numpy.pi / 10 # <<< create a statevector using QiskitSimulation.get_exponent_qasm >>> qasm = QasmUtils.qasm_header(n_qubits) qasm += QasmUtils.exponent_qasm(qubit_operator_tuple, angle) qiskit_statevector = QiskitSimBackend.statevector_from_qasm( qasm) qiskit_statevector = qiskit_statevector * numpy.exp( 1j * angle) # correct for a global phase qiskit_statevector = qiskit_statevector.round( 2) # round for the purpose of testing # <<< create a statevector using MatrixCalculation.get_qubit_operator_exponent_matrix >>> exp_matrix = MatrixUtils.get_excitation_matrix( 1j * qubit_operator, n_qubits, angle).todense() # prepare initial statevector corresponding to state |0> array_statevector = numpy.zeros(2**n_qubits) array_statevector[0] = 1 # update statevector array_statevector = numpy.array( exp_matrix.dot(array_statevector))[0].round( 2) # round for the purpose of testing # <<<< compare both state vectors >>>> self.assertEqual(len(array_statevector), len(qiskit_statevector)) # check the components of the two vectors are equal for i in range(len(qiskit_statevector)): self.assertEqual(qiskit_statevector[i], array_statevector[i])
def double_exchange_old(angle, qubit_pair_1, qubit_pair_2): assert len(qubit_pair_1) == 2 assert len(qubit_pair_2) == 2 qasm = [''] qasm.append( QasmUtils.partial_exchange(angle, qubit_pair_1[1], qubit_pair_2[0])) qasm.append( QasmUtils.partial_exchange(-angle, qubit_pair_1[0], qubit_pair_2[1])) qasm.append('cz q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_2[1])) qasm.append( QasmUtils.partial_exchange(-angle, qubit_pair_1[1], qubit_pair_2[0])) qasm.append( QasmUtils.partial_exchange(angle, qubit_pair_1[0], qubit_pair_2[1])) # corrections qasm.append('cz q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_2[1])) return ''.join(qasm)
def get_qasm(self, var_parameters): var_parameters_cycle = itertools.cycle(var_parameters) count = 0 qasm = [''] # add single qubit n rotations # for qubit in range(self.n_orbitals): # qasm.append('rz ({}) q[{}];\n'.format(var_parameters_cycle.__next__(), qubit)) # count += 1 # double orbital exchanges for qubit in range(self.n_orbitals): if qubit % 4 == 0: q_0 = qubit q_1 = (qubit + 1) % self.n_orbitals q_2 = (qubit + 2) % self.n_orbitals q_3 = (qubit + 3) % self.n_orbitals q_4 = (qubit + 4) % self.n_orbitals # qasm.append(DoubleExchangeAnsatzElement.double_exchange(var_parameters_cycle.__next__(), [q_0, q_1], [q_2, q_3])) # count += 1 qasm.append( DoubleExchangeAnsatzElement.double_exchange( var_parameters_cycle.__next__(), [q_1, q_2], [q_3, q_4])) count += 1 # single orbital exchanges for qubit in range(self.n_orbitals): if qubit % 2 == 0: qasm.append( QasmUtils.partial_exchange(var_parameters_cycle.__next__(), qubit, (qubit + 1) % self.n_orbitals)) count += 1 qasm.append( QasmUtils.partial_exchange(var_parameters_cycle.__next__(), (qubit + 1) % self.n_orbitals, (qubit + 2) % self.n_orbitals)) count += 1 assert count == len(var_parameters) return ''.join(qasm)
def get_excitation_list_qasm(excitation_list, var_parameters, gate_counter): qasm = [''] # iterate over all excitations (each excitation is represented by a sum of products of pauli operators) for i, excitation in enumerate(excitation_list): # print('Excitation ', i) # testing # iterate over the terms of each excitation (each term is a product of pauli operators, on different qubits) # TODO replace with the function from QasmUtils for exponent_term in excitation.terms: exponent_angle = var_parameters[i] * excitation.terms[exponent_term] assert exponent_angle.real == 0 exponent_angle = exponent_angle.imag qasm.append(QasmUtils.exponent_qasm(exponent_term, exponent_angle)) return ''.join(qasm)
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 return QasmUtils.partial_exchange( -var_parameters[0], self.qubits[0][0], self.qubits[1][0] ) # the minus sign is important for consistence with the d_q_exc, as well obtaining the correct sign for grads...
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 parameter = var_parameters[0] return QasmUtils.eff_d_f_exc_qasm(parameter, self.qubits[0], self.qubits[1])
def double_exchange(angle, qubit_pair_1, qubit_pair_2, parity_dependence=False, d_exc_correction=False): assert len(qubit_pair_1) == 2 assert len(qubit_pair_2) == 2 theta_1 = numpy.pi / 2 - angle qasm = [''] # 1st exchange + 0-2 qasm.append(QasmUtils.controlled_xz(qubit_pair_2[0], qubit_pair_1[0])) qasm.append('ry({}) q[{}];\n'.format(theta_1, qubit_pair_2[0])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[0])) qasm.append('ry({}) q[{}];\n'.format(-theta_1, qubit_pair_2[0])) # 2nd exchange + 1-3 qasm.append(QasmUtils.controlled_xz(qubit_pair_2[1], qubit_pair_1[1])) qasm.append('ry({}) q[{}];\n'.format(theta_1, qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[1], qubit_pair_2[1])) qasm.append('ry({}) q[{}];\n'.format(-theta_1, qubit_pair_2[1])) # CZ gates qasm.append('cz q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_2[1])) # qasm.append('cz q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) # correction 3rd order terms approximates the operation of a double exchange if d_exc_correction: angle_2 = DoubleExchange.second_angle(angle) # not correcting 3rd order terms approximates the operation of a double excitation (with 3rd order error terms) else: angle_2 = angle theta_2 = numpy.pi / 2 - angle_2 # 3rd exchange - 0-2 qasm.append('ry({}) q[{}];\n'.format(theta_2, qubit_pair_2[0])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[0])) qasm.append('ry({}) q[{}];\n'.format(-theta_2, qubit_pair_2[0])) qasm.append( QasmUtils.controlled_xz(qubit_pair_2[0], qubit_pair_1[0], reverse=True)) # 4th exchange -1-3 qasm.append('ry({}) q[{}];\n'.format(theta_2, qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[1], qubit_pair_2[1])) qasm.append('ry({}) q[{}];\n'.format(-theta_2, qubit_pair_2[1])) qasm.append( QasmUtils.controlled_xz(qubit_pair_2[1], qubit_pair_1[1], reverse=True)) # correcting for parameter sign if parity_dependence: # do not include the first qubit of the second pair parity_qubits = list(range( min(qubit_pair_1), max(qubit_pair_1))) + list( range(min(qubit_pair_2) + 1, max(qubit_pair_2))) # ladder of CNOT used to determine the parity cnot_ladder = [''] for i in range(len(parity_qubits) - 1): cnot_ladder.append('cx q[{}], q[{}];\n'.format( parity_qubits[i], parity_qubits[i + 1])) if angle > 0: # applies a CZ correction in front, to get a negative sign for the excitation term, if the parity is 1 # (or the parity of "parity_qubits" is 0) front = [''] # this is the CZ that determines the sign of the excitation term front.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) # this bit determines the parity and applies a CZ to negate the correction if the parity is wrong front += cnot_ladder front.append('x q[{}];\n'.format(parity_qubits[-1])) front.append('cz q[{}], q[{}];\n'.format( parity_qubits[-1], qubit_pair_2[0])) front.append('x q[{}];\n'.format(parity_qubits[-1])) front += cnot_ladder[::-1] # .. positive sign for the excitation term, if the parity is 0 (or the parity of "parity_qubits" is 1) rear = [''] # .. sign correction rear.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) # .. parity correction rear += cnot_ladder rear.append('cz q[{}], q[{}];\n'.format( parity_qubits[-1], qubit_pair_2[0])) rear += cnot_ladder[::-1] # additional correction of states 010 and 110 rear.append('x q[{}];\n'.format(qubit_pair_2[1])) rear.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) rear.append('x q[{}];\n'.format(qubit_pair_2[1])) qasm = front + qasm + rear else: front = [''] # sign correction front.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) # parity correction front += cnot_ladder front.append('cz q[{}], q[{}];\n'.format( parity_qubits[-1], qubit_pair_2[0])) front += cnot_ladder[::-1] rear = [''] # sign correction rear.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) # parity correction rear += cnot_ladder rear.append('x q[{}];\n'.format(parity_qubits[-1])) rear.append('cz q[{}], q[{}];\n'.format( parity_qubits[-1], qubit_pair_2[0])) rear.append('x q[{}];\n'.format(parity_qubits[-1])) rear += cnot_ladder[::-1] # 010 and 011 correction rear.append('x q[{}];\n'.format(qubit_pair_2[1])) rear.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) rear.append('x q[{}];\n'.format(qubit_pair_2[1])) qasm = front + qasm + rear else: if angle > 0: # adding a correcting CZ gate at the end will result in a minus sign qasm.append('cz q[{}], q[{}];\n'.format( qubit_pair_2[0], qubit_pair_2[1])) # qasm.append('cz q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) else: # adding a correcting CZ gate at the front will result in a plus sign qasm = ['cz q[{}], q[{}];\n'.format(qubit_pair_2[0], qubit_pair_2[1]), ] \ + qasm # 'cz q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1]) return ''.join(qasm)
def efficient_double_excitation_2(angle, qubit_pair_1, qubit_pair_2): qasm = [''] theta = angle / 8 # determine the parity of the two pairs qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_1)) qasm.append('x q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_2)) qasm.append('x q[{}];\n'.format(qubit_pair_2[1])) # apply a partial swap of qubits 0 and 2, controlled by 1 and 3 ## qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[0])) # # partial ccc_y operation qasm.append('rz({}) q[{}];\n'.format(numpy.pi / 2, qubit_pair_1[0])) qasm.append('rx({}) q[{}];\n'.format(theta, qubit_pair_1[0])) # + qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) # 0 1 qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('rx({}) q[{}];\n'.format(-theta, qubit_pair_1[0])) # - qasm.append('h q[{}];\n'.format(qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[1])) # 0 3 qasm.append('h q[{}];\n'.format(qubit_pair_2[1])) qasm.append('rx({}) q[{}];\n'.format(theta, qubit_pair_1[0])) # + qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) # 0 1 qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('rx({}) q[{}];\n'.format(-theta, qubit_pair_1[0])) # - qasm.append('h q[{}];\n'.format(qubit_pair_2[0])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[0])) # 0 2 qasm.append('h q[{}];\n'.format(qubit_pair_2[0])) qasm.append('rx({}) q[{}];\n'.format(theta, qubit_pair_1[0])) # + qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) # 0 1 qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('rx({}) q[{}];\n'.format(-theta, qubit_pair_1[0])) # - qasm.append('h q[{}];\n'.format(qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[1])) # 0 3 qasm.append('h q[{}];\n'.format(qubit_pair_2[1])) qasm.append('rx({}) q[{}];\n'.format(theta, qubit_pair_1[0])) # + qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_1[1])) # 0 1 qasm.append('h q[{}];\n'.format(qubit_pair_1[1])) qasm.append('rx({}) q[{}];\n'.format(-theta, qubit_pair_1[0])) # - qasm.append('rz({}) q[{}];\n'.format(-numpy.pi / 2, qubit_pair_1[0])) ##### test ##### # qasm.append('h q[{}];\n'.format(qubit_pair_2[0])) # qasm.append('cx q[{}], q[{}];\n'.format(qubit_pair_1[0], qubit_pair_2[0])) # 0 2 # qasm.append('h q[{}];\n'.format(qubit_pair_2[0])) # ############### # partial ccc_y operation ############ to here qasm.append( QasmUtils.controlled_xz(qubit_pair_1[0], qubit_pair_2[0], reverse=True)) # correct for parity determination qasm.append('x q[{}];\n'.format(qubit_pair_1[1])) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_1)) qasm.append('x q[{}];\n'.format(qubit_pair_2[1])) qasm.append('cx q[{}], q[{}];\n'.format(*qubit_pair_2)) return ''.join(qasm)
def get_qasm(self, var_parameters): assert len(var_parameters) == 1 return QasmUtils.eff_s_f_exc_qasm(var_parameters[0], self.qubits[0][0], self.qubits[1][0])