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 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 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 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 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_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])