def make_h3_2_5() -> Tuple[RestrictedHartreeFockObjective, of.MolecularData,
                           np.ndarray, np.ndarray, np.ndarray]:
    # load the molecule from moelcular data
    h3_2_5_path = os.path.join(
        hfvqe.__path__[0],
        'molecular_data/hydrogen_chains/h_3_p_sto-3g/bond_distance_2.5')

    molfile = os.path.join(h3_2_5_path,
                           'H3_plus_sto-3g_singlet_linear_r-2.5.hdf5')
    molecule = of.MolecularData(filename=molfile)
    molecule.load()

    S = np.load(os.path.join(h3_2_5_path, 'overlap.npy'))
    Hcore = np.load(os.path.join(h3_2_5_path, 'h_core.npy'))
    TEI = np.load(os.path.join(h3_2_5_path, 'tei.npy'))

    _, X = sp.linalg.eigh(Hcore, S)
    obi = of.general_basis_change(Hcore, X, (1, 0))
    tbi = np.einsum('psqr', of.general_basis_change(TEI, X, (1, 0, 1, 0)))
    molecular_hamiltonian = generate_hamiltonian(obi, tbi,
                                                 molecule.nuclear_repulsion)

    rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian,
                                                   molecule.n_electrons)

    scipy_result = rhf_minimization(rhf_objective)
    return rhf_objective, molecule, scipy_result.x, obi, tbi
示例#2
0
def make_h3_2_5(molecular_data_directory=None) \
        -> Tuple[RestrictedHartreeFockObjective, of.MolecularData,
                 np.ndarray, np.ndarray, np.ndarray]:
    if molecular_data_directory is None:
        molecular_data_directory = _MOLECULAR_DATA_DIRECTORY

    h3_2_5_path = f'{molecular_data_directory}/hydrogen_chains/h_3_p_sto-3g/bond_distance_2.5'
    molfile = f'{h3_2_5_path}/H3_plus_sto-3g_singlet_linear_r-2.5.hdf5'
    molecule = of.MolecularData(filename=molfile)
    molecule.load()

    S = np.load(os.path.join(h3_2_5_path, 'overlap.npy'))
    Hcore = np.load(os.path.join(h3_2_5_path, 'h_core.npy'))
    TEI = np.load(os.path.join(h3_2_5_path, 'tei.npy'))

    _, X = sp.linalg.eigh(Hcore, S)
    obi = of.general_basis_change(Hcore, X, (1, 0))
    tbi = np.einsum('psqr', of.general_basis_change(TEI, X, (1, 0, 1, 0)))
    molecular_hamiltonian = generate_hamiltonian(obi, tbi,
                                                 molecule.nuclear_repulsion)

    rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian,
                                                   molecule.n_electrons)

    scipy_result = rhf_minimization(rhf_objective)
    return rhf_objective, molecule, scipy_result.x, obi, tbi
def make_rhf_objective(molecule: of.MolecularData):
    S, Hcore, TEI = get_ao_integrals(molecule)
    _, X = sp.linalg.eigh(Hcore, S)

    obi = of.general_basis_change(Hcore, X, (1, 0))
    tbi = np.einsum('psqr', of.general_basis_change(TEI, X, (1, 0, 1, 0)))
    molecular_hamiltonian = generate_hamiltonian(obi, tbi,
                                                 molecule.nuclear_repulsion)

    rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian,
                                                   molecule.n_electrons)
    return rhf_objective, S, Hcore, TEI, obi, tbi
示例#4
0
def make_rhf_objective(molecule):
    # coverage: ignore
    S, Hcore, TEI = get_ao_integrals(molecule)
    _, X = scipy.linalg.eigh(Hcore, S)

    molecular_hamiltonian = generate_hamiltonian(
        general_basis_change(Hcore, X, (1, 0)),
        numpy.einsum('psqr', general_basis_change(TEI, X, (1, 0, 1, 0)),
                     molecule.nuclear_repulsion))

    rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian,
                                                   molecule.n_electrons)
    return rhf_objective, S, Hcore, TEI
