def test_uccsd_adapt(self): """ UCCSD test for adaptive features """ self.var_form_base = UCCSD(self.num_spin_orbitals, self.num_particles, initial_state=self.init_state) self.var_form_base.manage_hopping_operators() # assert that the excitation pool exists self.assertIsNotNone(self.var_form_base.excitation_pool) # assert that the hopping ops list has been reset to be empty self.assertEqual(self.var_form_base._hopping_ops, [])
def test_uccsd_hf_excitations(self): """ uccsd tapering test using all double excitations """ # initial state init_state = HartreeFock( num_orbitals=self.fermionic_transformation.molecule_info['num_orbitals'], qubit_mapping=self.fermionic_transformation._qubit_mapping, two_qubit_reduction=self.fermionic_transformation._two_qubit_reduction, num_particles=self.fermionic_transformation.molecule_info['num_particles'], sq_list=self.fermionic_transformation.molecule_info['z2_symmetries'].sq_list) # check singlet excitations var_form = UCCSD( num_orbitals=self.fermionic_transformation.molecule_info['num_orbitals'], num_particles=self.fermionic_transformation.molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=init_state, qubit_mapping=self.fermionic_transformation._qubit_mapping, two_qubit_reduction=self.fermionic_transformation._two_qubit_reduction, num_time_slices=1, z2_symmetries=self.fermionic_transformation.molecule_info['z2_symmetries'], shallow_circuit_concat=False, method_doubles='succ', excitation_type='d', skip_commute_test=True) double_excitations_singlet = var_form._double_excitations res = TestUCCSDHartreeFock.excitation_lists_comparator( double_excitations_singlet, self.reference_singlet_double_excitations) self.assertEqual(res, True) # check grouped singlet excitations var_form = UCCSD( num_orbitals=self.fermionic_transformation.molecule_info['num_orbitals'], num_particles=self.fermionic_transformation.molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=init_state, qubit_mapping=self.fermionic_transformation._qubit_mapping, two_qubit_reduction=self.fermionic_transformation._two_qubit_reduction, num_time_slices=1, z2_symmetries=self.fermionic_transformation.molecule_info['z2_symmetries'], shallow_circuit_concat=False, method_doubles='succ_full', excitation_type='d', skip_commute_test=True) double_excitations_singlet_grouped = var_form._double_excitations_grouped res_groups = TestUCCSDHartreeFock.group_excitation_lists_comparator( double_excitations_singlet_grouped, self.reference_singlet_groups) self.assertEqual(res_groups, True)
def test_uccsd_hf_qpUCCD(self): """ paired uccd test """ optimizer = SLSQP(maxiter=100) initial_state = HartreeFock( self.fermionic_transformation.molecule_info['num_orbitals'], self.fermionic_transformation.molecule_info['num_particles'], qubit_mapping=self.fermionic_transformation._qubit_mapping, two_qubit_reduction=self.fermionic_transformation._two_qubit_reduction) var_form = UCCSD( num_orbitals=self.fermionic_transformation.molecule_info['num_orbitals'], num_particles=self.fermionic_transformation.molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=initial_state, qubit_mapping=self.fermionic_transformation._qubit_mapping, two_qubit_reduction=self.fermionic_transformation._two_qubit_reduction, num_time_slices=1, shallow_circuit_concat=False, method_doubles='pucc', excitation_type='d' ) solver = VQE(var_form=var_form, optimizer=optimizer, quantum_instance=QuantumInstance( backend=BasicAer.get_backend('statevector_simulator'))) gsc = GroundStateEigensolver(self.fermionic_transformation, solver) result = gsc.solve(self.driver) self.assertAlmostEqual(result.total_energies[0], self.reference_energy_pUCCD, places=6)
def setUp(self): super().setUp() self.skipTest("Skip test until refactored.") self.reference_energy = -1.1373060356951838 self.seed = 700 algorithm_globals.random_seed = self.seed self.driver = HDF5Driver(self.get_resource_path('test_driver_hdf5.hdf5', 'drivers/hdf5d')) fermionic_transformation = \ FermionicTransformation(qubit_mapping=FermionicQubitMappingType.PARITY, two_qubit_reduction=False) self.qubit_op, _ = fermionic_transformation.transform(self.driver) self.fermionic_transformation = fermionic_transformation self.optimizer = SLSQP(maxiter=100) initial_state = HartreeFock( fermionic_transformation.molecule_info['num_orbitals'], fermionic_transformation.molecule_info['num_particles'], qubit_mapping=fermionic_transformation._qubit_mapping, two_qubit_reduction=fermionic_transformation._two_qubit_reduction) self.var_form = UCCSD( num_orbitals=fermionic_transformation.molecule_info['num_orbitals'], num_particles=fermionic_transformation.molecule_info['num_particles'], initial_state=initial_state, qubit_mapping=fermionic_transformation._qubit_mapping, two_qubit_reduction=fermionic_transformation._two_qubit_reduction)
def get_solver(self, transformation): num_orbitals = transformation.molecule_info['num_orbitals'] num_particles = transformation.molecule_info['num_particles'] initial_state = HartreeFock(num_orbitals, num_particles) var_form = UCCSD(num_orbitals, num_particles, initial_state=initial_state) vqe = VQE(var_form=var_form, quantum_instance=self._quantum_instance, optimizer=L_BFGS_B()) return vqe
def test_uccsd_excitations(self, expected_result_idx, num_orbitals, num_particles, active_occupied=None, active_unoccupied=None, same_spin_doubles=True, method_singles='both', method_doubles='ucc', excitation_type='sd' ): """ Test generated excitation lists in conjunction with active space """ excitations = UCCSD.compute_excitation_lists( num_orbitals=num_orbitals, num_particles=num_particles, active_occ_list=active_occupied, active_unocc_list=active_unoccupied, same_spin_doubles=same_spin_doubles, method_singles=method_singles, method_doubles=method_doubles, excitation_type=excitation_type) self.assertListEqual(list(excitations), self.EXCITATION_RESULTS[expected_result_idx])
def test_uccsd_hf_qUCCSD(self): """ uccsd tapering test using all double excitations """ fermionic_transformation = FermionicTransformation( transformation=FermionicTransformationType.FULL, qubit_mapping=FermionicQubitMappingType.PARITY, two_qubit_reduction=True, freeze_core=True, orbital_reduction=[], z2symmetry_reduction='auto' ) qubit_op, _ = fermionic_transformation.transform(self.driver) # optimizer optimizer = SLSQP(maxiter=100) # initial state init_state = HartreeFock( num_orbitals=fermionic_transformation.molecule_info['num_orbitals'], qubit_mapping=fermionic_transformation._qubit_mapping, two_qubit_reduction=fermionic_transformation._two_qubit_reduction, num_particles=fermionic_transformation.molecule_info['num_particles'], sq_list=fermionic_transformation.molecule_info['z2_symmetries'].sq_list) var_form = UCCSD( num_orbitals=fermionic_transformation.molecule_info['num_orbitals'], num_particles=fermionic_transformation.molecule_info['num_particles'], active_occupied=None, active_unoccupied=None, initial_state=init_state, qubit_mapping=fermionic_transformation._qubit_mapping, two_qubit_reduction=fermionic_transformation._two_qubit_reduction, num_time_slices=1, z2_symmetries=fermionic_transformation.molecule_info['z2_symmetries'], shallow_circuit_concat=False, method_doubles='ucc', excitation_type='sd', skip_commute_test=True) solver = VQE(var_form=var_form, optimizer=optimizer, quantum_instance=QuantumInstance( backend=BasicAer.get_backend('statevector_simulator'))) raw_result = solver.compute_minimum_eigenvalue(qubit_op, None) result = fermionic_transformation.interpret(raw_result) self.assertAlmostEqual(result.total_energies[0], self.reference_energy_UCCSD, places=6)
def get_solver(self, transformation): num_orbitals = transformation.molecule_info['num_orbitals'] num_particles = transformation.molecule_info['num_particles'] qubit_mapping = transformation.qubit_mapping two_qubit_reduction = transformation.molecule_info[ 'two_qubit_reduction'] z2_symmetries = transformation.molecule_info['z2_symmetries'] initial_state = HartreeFock(num_orbitals, num_particles, qubit_mapping, two_qubit_reduction, z2_symmetries.sq_list) var_form = UCCSD(num_orbitals=num_orbitals, num_particles=num_particles, initial_state=initial_state, qubit_mapping=qubit_mapping, two_qubit_reduction=two_qubit_reduction, z2_symmetries=z2_symmetries) vqe = VQE(var_form=var_form, quantum_instance=self._quantum_instance, optimizer=L_BFGS_B()) return vqe
def _compute_mp2(qmolecule, threshold): terms = {} mp2_delta = 0 num_orbitals = qmolecule.num_orbitals ints = qmolecule.mo_eri_ints o_e = qmolecule.orbital_energies # Orbital indexes given by this method are numbered according to the blocked spin ordering _, doubles = UCCSD.compute_excitation_lists( [qmolecule.num_alpha, qmolecule.num_beta], 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 enumerate(doubles): idxs = doubles[n] i = idxs[0] % num_orbitals # Since spins are same drop to MO indexing j = idxs[2] % num_orbitals a_i = idxs[1] % num_orbitals b = idxs[3] % num_orbitals tiajb = ints[i, a_i, j, b] tibja = ints[i, b, j, a_i] num = (2 * tiajb - tibja) denom = o_e[b] + o_e[a_i] - o_e[i] - o_e[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 build_hopping_operators( self, excitations: Union[str, List[List[int]]] = 'sd' ) -> Tuple[Dict[str, PauliSumOp], Dict[str, List[bool]], Dict[str, List[Any]]]: """Builds the product of raising and lowering operators (basic excitation operators) Args: excitations: The excitations to be included in the eom pseudo-eigenvalue problem. If a string ('s', 'd' or 'sd') then all excitations of the given type will be used. Otherwise a list of custom excitations can directly be provided. Returns: A tuple containing the hopping operators, the types of commutativities and the excitation indices. """ num_alpha, num_beta = self._molecule_info['num_particles'] num_orbitals = self._molecule_info['num_orbitals'] if isinstance(excitations, str): se_list, de_list = UCCSD.compute_excitation_lists( [num_alpha, num_beta], num_orbitals, excitation_type=excitations) excitations_list = se_list + de_list else: excitations_list = excitations size = len(excitations_list) # # get all to-be-processed index # mus, nus = np.triu_indices(size) # build all hopping operators hopping_operators: Dict[str, PauliSumOp] = {} type_of_commutativities: Dict[str, List[bool]] = {} excitation_indices = {} to_be_executed_list = [] for idx in range(size): to_be_executed_list += [ excitations_list[idx], list(reversed(excitations_list[idx])) ] hopping_operators['E_{}'.format(idx)] = None hopping_operators['Edag_{}'.format(idx)] = None type_of_commutativities['E_{}'.format(idx)] = None type_of_commutativities['Edag_{}'.format(idx)] = None excitation_indices['E_{}'.format(idx)] = excitations_list[idx] excitation_indices['Edag_{}'.format(idx)] = list( reversed(excitations_list[idx])) result = parallel_map(self._build_single_hopping_operator, to_be_executed_list, task_args=(num_alpha + num_beta, num_orbitals, self._qubit_mapping, self._two_qubit_reduction, self._molecule_info['z2_symmetries']), num_processes=algorithm_globals.num_processes) for key, res in zip(hopping_operators.keys(), result): hopping_operators[key] = res[0] type_of_commutativities[key] = res[1] return hopping_operators, type_of_commutativities, excitation_indices
class TestAdaptVQEUCCSD(QiskitNatureTestCase): """ Test Adaptive VQE with UCCSD""" def setUp(self): super().setUp() # np.random.seed(50) self.seed = 50 algorithm_globals.random_seed = self.seed try: self.driver = PySCFDriver(atom='H .0 .0 .0; H .0 .0 0.735', unit=UnitsType.ANGSTROM, basis='sto3g') except QiskitNatureError: self.skipTest('PYSCF driver does not appear to be installed') return molecule = self.driver.run() self.num_particles = molecule.num_alpha + molecule.num_beta self.num_spin_orbitals = molecule.num_orbitals * 2 fer_op = FermionicOperator(h1=molecule.one_body_integrals, h2=molecule.two_body_integrals) map_type = 'PARITY' qubit_op = fer_op.mapping(map_type) self.qubit_op = TwoQubitReduction( num_particles=self.num_particles).convert(qubit_op) self.num_qubits = self.qubit_op.num_qubits self.init_state = HartreeFock(self.num_spin_orbitals, self.num_particles) self.var_form_base = None def test_uccsd_adapt(self): """ UCCSD test for adaptive features """ self.var_form_base = UCCSD(self.num_spin_orbitals, self.num_particles, initial_state=self.init_state) self.var_form_base.manage_hopping_operators() # assert that the excitation pool exists self.assertIsNotNone(self.var_form_base.excitation_pool) # assert that the hopping ops list has been reset to be empty self.assertEqual(self.var_form_base._hopping_ops, []) def test_vqe_adapt(self): """ AdaptVQE test """ try: # pylint: disable=import-outside-toplevel from qiskit import Aer backend = Aer.get_backend('statevector_simulator') except ImportError as ex: # pylint: disable=broad-except self.skipTest( "Aer doesn't appear to be installed. Error: '{}'".format( str(ex))) return class CustomFactory(VQEUCCSDFactory): """A custom MESFactory""" def get_solver(self, transformation): num_orbitals = transformation.molecule_info['num_orbitals'] num_particles = transformation.molecule_info['num_particles'] initial_state = HartreeFock(num_orbitals, num_particles) var_form = UCCSD(num_orbitals, num_particles, initial_state=initial_state) vqe = VQE(var_form=var_form, quantum_instance=self._quantum_instance, optimizer=L_BFGS_B()) return vqe algorithm = AdaptVQE(FermionicTransformation(), solver=CustomFactory(QuantumInstance(backend)), threshold=0.00001, delta=0.1, max_iterations=1) result = algorithm.solve(driver=self.driver) self.assertEqual(result.num_iterations, 1) self.assertEqual(result.finishing_criterion, 'Maximum number of iterations reached') algorithm = AdaptVQE(FermionicTransformation(), solver=CustomFactory(QuantumInstance(backend)), threshold=0.00001, delta=0.1) result = algorithm.solve(driver=self.driver) self.assertAlmostEqual(result.electronic_energies[0], -1.85727503, places=2) self.assertEqual(result.num_iterations, 2) self.assertAlmostEqual(result.final_max_gradient, 0.0, places=5) self.assertEqual(result.finishing_criterion, 'Threshold converged') def test_vqe_adapt_check_cyclicity(self): """ AdaptVQE index cycle detection """ param_list = [ ([1, 1], True), ([1, 11], False), ([11, 1], False), ([1, 12], False), ([12, 2], False), ([1, 1, 1], True), ([1, 2, 1], False), ([1, 2, 2], True), ([1, 2, 21], False), ([1, 12, 2], False), ([11, 1, 2], False), ([1, 2, 1, 1], True), ([1, 2, 1, 2], True), ([1, 2, 1, 21], False), ([11, 2, 1, 2], False), ([1, 11, 1, 111], False), ([11, 1, 111, 1], False), ([1, 2, 3, 1, 2, 3], True), ([1, 2, 3, 4, 1, 2, 3], False), ([11, 2, 3, 1, 2, 3], False), ([1, 2, 3, 1, 2, 31], False), ([1, 2, 3, 4, 1, 2, 3, 4], True), ([11, 2, 3, 4, 1, 2, 3, 4], False), ([1, 2, 3, 4, 1, 2, 3, 41], False), ([1, 2, 3, 4, 5, 1, 2, 3, 4], False), ] for seq, is_cycle in param_list: with self.subTest(msg="Checking index cyclicity in:", seq=seq): self.assertEqual(is_cycle, AdaptVQE._check_cyclicity(seq))