Skip to content

Commit

Permalink
Update tutorial 1 notebook
Browse files Browse the repository at this point in the history
For latest changes in Qibochem. Tutorial 2 currently in-progress
  • Loading branch information
chmwzc committed May 6, 2024
1 parent e5db921 commit b6b35d9
Showing 1 changed file with 81 additions and 55 deletions.
136 changes: 81 additions & 55 deletions tutorials/1-introduction-to-quantum-computing-in-chemistry.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
" - Exact energy < Approximate energy\n",
"- Define a loss function (electronic energy), and minimise it\n",
" - Combines classical and quantum computing:\n",
" - Classical: Optimizers and molecular integrals\n",
" - Quantum: Represent the electronic wave function\n",
" - Classical computer: Optimizers and molecular integrals\n",
" - Quantum computer: Represent the electronic wave function\n",
" - 2 main approaches (ansatz):\n",
" - Chemistry-based:\n",
" - Expensive, need to make cheaper\n",
Expand Down Expand Up @@ -282,9 +282,7 @@
"metadata": {},
"outputs": [],
"source": [
"from qibo import models, gates\n",
"\n",
"# from qibochem.measurement.expectation import pauli_expectation_shots, circuit_expectation_shots"
"from qibo import Circuit, gates"
]
},
{
Expand All @@ -297,7 +295,7 @@
"# Example: the 0.1777 Z0 term for H2\n",
"\n",
"# First, we build a basic quantum circuit with 4 (= number of spin-orbitals, nso) qubits\n",
"circuit = models.Circuit(h2.nso)\n",
"circuit = Circuit(h2.nso)\n",
"print(circuit.draw())"
]
},
Expand All @@ -314,43 +312,69 @@
{
"cell_type": "code",
"execution_count": null,
"id": "97f05c26-235e-4774-ba79-cded9d789eed",
"id": "a6ed22f1-fb25-4a2d-86a8-83ecaef9bddd",
"metadata": {},
"outputs": [],
"source": [
"from qibochem.measurement.expectation import expectation\n",
"circuit = Circuit(h2.nso)\n",
"circuit.add(gates.M(0)) # Add a measurement gate to measure the circuit result at the first qubit\n",
"\n",
"# Run the circuit\n",
"n_shots = 100\n",
"result = circuit(nshots=n_shots)\n",
"frequencies = result.frequencies(binary=True)\n",
"print(f\"Measurement result: {frequencies}\")"
]
},
{
"cell_type": "markdown",
"id": "93050394-488d-4044-b0cd-b9f5cd699736",
"metadata": {},
"source": [
"The measurement results are returned as a binary string. Since we only added one measurement gate, the result is a single digit: \"0\"\n",
"\n",
"---\n",
"\n",
"from qibochem.driver.hamiltonian import symbolic_hamiltonian"
"The (statistical) results of running the circuit can then be used to calculate the expectation value of the Z0 term in the Hamiltonian."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62060716",
"id": "611e6f58-0355-4a8d-8e81-caff7b37de5e",
"metadata": {},
"outputs": [],
"source": [
"circuit = models.Circuit(h2.nso)\n",
"# circuit = models.Circuit(1)\n",
"circuit.add(gates.M(0)) # Add a measurement gate to measure Z\n",
"print(circuit.draw())\n",
"\n",
"# Define the Z0 QubitOperator \n",
"z0_qubit_operator = openfermion.QubitOperator('Z0', 0.1777)\n",
"print(f\"\\nTerm: {z0_qubit_operator}\\n\")\n",
"from qibo.hamiltonians import SymbolicHamiltonian\n",
"from qibo.symbols import Z\n",
"\n",
"# The pauli_expectation_shots(circuit, nshots) helper function runs and measures the output of circuit nshots times\n",
"# Since we're looking at the Z0 term, there's no need to apply any basis rotation gates before measurement\n",
"z0_expectation_value = expectation(circuit, symbolic_hamiltonian(z0_qubit_operator), from_samples=True, n_shots=100)\n",
"# Define the Z0 term of the Hamiltonian\n",
"z0 = SymbolicHamiltonian(0.1777*Z(0), nqubits=h2.nso)\n",
"z0_expectation_value = z0.expectation_from_samples(frequencies)\n",
"print(f\"Expectation value: {z0_expectation_value}\")"
]
},
{
"cell_type": "markdown",
"id": "b7bbfb01",
"id": "ad375b17-fe2a-4d39-a620-598817dcd66e",
"metadata": {},
"source": [
"Note: pauli_expectation_shots just gives the measurement directly, which is just equal to 1.0 for a circuit with no gates applied"
"For convenience, Qibochem has its own `expectation_from_samples` function that is essentially the code in the the above cell"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d9ca2b75-8eb7-4ebc-9c19-1aad095498ab",
"metadata": {},
"outputs": [],
"source": [
"from qibochem.measurement import expectation_from_samples\n",
"\n",
"# We need to re-define the circuit because it has already been executed\n",
"circuit = Circuit(h2.nso)\n",
"z0_expectation_value = expectation_from_samples(circuit, z0)\n",
"print(f\"Expectation value: {z0_expectation_value}\")"
]
},
{
Expand All @@ -376,48 +400,43 @@
"metadata": {},
"outputs": [],
"source": [
"# The same 0.1777 Z0 term, using the circuit state vector:\n",
"# Note: We need to broadcast the SymbolicHamiltonian using I (I as in identity) terms to match 4 qubits\n",
"# We use qibo.symbols here because openfermion.QubitOperator doesn't have I\n",
"from qibo.symbols import I, Z\n",
"from qibo.hamiltonians import SymbolicHamiltonian\n",
"\n",
"# The broadcasted Z_0 term using qibo.symbol\n",
"z0_qubit_operator_broadcasted = 0.1777*Z(0)*I(1)*I(2)*I(3)\n",
"# Convert it to a Qibo SymbolicHamiltonian\n",
"z0_symbolic = SymbolicHamiltonian(z0_qubit_operator_broadcasted)\n",
"\n",
"# Build and run the simulated circuit to obtain its state vector\n",
"circuit = models.Circuit(h2.nso)\n",
"circuit = Circuit(h2.nso)\n",
"circuit_result = circuit(nshots=1)\n",
"circuit_state = circuit_result.state()\n",
"# Calculate the expectation value using the state vector\n",
"z0_expectation_value = z0_symbolic.expectation(circuit_state)\n",
"z0_expectation_value = z0.expectation(circuit_state)\n",
"\n",
"print(f\"Expectation value: {z0_expectation_value}\")"
]
},
{
"cell_type": "markdown",
"id": "1c8f233d-9463-401e-9485-2e31e98fda67",
"metadata": {},
"source": [
"Again, Qibochem has its own `expectation` function for convenience"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb2de81a",
"metadata": {},
"outputs": [],
"source": [
"# Note: Helper function in Molecule class for expectation values\n",
"# TODO: Might change in next version of Qibo (0.1.12)\n",
"from qibochem.measurement import expectation\n",
"\n",
"# Using the broadcasted SymbolicHamiltonian\n",
"circuit = models.Circuit(h2.nso)\n",
"print(f\"Expectation value: {expectation(circuit, z0_symbolic)}\")"
"circuit = Circuit(h2.nso)\n",
"print(f\"Expectation value: {expectation(circuit, z0)}\")"
]
},
{
"cell_type": "markdown",
"id": "7af310f7",
"metadata": {},
"source": [
"Going forward, we will just use the expectation value of the molecular Hamiltonian, obtained using the simulated state vector, for convenience."
"Going forward, we will just use the expectation value of the molecular Hamiltonian, obtained using the simulated state vector."
]
},
{
Expand All @@ -428,7 +447,7 @@
"outputs": [],
"source": [
"# Example: Electronic energy of the vacuum state\n",
"circuit = models.Circuit(h2.nso)\n",
"circuit = Circuit(h2.nso)\n",
"\n",
"# Get the molecular Hamiltonian, and convert it to a SymbolicHamiltonian\n",
"hamiltonian = h2.hamiltonian()\n",
Expand Down Expand Up @@ -461,7 +480,7 @@
"metadata": {},
"outputs": [],
"source": [
"from qibochem.ansatz.hardware_efficient import hea"
"from qibochem.ansatz import he_circuit"
]
},
{
Expand All @@ -471,7 +490,8 @@
"metadata": {},
"outputs": [],
"source": [
"help(hea)"
"# The documentation can be consulted if one is unclear on how to use any specific functionality in Qibochem\n",
"help(he_circuit)"
]
},
{
Expand All @@ -485,15 +505,21 @@
},
"outputs": [],
"source": [
"# Get the list of quantum gates representing the ansatz\n",
"gate_list = hea(n_layers=1, n_qubits=h2.nso, coupling_gates='CNOT') # 1 layer is sufficient\n",
"\n",
"# Build a quantum circuit and add the gates from gate_list to it\n",
"circuit = models.Circuit(h2.nso)\n",
"circuit.add(gate for gate in gate_list)\n",
"# Build a quantum circuit representing a hardware-efficient ansatz\n",
"circuit = he_circuit(n_qubits=h2.nso, n_layers=1, coupling_gates='CNOT') # 1 layer is sufficient\n",
"print(circuit.draw())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "691f2d89-d8fc-4a4f-95d7-9a3da02cc6ce",
"metadata": {},
"outputs": [],
"source": [
"from qibo.models import VQE"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -509,8 +535,8 @@
"n_param_gates = len(circuit.get_parameters())\n",
"\n",
"# Create the VQE model\n",
"symbolic_hamiltonian = h2.hamiltonian()\n",
"vqe = models.VQE(circuit, symbolic_hamiltonian)\n",
"hamiltonian = h2.hamiltonian()\n",
"vqe = VQE(circuit, hamiltonian)\n",
"\n",
"# Optimize starting from a random guess for the variational parameters\n",
"initial_parameters = np.random.uniform(0, 2*np.pi,\n",
Expand All @@ -530,7 +556,7 @@
"\n",
"print(f\"Classical HF energy: {h2.e_hf}\")\n",
"# Exact groundstate energy of H2 as a reference\n",
"print(f\"{' ':>5}Exact solution: {symbolic_hamiltonian.eigenvalues()[0]}\")"
"print(f\"{' ':>5}Exact solution: {hamiltonian.eigenvalues()[0]}\")"
]
},
{
Expand Down Expand Up @@ -562,7 +588,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
"version": "3.11.9"
}
},
"nbformat": 4,
Expand Down

0 comments on commit b6b35d9

Please sign in to comment.