def get_uccsd_circuit(molecule, theta_vector=None, use_basis_gates=False): """Produce the full UCCSD circuit. Args: molecule :: string - must be a key of MOLECULE_TO_INFO theta_vector :: array - arguments for the vqe ansatz. If None, will generate random angles. use_basis_gates :: bool - Mike and Ike gates if False, Basis gates if True. Returns: circuit :: qiskit.QuantumCircuit - the UCCSD circuit parameterized by theta_vector, unoptimized """ molecule_info = MOLECULE_TO_INFO[molecule] driver = PySCFDriver(atom=molecule_info.atomic_string, basis='sto3g') qmolecule = driver.run() hamiltonian = Hamiltonian( qubit_mapping=QubitMappingType.PARITY, two_qubit_reduction=True, freeze_core=True, orbital_reduction=molecule_info.orbital_reduction) energy_input = hamiltonian.run(qmolecule) qubit_op = energy_input.qubit_op num_spin_orbitals = hamiltonian.molecule_info['num_orbitals'] num_particles = hamiltonian.molecule_info['num_particles'] map_type = hamiltonian._qubit_mapping qubit_reduction = hamiltonian.molecule_info['two_qubit_reduction'] HF_state = HartreeFock(qubit_op.num_qubits, num_spin_orbitals, num_particles, map_type, qubit_reduction) var_form = UCCSD(qubit_op.num_qubits, depth=1, num_orbitals=num_spin_orbitals, num_particles=num_particles, active_occupied=molecule_info.active_occupied, active_unoccupied=molecule_info.active_unoccupied, initial_state=HF_state, qubit_mapping=map_type, two_qubit_reduction=qubit_reduction, num_time_slices=1) if theta_vector is None: theta_vector = [ np.random.rand() * 2 * np.pi for _ in range(var_form._num_parameters) ] circuit = var_form.construct_circuit(theta_vector, use_basis_gates=use_basis_gates) return circuit
def _compute_mp2(qmolecule, threshold): terms = {} mp2_delta = 0 num_particles = qmolecule.num_alpha + qmolecule.num_beta num_orbitals = qmolecule.num_orbitals ints = qmolecule.mo_eri_ints oe = qmolecule.orbital_energies # Orbital indexes given by this method are numbered according to the blocked spin ordering singles, doubles = UCCSD.compute_excitation_lists(num_particles, num_orbitals * 2, same_spin_doubles=True) # doubles is list of [from, to, from, to] in spin orbital indexing where alpha runs # from 0 to num_orbitals-1, and beta from num_orbitals to num_orbitals*2-1 for n in range(len(doubles)): idxs = doubles[n] i = idxs[0] % num_orbitals # Since spins are same drop to MO indexing j = idxs[2] % num_orbitals a = idxs[1] % num_orbitals b = idxs[3] % num_orbitals tiajb = ints[i, a, j, b] tibja = ints[i, b, j, a] num = (2 * tiajb - tibja) denom = oe[b] + oe[a] - oe[i] - oe[j] coeff = -num / denom coeff = coeff if abs(coeff) > threshold else 0 e_delta = coeff * tiajb e_delta = e_delta if abs(e_delta) > threshold else 0 terms[_list_to_str(idxs)] = (coeff, e_delta) mp2_delta += e_delta return terms, mp2_delta
def test_tapered_op(self): """ tapered op test """ tapered_ops = self.z2_symmetries.taper(self.qubit_op) smallest_idx = 0 # Prior knowledge of which tapered_op has ground state the_tapered_op = tapered_ops[smallest_idx] optimizer = SLSQP(maxiter=1000) init_state = HartreeFock(num_qubits=the_tapered_op.num_qubits, num_orbitals=self.core._molecule_info['num_orbitals'], qubit_mapping=self.core._qubit_mapping, two_qubit_reduction=self.core._two_qubit_reduction, num_particles=self.core._molecule_info['num_particles'], sq_list=the_tapered_op.z2_symmetries.sq_list) var_form = UCCSD(num_qubits=the_tapered_op.num_qubits, depth=1, num_orbitals=self.core._molecule_info['num_orbitals'], num_particles=self.core._molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=init_state, qubit_mapping=self.core._qubit_mapping, two_qubit_reduction=self.core._two_qubit_reduction, num_time_slices=1, z2_symmetries=the_tapered_op.z2_symmetries) algo = VQE(the_tapered_op, var_form, optimizer) backend = BasicAer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend=backend) algo_result = algo.run(quantum_instance) _, result = self.core.process_algorithm_result(algo_result) self.assertAlmostEqual(result['energy'], self.reference_energy, places=6)
def __init__(self, operator, num_orbitals, num_particles, qubit_mapping=None, two_qubit_reduction=False, active_occupied=None, active_unoccupied=None, is_eom_matrix_symmetric=True, se_list=None, de_list=None, z2_symmetries=None, untapered_op=None): """Constructor. Args: operator (WeightedPauliOperator): qubit operator num_orbitals (int): total number of spin orbitals num_particles (Union(list, int)): number of particles, if it is a list, the first number is alpha and the second number if beta. qubit_mapping (str): qubit mapping type two_qubit_reduction (bool): two qubit reduction is applied or not active_occupied (list): list of occupied orbitals to include, indices are 0 to n where n is num particles // 2 active_unoccupied (list): list of unoccupied orbitals to include, indices are 0 to m where m is (num_orbitals - num particles) // 2 is_eom_matrix_symmetric (bool): is EoM matrix symmetric se_list (list[list]): single excitation list, overwrite the setting in active space de_list (list[list]): double excitation list, overwrite the setting in active space z2_symmetries (Z2Symmetries): represent the Z2 symmetries untapered_op (WeightedPauliOperator): if the operator is tapered, we need untapered operator to build element of EoM matrix """ self._operator = operator self._num_orbitals = num_orbitals self._num_particles = num_particles self._qubit_mapping = qubit_mapping self._two_qubit_reduction = two_qubit_reduction self._active_occupied = active_occupied self._active_unoccupied = active_unoccupied se_list_default, de_list_default = UCCSD.compute_excitation_lists( self._num_particles, self._num_orbitals, self._active_occupied, self._active_unoccupied) if se_list is None: self._se_list = se_list_default else: self._se_list = se_list logger.info("Use user-specified single excitation list: %s", self._se_list) if de_list is None: self._de_list = de_list_default else: self._de_list = de_list logger.info("Use user-specified double excitation list: %s", self._de_list) self._z2_symmetries = z2_symmetries if z2_symmetries is not None \ else Z2Symmetries([], [], []) self._untapered_op = untapered_op if untapered_op is not None else operator self._is_eom_matrix_symmetric = is_eom_matrix_symmetric
def test_h2_one_qubit_statevector(self): """Test H2 with tapering and statevector backend.""" two_qubit_reduction = True qubit_mapping = 'parity' core = Hamiltonian(transformation=TransformationType.FULL, qubit_mapping=QubitMappingType.PARITY, two_qubit_reduction=two_qubit_reduction, freeze_core=False, orbital_reduction=[]) qubit_op, _ = core.run(self.molecule) num_orbitals = core.molecule_info['num_orbitals'] num_particles = core.molecule_info['num_particles'] # tapering z2_symmetries = Z2Symmetries.find_Z2_symmetries(qubit_op) # know the sector tapered_op = z2_symmetries.taper(qubit_op)[1] initial_state = HartreeFock(tapered_op.num_qubits, num_orbitals=num_orbitals, num_particles=num_particles, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction, sq_list=tapered_op.z2_symmetries.sq_list) var_form = UCCSD(num_qubits=tapered_op.num_qubits, depth=1, num_orbitals=num_orbitals, num_particles=num_particles, initial_state=initial_state, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction, z2_symmetries=tapered_op.z2_symmetries) optimizer = SPSA(max_trials=50) eom_vqe = QEomVQE(tapered_op, var_form, optimizer, num_orbitals=num_orbitals, num_particles=num_particles, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction, z2_symmetries=tapered_op.z2_symmetries, untapered_op=qubit_op) backend = BasicAer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend) result = eom_vqe.run(quantum_instance) np.testing.assert_array_almost_equal(self.reference, result['energies'], decimal=5)
def test_tapered_op(self): # set_qiskit_chemistry_logging(logging.DEBUG) tapered_ops = [] for coeff in itertools.product([1, -1], repeat=len(self.sq_list)): tapered_op = Operator.qubit_tapering(self.qubit_op, self.cliffords, self.sq_list, list(coeff)) tapered_ops.append((list(coeff), tapered_op)) smallest_idx = 0 # Prior knowledge of which tapered_op has ground state the_tapered_op = tapered_ops[smallest_idx][1] the_coeff = tapered_ops[smallest_idx][0] optimizer = SLSQP(maxiter=1000) init_state = HartreeFock( num_qubits=the_tapered_op.num_qubits, num_orbitals=self.core._molecule_info['num_orbitals'], qubit_mapping=self.core._qubit_mapping, two_qubit_reduction=self.core._two_qubit_reduction, num_particles=self.core._molecule_info['num_particles'], sq_list=self.sq_list) var_form = UCCSD( num_qubits=the_tapered_op.num_qubits, depth=1, num_orbitals=self.core._molecule_info['num_orbitals'], num_particles=self.core._molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=init_state, qubit_mapping=self.core._qubit_mapping, two_qubit_reduction=self.core._two_qubit_reduction, num_time_slices=1, cliffords=self.cliffords, sq_list=self.sq_list, tapering_values=the_coeff, symmetries=self.symmetries) algo = VQE(the_tapered_op, var_form, optimizer, 'matrix') backend = BasicAer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend=backend) algo_result = algo.run(quantum_instance) lines, result = self.core.process_algorithm_result(algo_result) self.assertAlmostEqual(result['energy'], self.reference_energy, places=6)
def test_h2_two_qubits_statevector(self): """Test H2 with parity mapping and statevector backend.""" two_qubit_reduction = True qubit_mapping = 'parity' core = Hamiltonian(transformation=TransformationType.FULL, qubit_mapping=QubitMappingType.PARITY, two_qubit_reduction=two_qubit_reduction, freeze_core=False, orbital_reduction=[]) qubit_op, _ = core.run(self.molecule) num_orbitals = core.molecule_info['num_orbitals'] num_particles = core.molecule_info['num_particles'] initial_state = HartreeFock(qubit_op.num_qubits, num_orbitals=num_orbitals, num_particles=num_particles, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction) var_form = UCCSD(num_qubits=qubit_op.num_qubits, depth=1, num_orbitals=num_orbitals, num_particles=num_particles, initial_state=initial_state, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction) optimizer = COBYLA(maxiter=1000) eom_vqe = QEomVQE(qubit_op, var_form, optimizer, num_orbitals=num_orbitals, num_particles=num_particles, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction) backend = BasicAer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend) result = eom_vqe.run(quantum_instance) np.testing.assert_array_almost_equal(self.reference, result['energies'], decimal=5)
backend = BasicAer.get_backend("statevector_simulator") distances = np.arange(0.5) exact_energies = [] vqe_energies = [] optimizer = SLSQP(maxiter=5) for dist in distances: qubitOp, num_particles, num_spin_orbitals, shift = get_qubit_op(dist) result = ExactEigensolver(qubitOp).run() exact_energies.append(result['energy'] + shift) initial_state = HartreeFock( qubitOp.num_qubits, num_spin_orbitals, num_particles, 'parity' ) var_form = UCCSD( qubitOp.num_qubits, depth=1, num_orbitals=num_spin_orbitals, num_particles=num_particles, initial_state=initial_state, qubit_mapping='parity' ) vqe = VQE(qubitOp, var_form, optimizer, 'matrix') results = vqe.run(backend)['energy'] + shift vqe_energies.append(results) print("Interatomic Distance:", np.round(dist, 2), "VQE Result:", results, "Exact Energy:", exact_energies[-1]) print("All energies have been calculated")
hamiltonian = algo_input[0] num_orbitals = core.molecule_info['num_orbitals'] num_particles = core.molecule_info['num_particles'] init_state = HartreeFock(hamiltonian.num_qubits, num_orbitals, num_particles, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction) depth = 1 var_form = UCCSD(hamiltonian.num_qubits, depth, num_orbitals, num_particles, initial_state=init_state, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction) optimizer = COBYLA(maxiter=5000) algo = VQE(hamiltonian, var_form, optimizer) results = algo.run(sv_simulator) print(results) energy = results['energy'] opt_params = results['opt_params'] ground_state = results['min_vector'] eom = QEquationOfMotion(hamiltonian,
num_particles) if qubit_reduction else qubitOp qubitOp.chop(10**-10) #print(qubitOp.print_operators()) print(qubitOp, flush=True) # setup HartreeFock state HF_state = HartreeFock(qubitOp.num_qubits, num_spin_orbitals, num_particles, map_type, qubit_reduction) # setup UCCSD variational form var_form = UCCSD(qubitOp.num_qubits, depth=1, num_orbitals=num_spin_orbitals, num_particles=num_particles, active_occupied=[0], active_unoccupied=[0, 1], initial_state=HF_state, qubit_mapping=map_type, two_qubit_reduction=qubit_reduction, num_time_slices=1) circuit = var_form.construct_circuit(parameters, use_basis_gates=False) print("Target circuit initialized.", flush=True) #circuit.draw(output='text', line_length=350) backend_sim = Aer.get_backend('unitary_simulator') result = qiskit.execute(circuit, backend_sim).result() U = result.get_unitary()
num_particles=molecule.num_alpha+molecule.num_beta map_type='jordan_wigner' ferOp = FermionicOperator(h1=molecule.one_body_integrals, h2=molecule.two_body_integrals) qubitOp = ferOp.mapping(map_type=map_type, threshold=0.00000001) exact_solution = ExactEigensolver(qubitOp).run()['energy'] exact_solution=exact_solution+repulsion_energy #optimizer = SLSQP(maxiter=5) optimizer = COBYLA(maxiter=opt_iter) HF_state=HartreeFock(qubitOp.num_qubits, num_spin_orbitals, num_particles, map_type) #var_form = RYRZ(qubitOp.num_qubits, depth=1, entanglement="linear") var_form = UCCSD(qubitOp.num_qubits, depth=1, num_orbitals=num_spin_orbitals, num_particles=num_particles, active_occupied=None, active_unoccupied=None, initial_state=HF_state, qubit_mapping='jordan_wigner', two_qubit_reduction=False, num_time_slices=1, shallow_circuit_concat=True, z2_symmetries=None) #No parallelization energies_exp_n=[] for n in range(experiments): t=time.time() #Without parallelisation n_shots=50 n_instances=1 instances=[] for i in range(n_instances): instances.append(QuantumInstance(backend=BasicAer.get_backend("qasm_simulator"), shots=n_shots)) if 'parameters_n_P' in locals():
orbital_reduction=[-3, -2]) qubit_op, aux_ops = operator.run(qmolecule) if algorithms[j] == 'ExactEigensolver': result = ExactEigensolver(qubit_op, aux_operators=aux_ops).run() optimizer = COBYLA(maxiter=1000) initial_state = HartreeFock( qubit_op.num_qubits, operator.molecule_info['num_orbitals'], operator.molecule_info['num_particles'], qubit_mapping=operator._qubit_mapping, two_qubit_reduction=operator._two_qubit_reduction) var_form = UCCSD(qubit_op.num_qubits, depth=1, num_orbitals=operator.molecule_info['num_orbitals'], num_particles=operator.molecule_info['num_particles'], initial_state=initial_state, qubit_mapping=operator._qubit_mapping, two_qubit_reduction=operator._two_qubit_reduction) algo = VQE(qubit_op, var_form, optimizer) result = algo.run( QuantumInstance(BasicAer.get_backend('statevector_simulator'))) lines, result = operator.process_algorithm_result(result) energies[j][i] = result['energy'] hf_energies[i] = result['hf_energy'] distances[i] = d pylab.plot(distances, hf_energies, label='Hartree-Fock')
def __init__(self, ansatz, molecule, mean_field=None, backend_options=None): """Initialize the settings for simulation. If the mean field is not provided it is automatically calculated. Args: ansatz (QiskitParametricSolver.Ansatze): Ansatz for the quantum solver. molecule (pyscf.gto.Mole): The molecule to simulate. mean_field (pyscf.scf.RHF): The mean field of the molecule. backend_options (dict): Extra parameters that control the behaviour of the solver. """ # Check the ansatz assert (isinstance(ansatz, QiskitParametricSolver.Ansatze)) self.ansatz = ansatz # Calculate the mean field if the user has not already done it. if not mean_field: mean_field = scf.RHF(molecule) mean_field.verbose = 0 mean_field.scf() if (mean_field.converged == False): orb_temp = mean_field.mo_coeff occ_temp = mean_field.mo_occ nr = scf.newton(mean_field) energy = nr.kernel(orb_temp, occ_temp) mean_field = nr # Check the convergence of the mean field if not mean_field.converged: warnings.warn( "QiskitParametricSolver simulating with mean field not converged.", RuntimeWarning) # Initialize molecule quantities # ------------------------------ self.num_orbitals = mean_field.mo_coeff.shape[0] self.num_spin_orbitals = self.num_orbitals * 2 self.num_particles = molecule.nelec[0] + molecule.nelec[1] self.nuclear_repulsion_energy = gto.mole.energy_nuc(molecule) # Build one body integrals in Qiskit format one_body_integrals_pyscf = mean_field.mo_coeff.T @ mean_field.get_hcore( ) @ mean_field.mo_coeff self.one_body_integrals = QMolecule.onee_to_spin( one_body_integrals_pyscf) # Build two body integrals in Qiskit format eri = ao2mo.incore.full(mean_field._eri, mean_field.mo_coeff, compact=False) eri2 = eri.reshape(tuple([self.num_orbitals] * 4)) self.two_body_integrals = QMolecule.twoe_to_spin(eri2) # Build Hamiltonians # ------------------ # Set the fermionic Hamiltonian self.f_hamiltonian = FermionicOperator(h1=self.one_body_integrals, h2=self.two_body_integrals) # Transform the fermionic Hamiltonian into qubit Hamiltonian self.map_type = 'jordan_wigner' self.qubit_hamiltonian = self.f_hamiltonian.mapping( map_type=self.map_type, threshold=1e-8) self.qubit_hamiltonian.chop(10**-10) self.n_qubits = self.qubit_hamiltonian.num_qubits # Qubits, mapping, backend backend_opt = ('statevector_simulator', 'matrix') # backend_opt = ('qasm_simulator', 'paulis') self.backend = Aer.get_backend(backend_opt[0]) self.backend_opt = backend_opt # Set ansatz and initial parameters # --------------------------------- # Define initial state self.init_state = HartreeFock(self.qubit_hamiltonian.num_qubits, self.num_spin_orbitals, self.num_particles, self.map_type, False) # No qubit reduction # Select ansatz, set the dimension of the amplitudes self.var_form = UCCSD(self.qubit_hamiltonian.num_qubits, depth=1, num_orbitals=self.num_spin_orbitals, num_particles=self.num_particles, initial_state=self.init_state, qubit_mapping=self.map_type, two_qubit_reduction=False, num_time_slices=1) self.amplitude_dimension = self.var_form._num_parameters self.optimized_amplitudes = []
print("The total ground state energy is: {:.12f}".format(ret['eigvals'][0].real + energy_shift + nuclear_repulsion_energy)) #from qiskit import IBMQ #from qiskit.providers.ibmq import least_busy #IBMQ.load_accounts() #large_enough_devices = IBMQ.backends(filters=lambda x: x.configuration().n_qubits > 4 and not x.configuration().simulator) #backend = least_busy(large_enough_devices) backend = Aer.get_backend('statevector_simulator') # setup COBYLA optimizer max_eval = 200 cobyla = COBYLA(maxiter=max_eval) # setup HartreeFock state HF_state = HartreeFock(qubitOp.num_qubits, num_spin_orbitals, num_particles, map_type, qubit_reduction) # setup UCCSD variational form var_form = UCCSD(qubitOp.num_qubits, depth=1, num_orbitals=num_spin_orbitals, num_particles=num_particles,active_occupied=[0], active_unoccupied=[0,1], initial_state=HF_state, qubit_mapping=map_type, two_qubit_reduction=qubit_reduction, num_time_slices=1) # setup VQE vqe = VQE(qubitOp, var_form, cobyla, 'matrix') quantum_instance = QuantumInstance(backend=backend) # Run algorithms and retrieve the results results = vqe.run(quantum_instance) print("The computed ground state energy is: {:.12f}".format(results['eigvals'][0])) print("Final energy: {:.12f}".format(results['eigvals'][0] + energy_shift + nuclear_repulsion_energy)) print("Parameters: {}".format(results['opt_params']))