Beispiel #1
0
def load_and_encode(file_name: str,
                    problem_description_index: int = 0,
                    initial_state_label: str = None) -> JWEncodedData:
    """Wrapper function for loading and encoding Broombridge file into
    JWEncodedData-compatible format.

    :param file_name: Broombridge file name
    :type file_name: str
    :param problem_description_index: Index of problem description to use,
        defaults to 0
    :type problem_description_index: int, optional
    :param initial_state_label: Label of initial state to use, defaults to
        first available label
    :type initial_state_label: str, optional
    """
    broombridge_data = load_broombridge(file_name)
    problem = broombridge_data.problem_description[problem_description_index]

    if initial_state_label is None:
        # Pick first in list
        initial_state_label = problem.initial_state_suggestions[0].get("Label")
        _log.info(f"Using initial state label: {initial_state_label}")

    input_state = load_input_state(file_name, initial_state_label)
    ferm_hamiltonian = problem.load_fermion_hamiltonian()
    (num_qubits, hamiltonian_term_list, input_state_terms,
     energy_offset) = encode(ferm_hamiltonian, input_state)

    return (num_qubits, hamiltonian_term_list, input_state_terms,
            energy_offset)
Beispiel #2
0
def load_jw_encoded_data(filename: str):
    broombridge_data = load_broombridge(filename)
    problem_description = broombridge_data.problem_description[0]
    ferm_hamiltonian = problem_description.load_fermion_hamiltonian()
    input_state = load_input_state(filename, "UCCSD |G>")
    jw_encoded = encode(ferm_hamiltonian, input_state)

    return jw_encoded
def test_jw_encode():
    """
    Checks that we can encode a hamiltonian + input state
    """
    broombridge = qsharp.chemistry.load_broombridge("broombridge.yaml")

    fh1 = broombridge.problem_description[0].load_fermion_hamiltonian()
    is1 = broombridge.problem_description[0].load_input_state()

    jw = encode(fh1, is1)
    assert(len(jw) == 4)
