# H₂ Molecule Homework Assignment

### Quantum Software Development Journey: From Theory to Application with Classiq - Part 3

• Similarly to what we have done in class, in this exercise we will implement the VQE on H2 molecule.

• This time instead of using the built-in methods and functions (such as Molecule and MoleculeProblem) to difne and solve the problem, you will be provided with a two qubits Hamiltonian.

## Submission

• Submit the completed Jupyter notebook and report via GitHub. Ensure all files are correctly named and organized.

• Use the Typeform link provided in the submission folder to confirm your submission.

## Important Dates

• Assignment Release: 22.5.2024

• Submission Deadline: 3.6.2024 (7 A.M GMT+3)

Happy coding and good luck!

### Part 1

Given the following Hamiltonian:

$\hat{H} = -1.0523 \cdot (I \otimes I) + 0.3979 \cdot (I \otimes Z) - 0.3979 \cdot (Z \otimes I) - 0.0112 \cdot (Z \otimes Z) + 0.1809 \cdot (X \otimes X)$

Complete the following code

from typing import List

from classiq import *

HAMILTONIAN = QConstant(
"HAMILTONIAN",
List[PauliTerm],  # [...]) #TODO: Complete Hamiltonian
[
PauliTerm([Pauli.I, Pauli.I], -1.0523),
PauliTerm([Pauli.I, Pauli.Z], 0.3979),
PauliTerm([Pauli.Z, Pauli.I], -0.3979),
PauliTerm([Pauli.Z, Pauli.Z], -0.0112),
PauliTerm([Pauli.X, Pauli.X], 0.1809),
],
)

@qfunc
def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:
# TODO: Create an ansatz which allows each qubit to have arbitrary rotation

allocate(2, q)
U(angles[0], angles[1], angles[2], 0, q[0])
U(angles[0], angles[1], angles[2], 0, q[1])

@cfunc
def cmain() -> None:
res = vqe(
HAMILTONIAN,  # .TODO: complete the missing argument
False,
[],
optimizer=Optimizer.COBYLA,
max_iteration=1000,
tolerance=0.001,
step_size=0,
skip_compute_variance=False,
alpha_cvar=1.0,
)
save({"result": res})

qmod = create_model(
main, classical_execution_function=cmain
)  # TODO: complete the line, use classical_execution_function
qprog = synthesize(qmod)
show(qprog)

Opening: https://platform.classiq.io/circuit/53712c40-3bc3-46d5-a5a4-fe4b3a2aa001?version=0.42.0

execution = execute(qprog)
res = execution.result()
# execution.open_in_ide()
vqe_result = res[0].value  # TODO: complete the line

print(f"Optimal energy: {vqe_result.energy}")
print(f"Optimal parameters: {vqe_result.optimal_parameters}")
print(f"Eigenstate: {vqe_result.eigenstate}")

Optimal energy: -1.06419619140625
Optimal parameters: {'angles_0': 6.111236674714585, 'angles_1': -0.887265255532695, 'angles_2': 3.112766526311032}
Eigenstate: {'01': (0.09110862335695782+0j), '10': (0.09110862335695782+0j), '00': (0.9916644782889019+0j)}


Does it similar to the optimal energy we calculated in class? \ Does it similar to the total energy we calculated in class?

### Part 2

Now, we want to have a more interesting ansatz in our main.
Add one line of code to the main function you created in Part 1 that creates entanglement between the two qubits.
Which gate should you use?

@qfunc
def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:
# TODO: Create an ansatz which allows each qubit to have arbitrary rotation

allocate(2, q)
U(angles[0], angles[1], angles[2], 0, q[0])
U(angles[0], angles[1], angles[2], 0, q[1])
CX(q[1], q[0])

@cfunc
def cmain() -> None:
res = vqe(
HAMILTONIAN,  # TODO: complete the missing argument
False,
[],
optimizer=Optimizer.COBYLA,
max_iteration=1000,
tolerance=0.001,
step_size=0,
skip_compute_variance=False,
alpha_cvar=1.0,
)
save({"result": res})

qmod = create_model(
main, classical_execution_function=cmain
)  # TODO: complete the line, use classical_execution_function
qprog = synthesize(qmod)
show(qprog)

Opening: https://platform.classiq.io/circuit/1d523274-b861-41f3-9ad1-62c8d76927de?version=0.42.0

execution = execute(qprog)
res = execution.result()
# execution.open_in_ide()
vqe_result = res[0].value  # TODO: complete the line

Opening in existing browser session.
Opening in existing browser session.

print(f"Optimal energy: {vqe_result.energy}")
print(f"Optimal parameters: {vqe_result.optimal_parameters}")
print(f"Eigenstate: {vqe_result.eigenstate}")

Optimal energy: -1.311106640625
Optimal parameters: {'angles_0': 5.243383358664046, 'angles_1': -0.362281429584872, 'angles_2': -3.9155584047002607}
Eigenstate: {'01': (0.4215855488510013+0j), '11': (0.4250459533979826+0j), '10': (0.2548360379734389+0j), '00': (0.7593814300139292+0j)}


Does it similar to the optimal energy we calculated in class? \ Does it similar to the total energy we calculated in class? \ What can we learn about the provided form this result Hamiltonian?