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)
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_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)
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)
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()