{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Running on the Aer simulator \n", "=============================" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In this two-part tutorial, we demonstrate the process of executing a simple quantum chemical computation using 'shot' based sampling on noisy quantum emulators and hardware.\n", "\n", "Since this tutorial is focused on practical quantum computation, we will perform a straightforward calculation: the single-point evaluation of the total energy for the H2 molecule using the Unitary Coupled Cluster (UCC) ansatz, without optimization or parameter variance. \n", "\n", "In this first part of the tutorial, we take advantage of [pytket-qiskit](https://docs.quantinuum.com/tket/extensions/pytket-qiskit/) to run circuits on the AER simulator locally. For the second part we examine the use of a [Quantinuum hardware emulator](InQ_htut_qsys_H2.ipynb). The use of IBM hardware (and emulator) is also possible, but note that this requires an IBM Quantum account and the appropriate credentials to run on a machine with at least four qubits for a brief duration. Users with access to Quantinuum Nexus can add their [IBMQ credentials](https://docs.quantinuum.com/nexus/user_guide/credentials.html) and access IBMQ backends [via Nexus](https://docs.quantinuum.com/nexus/trainings/notebooks/basics/ibmq_examples.html).\n", "\n", "The outlined steps are as follows:\n", "\n", "Notebook 1\n", "\n", "- Define the system \n", "- Perform noise-free simulation (AerStateBackend)\n", "- Perform stochastic simulation (AerBackend)\n", "- Perform simulation with simple noisy simulation of the quantum computation (AerBackend + custom noise profile)\n", "\n", "Notebook 2\n", "\n", "- Redefine the system\n", "- Perform computation with emulated hardware noise (QuantinuumBackend emulator + machine noise profile)\n", "- Demonstrate error mitigation methods on emulated hardware (PMSV)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 0. System preparation\n", "To begin, we use the `express` module to load in the converged mean-field (Hartree-Fock) spin-orbitals, potential, and Hamiltonian from a calculation of H2 using the STO-3G basis set. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from inquanto.express import load_h5\n", "\n", "h2 = load_h5(\"h2_sto3g.h5\", as_tuple=True)\n", "hamiltonian = h2.hamiltonian_operator" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we prepare the Fermionic space and define the Fermionic state. \n", "\n", "The space here is defined with 4 spin-orbitals (which matches the full H2 STO-3G space) and we use the D2h point group.\n", "\n", "This point group is the most practical high symmetry group to approximate the $\\text{D} \\infty \\text{h}$ group. We also explicitly define the orbital symmetries.\n", "\n", "The state is then set by the ground state occupations [1,1,0,0] and the Hamiltonian encoded from the Hartree-Fock \n", "integrals. \n", "\n", "A space of excited states is then created using the UCCSD ansatz, which is then mapped to a quantum circuit using Jordan-Wigner (JW) encoding. InQuanto uses an efficient ansatz circuit compilation approach here, provided by the `FermionSpaceStateExpJWChemicallyAware` class, to reduce the computational resources required.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from inquanto.spaces import FermionSpace\n", "from inquanto.states import FermionState\n", "from inquanto.symmetry import PointGroup\n", "from inquanto.ansatzes import FermionSpaceStateExpChemicallyAware\n", "\n", "space = FermionSpace(\n", " 4, point_group=PointGroup(\"D2h\"), orb_irreps=[\"Ag\", \"Ag\", \"B1u\", \"B1u\"]\n", ")\n", "\n", "state = FermionState([1, 1, 0, 0])\n", "qubit_hamiltonian = hamiltonian.qubit_encode()\n", "\n", "exponents = space.construct_single_ucc_operators(state)\n", "## the above adds nothing due to the symmetry of the system\n", "exponents += space.construct_double_ucc_operators(state)\n", "ansatz = FermionSpaceStateExpChemicallyAware(exponents, state)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ansatz circuit structure is well-defined, but the guess for the wave function parameters (weights of the exponentiated determinants / angles of rotation gates) has not been established. These parameters are initialized with a single value denoted as 'p', detailed below. \n", "\n", "Once the parameters are defined, the `Computable` class is employed to specify the quantity of interest: we seek to evaluate the expectation value of the Hamiltonian for a given parameter value $\\theta$, $E=\\langle \\Psi(\\theta)|\\hat{H} |\\Psi(\\theta)\\rangle$.\n", "\n", "For demonstration purposes, we fix the random seed on the initialization of the parameters using `seed=6`, which should set a parameter value of 0.499675. Alternatively, this parameter can be set using `p = ansatz.state_symbols.construct_from_array([0.4996755931358105])`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{d0: 0.4996755931358105}\n" ] } ], "source": [ "# p = ansatz.state_symbols.construct_random(seed=6)\n", "p = ansatz.state_symbols.construct_from_array([0.4996755931358105])\n", "print(p)\n", "\n", "from inquanto.computables import ExpectationValue\n", "\n", "expectation0 = ExpectationValue(ansatz, hamiltonian.qubit_encode())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the circuit and parameters now established, it becomes possible to display and analyze the circuit. This particular circuit comprises 4 qubits and consists of 31 gates. Notably, among these gates, the multi-qubit CNOT gates, are expected to contribute the most noise. In this circuit, there are a total of 4 CNOT gates." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "