from openfermion.chem import MolecularData
from openfermionpyscf import run_pyscf
from classiq.applications.chemistry.hartree_fock import get_hf_state
from classiq.applications.chemistry.op_utils import qubit_op_to_qmod
from classiq.applications.chemistry.problems import FermionHamiltonianProblem
from classiq.applications.chemistry.ucc import get_ucc_hamiltonians
from classiq.applications.chemistry.z2_symmetries import Z2SymTaperMapper
# create the molecule, insert the distance, prepare H, create UCC anzats and solve in energy
qmods = []
qprogs = []
results = []
durations = []
for x in distance:
time1 = time.time()
# Define a molecule
geometry = [("H", (0.0, 0.0, 0)), ("H", (0.0, 0.0, float(x)))]
molecule = MolecularData(geometry, basis="sto-3g", multiplicity=1, charge=0)
molecule = run_pyscf(
molecule,
run_mp2=True,
run_cisd=True,
run_ccsd=True,
run_fci=True, # relevant for small, classically solvable problems
)
# Define a problem and a mapper
problem = FermionHamiltonianProblem.from_molecule(molecule)
mapper = Z2SymTaperMapper.from_problem(problem)
# Construct a model
hf_state = get_hf_state(problem, mapper)
uccsd_hamiltonians = get_ucc_hamiltonians(problem, mapper, excitations=[1, 2])
num_params = len(uccsd_hamiltonians)
vqe_hamiltonian = qubit_op_to_qmod(mapper.map(problem.fermion_hamiltonian))
@qfunc
def main(params: CArray[CReal, num_params], state: Output[QArray]):
prepare_basis_state(hf_state, state)
multi_suzuki_trotter(uccsd_hamiltonians, params, 1, 1, state)
# Synthesize
qprog = synthesize(main)
qprog = set_quantum_program_execution_preferences(
qprog,
preferences=ExecutionPreferences(
num_shots=1000,
backend_preferences=ClassiqBackendPreferences(
backend_name="simulator_statevector"
),
),
)
qprogs.append(qprog)
# Execute
with ExecutionSession(qprog) as es:
result = es.minimize(
cost_function=vqe_hamiltonian,
initial_params={"params": [0] * num_params},
max_iteration=500,
)
VQE_energy.append(result[-1][0])
HF_energy.append(molecule.hf_energy)
exact_energy.append(molecule.fci_energy)
time2 = time.time()
duration = time2 - time1
durations.append(duration)
print(duration)