Beispiel #4
0
    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 (OpenFermionParametricSolver.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.
        """
        # Import python packages for Microsoft Python interops
        import qsharp
        import qsharp.chemistry as qsharpchem

        assert(isinstance(ansatz, MicrosoftQSharpParametricSolver.Ansatze))
        self.ansatz = ansatz

        self.verbose = False

        # Initialize the number of samples to be used by the MicrosoftQSharp backend
        self.n_samples = 1e18

        # Initialize the amplitudes (parameters to be optimized)
        self.optimized_amplitudes = []

        # Obtain fragment info with PySCF
        # -----------------------------------------

        # Compute mean-field if not provided. Check that it has converged
        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

        if not mean_field.converged:
            warnings.warn("MicrosoftQSharpParametricSolver simulating with mean field not converged.",
                    RuntimeWarning)

        self.molecule = molecule
        self.mean_field = mean_field

        self.n_orbitals = len(mean_field.mo_energy)
        self.n_spin_orbitals = 2 * self.n_orbitals
        self.n_electrons = molecule.nelectron
        nuclear_repulsion = mean_field.energy_nuc()

        # Compute and set values of electronic integrals
        # ----------------------------------------------

        # Get data-structure to store problem description
        fd, path = tempfile.mkstemp(suffix='.yaml')
        try:
            # Write the dummp_0.2.yaml file to a temporary file
            with os.fdopen(fd, 'w') as tmp:
                tmp.write(_dummy_0_2_yaml)

            molecular_data = qsharpchem.load_broombridge(path)

            # Compute one and two-electron integrals, store them in the Microsoft data-structure
            integrals_one, integrals_two = compute_integrals_fragment(molecule, mean_field)
            molecular_data.problem_description[0].hamiltonian['OneElectronIntegrals']['Values'] = integrals_one
            molecular_data.problem_description[0].hamiltonian['TwoElectronIntegrals']['Values'] = integrals_two
            molecular_data.problem_description[0].coulomb_repulsion['Value'] = nuclear_repulsion

            # Compute and set values of UCCSD operators
            # -----------------------------------------

            # Generate UCCSD one- and two-body operators
            n_amplitudes = count_amplitudes(self.n_spin_orbitals, self.n_electrons)
            self.amplitude_dimension = n_amplitudes
            amplitudes = 0.01 * np.ones((n_amplitudes), dtype=np.float64)
            self.preferred_var_params = amplitudes
            ref,t = compute_cluster_operator(self.n_spin_orbitals, self.n_electrons, amplitudes)

            # Load a dummy inputstate object from the dummy Broombridge file, and set its values
            self.inputstate = qsharpchem.load_input_state(path, "UCCSD |G>")

            if self.verbose:
                print("inputstate energy :\n", self.inputstate.Energy)
                print("inputstate mcfdata :\n", self.inputstate.MCFData)
                print("inputstate method :\n", self.inputstate.Method)
                print("inputstate scfdata :\n", self.inputstate.SCFData)
                print("inputstate uccdata :\n", self.inputstate.UCCData, "\n\n\n")

            self.inputstate.UCCData['Reference'] = ref
            self.inputstate.UCCData['Excitations'] = t

            if self.verbose:
                print("inputstate :\n", self.inputstate.UCCData)
                print("------------\n")

            # Generate Fermionic and then qubit Hamiltonians
            # ----------------------------------------------

            # C# Chemistry library : Compute fermionic Hamiltonian
            self.ferm_hamiltonian = molecular_data.problem_description[0].load_fermion_hamiltonian()
            if self.verbose:
                print("ferm_hamiltonian:\n", self.ferm_hamiltonian.terms)
                print("------------\n")

            # C# Chemistry library : Compute the Pauli Hamiltonian using the Jordan-Wigner transform
            self.jw_hamiltonian = qsharpchem.encode(self.ferm_hamiltonian, self.inputstate)
            if self.verbose:
                print("jw_hamiltonian ::", self.jw_hamiltonian)
                print("------------\n")

            # Retrieve energy offset and number of qubits
            self.n_qubits = self.jw_hamiltonian[0]
            self.energy_offset = self.jw_hamiltonian[3]
        finally:
            # Cleanup the temp file
            os.remove(path)
Beispiel #5
0
    def get_rdm(self):
        """Obtain the RDMs from the optimized amplitudes.

        Obtain the RDMs from the optimized amplitudes by using the
        same function for energy evaluation.
        The RDMs are computed by using each fermionic Hamiltonian term,
        transforming them and computing the elements one-by-one.
        Note that the Hamiltonian coefficients will not be multiplied
        as in the energy evaluation.
        The first element of the Hamiltonian is the nuclear repulsion
        energy term, not the Hamiltonian term.

        Returns:
            (numpy.array, numpy.array): One & two-particle RDMs (rdm1_np & rdm2_np, float64).
        """
        import qsharp
        import qsharp.chemistry as qsharpchem

        amplitudes = self.optimized_amplitudes
        one_rdm = np.zeros((self.n_orbitals, self.n_orbitals))
        two_rdm = np.zeros((self.n_orbitals, self.n_orbitals, self.n_orbitals, self.n_orbitals))

        # Loop over all single fermionic hamiltonian term to get RDM values
        all_terms = self.ferm_hamiltonian.terms
        import copy
        fh_copy = copy.deepcopy(self.ferm_hamiltonian)

        for ii in all_terms:
            for jj in ii[1]:
                # Only use a single fermionic term, set its coefficient to 1.
                term_type = ii[0]
                jj = (jj[0], 1.0)
                single_fh = (term_type, [jj])

                fh_copy.terms = [single_fh]
                # Compute qubit Hamiltonian (C# Chemistry library)
                self.jw_hamiltonian = qsharpchem.encode(fh_copy, self.inputstate)

                # Compute RDM value
                RDM_value = self.simulate(amplitudes)

                # Update RDM matrices
                ferm_ops = single_fh[1][0][0][0]
                indices = [ferm_op[1] for ferm_op in ferm_ops]

                # 1-RDM matrix
                if (len(term_type) == 2):
                    i, j = indices[0]//2, indices[1]//2
                    if (i == j):
                        one_rdm[i, j] += RDM_value
                    else:
                        one_rdm[i, j] += RDM_value
                        one_rdm[j, i] += RDM_value

                # 2-RDM matrix (works with Microsoft Chemistry library sign convention)
                elif (len(term_type) == 4):
                    i, j, k, l = indices[0]//2, indices[1]//2, indices[2]//2, indices[3]//2

                    if((indices[0]==indices[3]) and (indices[1]==indices[2])):
                        if((indices[0]%2 == indices[2]%2) and (indices[1]%2 == indices[3]%2)):
                            two_rdm[i,l,j,k] += RDM_value
                            two_rdm[j,k,i,l] += RDM_value
                            two_rdm[i,k,j,l] -= RDM_value
                            two_rdm[j,l,i,k] -= RDM_value
                        else:
                            two_rdm[i,l,j,k] += RDM_value
                            two_rdm[j,k,i,l] += RDM_value
                    else:
                        if((indices[0]%2 == indices[3]%2) and (indices[1]%2 == indices[2]%2)):
                            two_rdm[i,l,j,k] += RDM_value
                            two_rdm[j,k,i,l] += RDM_value
                            two_rdm[l,i,k,j] += RDM_value
                            two_rdm[k,j,l,i] += RDM_value
                            if((indices[0]%2 == indices[2]%2) and (indices[1]%2 == indices[3]%2)):
                                two_rdm[i,k,j,l] -= RDM_value
                                two_rdm[j,l,i,k] -= RDM_value
                                two_rdm[k,i,l,j] -= RDM_value
                                two_rdm[l,j,k,i] -= RDM_value
                        else:
                            two_rdm[i,k,j,l] -= RDM_value
                            two_rdm[j,l,i,k] -= RDM_value
                            two_rdm[k,i,l,j] -= RDM_value
                            two_rdm[l,j,k,i] -= RDM_value

        return (one_rdm, two_rdm)
    "|E1>", index_convention=IndexConvention.HalfUp)
print("is2 ready.")
logging.info(is2)

####
# An end-to-end example of how to simulate H2:
####

# Reload to make sure the quantum.qs file is correctly compiled:
qsharp.reload()

# Import the Q# operation into Python:
from Microsoft.Quantum.Samples.Python import TrotterEstimateEnergy

# load the broombridge data for H2:
h2 = load_broombridge("h2.yaml")
problem = h2.problem_description[0]
fh = problem.load_fermion_hamiltonian()
input_state = problem.load_input_state()

# Once we have the hamiltonian and input state, we can call 'encode' to generate a Jordan-Wigner
# representation, suitable for quantum simulation:
qsharp_encoding = encode(fh, input_state)

# Simulate the Q# operation:
print('Starting simulation.')
result = TrotterEstimateEnergy.simulate(qSharpData=qsharp_encoding,
                                        nBitsPrecision=10,
                                        trotterStepSize=.4)
print(f'Trotter simulation complete. (phase, energy): {result}')