예제 #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)
예제 #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
예제 #3
0
def test_load_input_state():
    """
    Checks that loading an input state from file or from broombridge gives the same result.
    """
    broombridge = qsharp.chemistry.load_broombridge("broombridge.yaml")

    is1 = broombridge.problem_description[0].load_input_state("UCCSD |G>")
    is2 = load_input_state("broombridge.yaml", "UCCSD |G>")

    assert(is1.Method == "UnitaryCoupledCluster")
    assert(is1 == is2)
    
    is3 = broombridge.problem_description[0].load_input_state("UCCSD |G>", IndexConvention.HalfUp)
    is4 = load_input_state("broombridge.yaml", "UCCSD |G>", IndexConvention.HalfUp)

    assert(is3.Method == "UnitaryCoupledCluster")
    assert(is3 == is4)
    assert(is1 != is4)
예제 #4
0
def test_load_greedy_state():
    """
    Checks that not passing a wavefunction label generates the greedy input state.
    """
    broombridge = qsharp.chemistry.load_broombridge("broombridge.yaml")

    is1 = broombridge.problem_description[0].load_input_state("", IndexConvention.HalfUp)
    is2 = load_input_state("broombridge.yaml", "", IndexConvention.HalfUp)

    assert(is1.Method == "SparseMultiConfigurational")
    assert(is1 == is2)
예제 #5
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)
# optionally, load first the problem description from a Broombridge file, and from there
# load the fermion Hamiltonian from a problem description:
broombridge = load_broombridge("broombridge.yaml")
fh2 = broombridge.problem_description[0].load_fermion_hamiltonian()
print("fh2 ready.")
logging.info(fh2.terms)

# Here I show how to add a couple of completely made-up terms to the fh2 Hamiltonian:
terms = [([], 10.0), ([0, 6], 1.0), ([0, 2, 2, 0], 1.0)]
fh2.add_terms(terms)
print("terms added successfully")
logging.info(fh2)

# Similarly, you can load an input state either directly from a broombridge.yaml file,
is1 = load_input_state("broombridge.yaml", "|E1>")
print("is1 ready.")
logging.info(is1)

# or from the problem description:
is2 = broombridge.problem_description[0].load_input_state(
    "|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()