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, WeightedPauliOperator], 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, WeightedPauliOperator] = {} 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=aqua_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
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 print_UCCSD_parameters(molecule, core, var_form, algo_result, z2syms, sqlist, deleted_orbitals, outfile): sd, dd = UCCSD.compute_excitation_lists( [var_form._num_alpha, var_form._num_beta], var_form._num_orbitals, None, None, same_spin_doubles=var_form.same_spin_doubles, method_singles=var_form._method_singles, method_doubles=var_form._method_doubles, excitation_type=var_form._excitation_type) kept_orbitals = [ x for x in range(molecule.num_orbitals) if x not in deleted_orbitals ] ed = sd + dd results = parallel_map(UCCSD._build_hopping_operator, ed, task_args=(var_form._num_orbitals, [ var_form._num_alpha, var_form._num_beta ], core._qubit_mapping, core._two_qubit_reduction, z2syms), num_processes=aqua_globals.num_processes) def convert_index(idx): idx_converted = [] for i in idx: if (i < len(kept_orbitals)): idx_converted.append(str(kept_orbitals[i]) + 'u') else: idx_converted.append( str(kept_orbitals[i - len(kept_orbitals)]) + 'd') return idx_converted t = PrettyTable(['excitation', 'amplitude']) lst = [] im = 0 for m, (op, index) in enumerate(results): if op is not None and not op.is_empty(): lst.append( [convert_index(index), algo_result['optimal_point'][im]]) im += 1 for i in range(len(lst)): for j in range(i + 1, len(lst)): if (np.abs(lst[j][1]) > np.abs(lst[i][1])): lst[i], lst[j] = lst[j], lst[i] t.add_row([str(lst[i][0])] + [str(lst[i][1])]) outfile.write(str(t)) outfile.write("\n")
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 __init__(self, operator: LegacyBaseOperator, num_orbitals: int, num_particles: Union[List[int], int], qubit_mapping: Optional[str] = None, two_qubit_reduction: bool = False, active_occupied: Optional[List[int]] = None, active_unoccupied: Optional[List[int]] = None, is_eom_matrix_symmetric: bool = True, se_list: Optional[List[List[int]]] = None, de_list: Optional[List[List[int]]] = None, z2_symmetries: Optional[Z2Symmetries] = None, untapered_op: Optional[LegacyBaseOperator] = None) -> None: """Constructor. Args: operator: qubit operator num_orbitals: total number of spin orbitals num_particles: number of particles, if it is a list, the first number is alpha and the second number if beta. qubit_mapping: qubit mapping type two_qubit_reduction: two qubit reduction is applied or not active_occupied: list of occupied orbitals to include, indices are 0 to n where n is num particles // 2 active_unoccupied: list of unoccupied orbitals to include, indices are 0 to m where m is (num_orbitals - num particles) // 2 is_eom_matrix_symmetric: is EoM matrix symmetric se_list: single excitation list, overwrite the setting in active space de_list: double excitation list, overwrite the setting in active space z2_symmetries: represent the Z2 symmetries untapered_op: 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