示例#5
0
def moving_frame_augmented_hessian_optimizer(
        rhf_objective: RestrictedHartreeFockObjective,
        initial_parameters: np.ndarray,
        opdm_aa_measurement_func: Callable,
        max_iter: Optional[int] = 15,
        rtol: Optional[float] = 0.2E-2,
        delta: Optional[float] = 0.03,
        verbose: Optional[bool] = True,
        hessian_update: Optional[bool] = 'diagonal'):  # testpragma: no cover
    # coverage: ignore
    """The moving frame optimizer.

    Determine an optimal basis rotation by continuously updating the
    coordinate system and asking if stationarity is achieved.

    Args:
        rhf_objective: recirq.hfvqe.RestrictedHartreeFockObjective
        initial_parameters: parameters to start the optimization
        opdm_aa_measurement_func: callable functioon that takes the parameter
            vector and returns the opdm
        max_iter: maximum number of iterations to take
        rtol: Terminate the optimization with the norm of the update angles
            falls below this threshold
        verbose: Allow printing of intermediate optimization information
        hessian_update: Optional argument if diagonal or full Hessian is used
    """
    if delta > 1 or delta < 0:
        raise ValueError("Delta must be in the domain [0, 1]")
    if hessian_update not in ['diagonal', 'energy']:
        raise ValueError("hessian_update parameter not valid.")

    res = OptimizeResult()
    res.fr_vals = []
    res.opdms = []
    res.x_iters = []
    res.func_vals = []
    res.f = None
    res.iter_times = []

    fr_vals = initial_parameters
    current_unitary = np.eye(rhf_objective.nocc + rhf_objective.nvirt)
    break_at_count = max_iter
    current_count = 0
    energies = []
    fval_norms = []
    # for debugging
    opdm_initial = np.diag([1] * rhf_objective.nocc +
                           [0] * rhf_objective.nvirt)
    start_time = time.time()
    while current_count < break_at_count:
        # Iterate of algorithm has a unitary and parameters
        # first step is to generate new unitary
        u_new = group_action(old_unitary=current_unitary,
                             new_parameters=fr_vals,
                             occ=rhf_objective.occ,
                             virt=rhf_objective.virt)

        # get initial opdm from starting parameters
        opdm = opdm_aa_measurement_func(u_new.copy())
        # opdm = u_new @ opdm_initial @ u_new.conj().T

        # Calculate energy, residual, and hessian terms
        rdms: InteractionRDM = rhf_objective.rdms_from_opdm_aa(opdm)
        current_energy: float = rdms.expectation(
            rhf_objective.hamiltonian).real
        energies.append(current_energy)

        res.x_iters.append(u_new)
        res.func_vals.append(current_energy)
        res.fr_vals.append(fr_vals)
        res.opdms.append(opdm)
        res.iter_times.append(time.time() - start_time)

        rot_gens = non_redundant_rotation_generators(rhf_objective)
        dvec, hmat = get_dvec_hmat(
            rotation_generators=rot_gens,
            rhf_objective=rhf_objective,
            rdms=rdms,
            diagonal_hessian=True if hessian_update == 'diagonal' else False)
        # talk if talking is allowed
        if verbose:
            print("\nITERATION NUMBER : ", current_count)
            print("\n unitary")
            print(current_unitary)
            test_opdm_aa = u_new @ opdm_initial @ u_new.conj().T
            true_energy = rhf_objective.energy_from_opdm(test_opdm_aa)
            print("Current Energy: ", current_energy)
            print("true energy ", true_energy)
            print("dvec")
            print(list(zip(dvec, rot_gens)))

        # build augmented Hessian
        dvec = dvec.reshape((-1, 1))
        aug_hess = np.hstack((np.array([[0]]), dvec.conj().T))
        aug_hess = np.vstack((aug_hess, np.hstack((dvec, hmat))))

        w, v = np.linalg.eig(aug_hess)
        sort_idx = np.argsort(w)
        w = w[sort_idx]
        v = v[:, sort_idx]
        new_fr_vals = v[1:, [0]].flatten() / v[0, 0]

        assert new_fr_vals.shape[0] == initial_parameters.shape[0]
        assert np.isclose(w[0], dvec.T @ new_fr_vals)

        # Qiming's algorithm for no learning rate rescaling
        if np.max(abs(new_fr_vals)) >= delta:
            new_fr_vals = delta * new_fr_vals / np.max(abs(new_fr_vals))

        # keep track of the norm
        fval_norms.append(np.linalg.norm(new_fr_vals))
        # allow a stopping condition
        if verbose:
            print("New fr values norm")
            print(np.linalg.norm(new_fr_vals))
        if np.linalg.norm(new_fr_vals) < rtol:
            if verbose:
                print("Finished Optimization")
            break

        # assign new values to the things being evaluated next iteration
        fr_vals = new_fr_vals.copy()
        current_unitary = u_new.copy()

        current_count += 1

    return res