{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "A basic VQE simulation\n", "=======================" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This file will introduce the basic methodology of performing quantum chemistry calculations on quantum computers using InQuanto. We focus here on a practical guide for computation using InQuanto. A discussion of the theory of [VQE](https://docs.quantinuum.com/inquanto/manual/algorithms/algorithms_vqe.html) is available in the [InQuanto docs](https://docs.quantinuum.com/inquanto/). For this example, we will consider the calculation of the ground state electronic energy of the hydrogen molecule in a single geometric configuration, using a standard VQE methodology.\n", "\n", "The goal of any form of electronic structure calculation is to find the eigenvalues and eigenvectors (for the ground state, the lowest eigenvalue/vector) of the second quantized electronic Hamiltonian:\n", "\n", "$$\n", "\\hat{H} = \\sum_{i,j=0}^N {h_{ij} \\hat{a}^{\\dagger}_{i} \\hat{a}_j} + \\frac{1}{2}\\sum_{i,j,k,l = 0}^N {h_{ijkl} \\hat{a}^\\dagger_i \\hat{a}^\\dagger_j \\hat{a}_k \\hat{a}_l}\n", "$$\n", "\n", "where $N$ is the number of fermionic spin-orbitals, $\\hat{a}_i^\\dagger$ and $\\hat{a}_i$ are creation and annihilation operators acting on fermionic spin-orbitals, and $h_{ij}$ and $h_{ijkl}$ are classically precomputable integrals giving the strengths of the one and two electron interactions, respectively.\n", "\n", "In the figure below we show the computational steps required in a canonical VQE calculation. The initial five steps here are classical preprocessing steps, whereas the final step may utilize either an actual quantum device, or a classical simulator. In order to demonstrate the simulation process, we subdivide the overall algorithm here to demonstrate the various components of InQuanto. \n", "\n", "![](_images/inquanto_vqe_flow.png)\n", "\n", "In the cell below we start by specifying the molecular system, which here is $H_2$ in the minimal basis set - STO-3G. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ########################\n", "# MOLECULE SPECIFICATION #\n", "# ########################\n", "\n", "basis = \"sto-3g\"\n", "geometry = [[\"H\", [0, 0, 0]], [\"H\", [0, 0, 0.7122]]]\n", "charge = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As is the case of classical computational chemistry we specify the atomic orbital basis, the molecular geometry, and the system charge. In InQuanto these are obtained from a ``driver``, which runs classical electronic structure calculation to determine the reference molecular spin-orbitals and the $h_{ij}$ and $h_{ijkl}$ integrals in the electronic Hamiltonian (eq 1.). For example a user could run a Hartree-Fock calculation using Psi4, generate an FCIDump file, and use that to instantiate the system. However, [inquanto.extensions](https://docs.quantinuum.com/inquanto/extensions/extensions-overview.html)\n", "streamlines this process. \n", "\n", "Here we will utilize [inquanto-pyscf](https://docs.quantinuum.com/inquanto/extensions/inquanto-pyscf.html) which is an interface to the [PySCF](https://pyscf.org/) code. This code will steer PySCF calculations and collect the results necessary to build InQuanto objects (fermion operator, state, space). The choice of extension/driver will determine the availability of methods, basis sets, etc. Don't worry if you don't have [inquanto.extensions](https://docs.quantinuum.com/inquanto/extensions/extensions-overview.html) or [PySCF](https://pyscf.org/) - InQuanto provides some data for [small test systems](https://docs.quantinuum.com/inquanto/manual/express.html#list-of-express-files).\n", "\n", "In the cell below we use a restricted Hartree-Fock calculation to build our system, running a PySCF calculation using the `inquanto.extensions.pyscf.ChemistryDriverPySCFMolecularRHF` driver. Some useful parameters to the PySCF drivers are `frozen` (to specify frozen spatial atomic orbitals) and `point_group_symmetry` (to enable the use of point group symmetry to reduce computational cost). " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "HARTREE FOCK ENERGY: -1.1175058842043315\n", "\n" ] } ], "source": [ "# ######################### #\n", "# PRELIMINARY CALCULATIONS #\n", "# ######################### #\n", "from inquanto.extensions.pyscf import ChemistryDriverPySCFMolecularRHF\n", "\n", "driver = ChemistryDriverPySCFMolecularRHF(basis=basis, geometry=geometry, charge=charge)\n", "chemistry_hamiltonian, fock_space, hartree_fock_state = driver.get_system()\n", "hartree_fock_energy = driver.mf_energy\n", "\n", "print('HARTREE FOCK ENERGY: {}\\n'.format(hartree_fock_energy))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `inquanto.extensions.pyscf.ChemistryDriverPySCFMolecularRHF.get_system` method uses PySCF to run the restricted Hartree-Fock calculation, returning the integrals in the electronic Hamiltonian as a `inquanto.operators.ChemistryRestrictedIntegralOperator`, a `inquanto.spaces.FermionSpace` object describing the fermionic Fock space, and the Hartree-Fock fermionic reference state. \n", "\n", "In the cell below, we show how the `inquanto.operators.ChemistryRestrictedIntegralOperator`, which internally stores the $h_{ij}$ and $h_{ijkl}$ integrals, can be converted to a `inquanto.operators.FermionOperator` that represents the electronic Hamiltonian as a sum of terms. These terms can be viewed in a data frame table or printed. The `inquanto.operators.FermionOperator` contains a description of both the molecular orbital integrals, and the fermionic creation and annihilation operators. As shown in the snippet above, we can also extract the Hartree-Fock energy from the driver - this gives us an upper bound as to the electronic ground-state energy (no electron correlation). " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SECOND QUANTIZED HAMILTONIAN PRINTED:\n", "(0.7430177069924179, ), (-1.2702927243904387, F0^ F0 ), (-0.45680735030941, F2^ F2 ), (-1.2702927243904387, F1^ F1 ), (-0.45680735030941, F3^ F3 ), (-0.4889085974504731, F2^ F0^ F2 F0 ), (-0.4889085974504731, F3^ F1^ F3 F1 ), (-0.680061857584128, F1^ F0^ F1 F0 ), (-0.1796686795630159, F1^ F0^ F3 F2 ), (0.179668679563016, F3^ F0^ F2 F1 ), (-0.17966867956301572, F3^ F2^ F1 F0 ), (-0.6685772770134891, F3^ F0^ F3 F0 ), (-0.702813533276279, F3^ F2^ F3 F2 ), (0.179668679563016, F2^ F1^ F3 F0 ), (-0.6685772770134891, F2^ F1^ F2 F1 )\n", "\n", "SECOND QUANTIZED HAMILTONIAN AS DATAFRAME:\n" ] }, { "data": { "application/vnd.microsoft.datawrangler.viewer.v0+json": { "columns": [ { "name": "index", "rawType": "int64", "type": "integer" }, { "name": "Coefficient", "rawType": "float64", "type": "float" }, { "name": "Term", "rawType": "object", "type": "string" }, { "name": "Coefficient type", "rawType": "object", "type": "unknown" } ], "ref": "da4a39f1-d4d2-4b1b-8b05-a572ee06515c", "rows": [ [ "0", "0.7430177069924179", "", "" ], [ "1", "-1.2702927243904387", "F0^ F0 ", "" ], [ "2", "-0.680061857584128", "F1^ F0^ F1 F0 ", "" ], [ "3", "-0.1796686795630159", "F1^ F0^ F3 F2 ", "" ], [ "4", "-1.2702927243904387", "F1^ F1 ", "" ], [ "5", "-0.4889085974504731", "F2^ F0^ F2 F0 ", "" ], [ "6", "-0.6685772770134891", "F2^ F1^ F2 F1 ", "" ], [ "7", "0.179668679563016", "F2^ F1^ F3 F0 ", "" ], [ "8", "-0.45680735030941", "F2^ F2 ", "" ], [ "9", "0.179668679563016", "F3^ F0^ F2 F1 ", "" ], [ "10", "-0.6685772770134891", "F3^ F0^ F3 F0 ", "" ], [ "11", "-0.4889085974504731", "F3^ F1^ F3 F1 ", "" ], [ "12", "-0.17966867956301572", "F3^ F2^ F1 F0 ", "" ], [ "13", "-0.702813533276279", "F3^ F2^ F3 F2 ", "" ], [ "14", "-0.45680735030941", "F3^ F3 ", "" ] ], "shape": { "columns": 3, "rows": 15 } }, "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
CoefficientTermCoefficient type
00.743018<class 'numpy.float64'>
1-1.270293F0^ F0<class 'numpy.float64'>
2-0.680062F1^ F0^ F1 F0<class 'numpy.float64'>
3-0.179669F1^ F0^ F3 F2<class 'numpy.float64'>
4-1.270293F1^ F1<class 'numpy.float64'>
5-0.488909F2^ F0^ F2 F0<class 'numpy.float64'>
6-0.668577F2^ F1^ F2 F1<class 'numpy.float64'>
70.179669F2^ F1^ F3 F0<class 'numpy.float64'>
8-0.456807F2^ F2<class 'numpy.float64'>
90.179669F3^ F0^ F2 F1<class 'numpy.float64'>
10-0.668577F3^ F0^ F3 F0<class 'numpy.float64'>
11-0.488909F3^ F1^ F3 F1<class 'numpy.float64'>
12-0.179669F3^ F2^ F1 F0<class 'numpy.float64'>
13-0.702814F3^ F2^ F3 F2<class 'numpy.float64'>
14-0.456807F3^ F3<class 'numpy.float64'>
\n", "
" ], "text/plain": [ " Coefficient Term Coefficient type\n", "0 0.743018 \n", "1 -1.270293 F0^ F0 \n", "2 -0.680062 F1^ F0^ F1 F0 \n", "3 -0.179669 F1^ F0^ F3 F2 \n", "4 -1.270293 F1^ F1 \n", "5 -0.488909 F2^ F0^ F2 F0 \n", "6 -0.668577 F2^ F1^ F2 F1 \n", "7 0.179669 F2^ F1^ F3 F0 \n", "8 -0.456807 F2^ F2 \n", "9 0.179669 F3^ F0^ F2 F1 \n", "10 -0.668577 F3^ F0^ F3 F0 \n", "11 -0.488909 F3^ F1^ F3 F1 \n", "12 -0.179669 F3^ F2^ F1 F0 \n", "13 -0.702814 F3^ F2^ F3 F2 \n", "14 -0.456807 F3^ F3 " ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fermionic_hamiltonian = chemistry_hamiltonian.to_FermionOperator()\n", "\n", "print('SECOND QUANTIZED HAMILTONIAN PRINTED:\\n{}\\n'.format(fermionic_hamiltonian))\n", "print('SECOND QUANTIZED HAMILTONIAN AS DATAFRAME:')\n", "fermionic_hamiltonian.df()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `fock_space` and `hartree_fock_state` can be also printed to inspect which orbitals or spin-orbitals are occupied." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "FOCK SPACE AND THE HARTREE-FOCK STATE OCCUPATIONS:\n", " 0 0a : 1 \n", " 1 0b : 1 \n", " 2 1a : 0 \n", " 3 1b : 0 \n" ] } ], "source": [ "print('FOCK SPACE AND THE HARTREE-FOCK STATE OCCUPATIONS:')\n", "fock_space.print_state(hartree_fock_state)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As mentioned above, InQuanto also provides a set of [small test systems](https://docs.quantinuum.com/inquanto/manual/express.html#list-of-express-files) for where use of a full extension is undesirable. We access these using the [inquanto.express](https://docs.quantinuum.com/inquanto/manual/express.html) module. In the cell below we repeat the above example which used [inquanto-pyscf](https://docs.quantinuum.com/inquanto/extensions/inquanto-pyscf.html), but instead of running the Hartree-Fock we load in the precomputed data from express." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SECOND QUANTIZED HAMILTONIAN:\n", "(0.7430177069924179, ), (-1.270292724390438, F0^ F0 ), (-0.45680735030941033, F2^ F2 ), (-1.270292724390438, F1^ F1 ), (-0.45680735030941033, F3^ F3 ), (-0.48890859745047305, F2^ F0^ F2 F0 ), (-0.48890859745047305, F3^ F1^ F3 F1 ), (-0.6800618575841273, F1^ F0^ F1 F0 ), (-0.1796686795630157, F1^ F0^ F3 F2 ), (0.17966867956301563, F3^ F0^ F2 F1 ), (-0.1796686795630155, F3^ F2^ F1 F0 ), (-0.6685772770134887, F3^ F0^ F3 F0 ), (-0.7028135332762804, F3^ F2^ F3 F2 ), (0.17966867956301563, F2^ F1^ F3 F0 ), (-0.6685772770134887, F2^ F1^ F2 F1 )\n", "\n", "HARTREE FOCK ENERGY: -1.1175058842043306\n", "\n", "FOCK SPACE AND THE HARTREE-FOCK STATE OCCUPATIONS:\n", " 0 0a : 1 \n", " 1 0b : 1 \n", " 2 1a : 0 \n", " 3 1b : 0 \n" ] } ], "source": [ "from inquanto.express import load_h5\n", "from inquanto.spaces import FermionSpace\n", "from inquanto.states import FermionState\n", "h2_sto3g_data = load_h5('h2_sto3g.h5')\n", "\n", "integrals = h2_sto3g_data['hamiltonian_operator']\n", "fermionic_hamiltonian = integrals.to_FermionOperator()\n", "\n", "hartree_fock_energy = h2_sto3g_data['energy_hf']\n", "num_electrons = h2_sto3g_data['n_electron']\n", "num_spin_orbitals = h2_sto3g_data['n_orbital'] * 2\n", "\n", "\n", "\n", "fock_space = FermionSpace(num_spin_orbitals)\n", "hartree_fock_state = FermionState([1] * num_electrons + [0] * (num_spin_orbitals-num_electrons))\n", "\n", "print('SECOND QUANTIZED HAMILTONIAN:\\n{}\\n'.format(fermionic_hamiltonian))\n", "print('HARTREE FOCK ENERGY: {}\\n'.format(hartree_fock_energy))\n", "print('FOCK SPACE AND THE HARTREE-FOCK STATE OCCUPATIONS:')\n", "fock_space.print_state(hartree_fock_state)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now have our data gathered directly from [inquanto.express](https://docs.quantinuum.com/inquanto/manual/express.html#list-of-express-files) instead of via an external quantum chemistry package. Note that here we needed to manually create `FermionSpace` and `FermionState` objects instead of deriving them from an external driver. The [inquanto.express](https://docs.quantinuum.com/inquanto/manual/express.html#list-of-express-files) also stores the integrals as a `ChemistryRestrictedIntegralOperator` which we need to transform to `FermionOperator`.\n", "\n", "Having found the fermionic Hamiltonian, we now must transform it into a form implementable on a quantum computer. As [discussed in the documentation](https://docs.quantinuum.com/inquanto/manual/spaces.html#fermion-to-qubit-mapping), the fermionic creation and annihilation operators must be mapped to strings of Pauli operators. In this example, we use the Jordan-Wigner transformation for this purpose." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "QUBIT HAMILTONIAN:\n", "(-0.05962058276034765, ), (0.1757594291831968, Z0), (0.17575942918319679, Z1), (0.17001546439603182, Z0 Z1), (0.044917169890753894, X0 Y1 Y2 X3), (-0.044917169890753894, X0 X1 Y2 Y3), (-0.044917169890753894, Y0 Y1 X2 X3), (0.044917169890753894, Y0 X1 X2 Y3), (-0.23667117678035537, Z2), (0.12222714936261826, Z0 Z2), (0.16714431925337217, Z1 Z2), (-0.23667117678035543, Z3), (0.16714431925337217, Z0 Z3), (0.12222714936261826, Z1 Z3), (0.1757033833190701, Z2 Z3)\n" ] } ], "source": [ "# ######################### #\n", "# QUBIT MAPPING HAMILTONIAN #\n", "# ######################### #\n", "\n", "from inquanto.mappings import QubitMappingJordanWigner\n", "\n", "jw_map = QubitMappingJordanWigner()\n", "qubit_hamiltonian = jw_map.operator_map(fermionic_hamiltonian)\n", "print('QUBIT HAMILTONIAN:\\n{}'.format(qubit_hamiltonian))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Here, we use the `inquanto.mappings.QubitMappingJordanWigner` class to perform the mapping, yielding a qubit Hamiltonian as a weighted sum of strings of Pauli X, Y and Z operators acting on qubits. The [inquanto.mappings](https://docs.quantinuum.com/inquanto/api/inquanto/mappings.html) module contains several fermion-qubit mappings, which all utilize the `.operator_map()` method to map fermionic `FermionOperator`s to InQuanto `QubitOperator`s. This qubit Hamiltonian will be used to calculate the ground state energy by determining the expectation value of each term in the sum. While the Hamiltonian alone is sufficient for some quantum algorithms (e.g. phase estimation), here we consider a VQE calculation where the preparation of an [ansatz](https://docs.quantinuum.com/inquanto/manual/ansatzae_overview.html) state is required.\n", "\n", "In the cell below, we use the canonical UCCSD Ansatz -- `inquanto.ansatz.FermionSpaceAnsatzUCCSD`. When instantiated, the Ansatz object contains a tket circuit object corresponding to the generation of the parameterized Ansatz state. We can use the `.generate_report()` and `circuit_resources()` methods of the Ansatz object to give a quick indication of some of the quantum resource costs associated with generating the Ansatz -- the number of Ansatz parameters, the number of qubits required, and the 2-qubit gate count. For more in-depth diagnostics, the user can examine the tket circuit object itself using `ansatz.state_circuit`. Further information about how to analyze tket circuits can be found in the [tket documentation](https://docs.quantinuum.com/tket/user-guide/manual/manual_circuit.html#analysing-circuits). \n", "\n", "Two final steps are needed before a VQE simulation can be run - determining how the quantum computer itself will be simulated and setting up the classical optimizer." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ANSATZ REPORT:\n", "{'n_parameters': 3, 'n_qubits': 4}\n", "\n", " 2-qubit GATES: 64\n", "\n", " ANSATZ GENERATION CIRCUIT:\n" ] }, { "data": { "text/plain": [ "[X q[0]; X q[1]; [ansatz_commuting_block] CircBox q[0], q[1], q[2], q[3]; [ansatz_commuting_block] CircBox q[0], q[1], q[2], q[3]; [ansatz_commuting_block] CircBox q[0], q[1], q[2], q[3]; ]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\n", "# ##################### #\n", "# CREATE A UCCSD ANSATZ #\n", "# ##################### #\n", "\n", "from inquanto.ansatzes import FermionSpaceAnsatzUCCSD\n", "from pytket import Circuit, OpType\n", "\n", "ansatz = FermionSpaceAnsatzUCCSD(fock_space, hartree_fock_state)\n", "print('ANSATZ REPORT:')\n", "print(ansatz.generate_report())\n", "print('\\n 2-qubit GATES: {}'.format(ansatz.circuit_resources()['gates_2q']))\n", "print(\"\\n ANSATZ GENERATION CIRCUIT:\")\n", "ansatz.state_circuit\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To simulate the quantum computer, we connect to a backend using a [pytket extension](https://docs.quantinuum.com/tket/api-docs/extensions.html). The backends are where the quantum circuit is run or simulated. In this case, we are using the [Qiskit](https://qiskit.org/) state vector simulator through the use of `pytket.extensions.qiskit`.\n", "\n", "There are two broad approaches to simulating the action of a quantum circuit which differ in how measurement is treated. Firstly, the full state of the qubits may be tracked and returned as a vector of complex amplitudes -- *state vector* simulation. Alternatively, we can build up the probability distribution of states through repeated measurement of the qubit register -- *shot based* simulation. This latter approach is a more faithful simulation of how current quantum computation is performed, but requires many repetitions to obtain accurate statistics of the desired quantity. The type of simulator influences how InQuanto handles the result returned by the backend. The Qiskit `AerStateBackend` here performs a state vector simulation.\n", "\n", "Finally, we also need to choose how the classical optimization of Ansatz parameters is performed. This functionality is provided by the [inquanto.minimizers](https://docs.quantinuum.com/inquanto/api/inquanto/minimizers.html#module-inquanto.minimizers) module. In this case, we use [Scipy](https://www.scipy.org) to perform the minimization, which is interfaced through `inquanto.minimizers.scipy`. The choice of optimization algorithm and the settings can be passed through to Scipy. Here, we have requested an `L-BFGS-B` optimizer. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ############################### #\n", "# SIMULATOR AND OPTIMIZER DETAILS #\n", "# ############################### #\n", "\n", "# install pytket-qiskit using e.g. pip install pytket-qiskit if necessary\n", "\n", "\n", "from pytket.extensions.qiskit import AerStateBackend\n", "from inquanto.minimizers import MinimizerScipy\n", "\n", "backend = AerStateBackend()\n", "minimizer = MinimizerScipy(method=\"L-BFGS-B\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To make the first VQE simulation simple we use the `run_vqe()` function from the `inquanto.express` that is suitable to run with [Qiskit](https://qiskit.org/) state vector simulator. In order to perform much more customized VQE experiments, it is recommended to use `AlgorithmVQE` and the corresponding `Computables` and `Protocols`. \n", "\n", "After all these, we can call the `run_vqe()` function that also executes the simulation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# TIMER BLOCK-0 BEGINS AT 2025-06-12 15:14:02.658103\n", "# TIMER BLOCK-0 ENDS - DURATION (s): 0.1430625 [0:00:00.143062]\n", "\n", "VQE ENERGY: -1.1368465754720531\n", "\n", "VQE REPORT: \n" ] }, { "data": { "text/plain": [ "{'minimizer': {'n_iterations': 3,\n", " 'function_evaluations': 5,\n", " 'final_value': -1.1368465754720531,\n", " 'final_parameters': array([-0.107, 0. , 0. ])},\n", " 'final_value': -1.1368465754720531,\n", " 'initial_parameters': [{'Ordering': 0, 'Symbol': 'd0', 'Value': 0.0},\n", " {'Ordering': 1, 'Symbol': 's0', 'Value': 0.0},\n", " {'Ordering': 2, 'Symbol': 's1', 'Value': 0.0}],\n", " 'final_parameters': [{'Ordering': 0,\n", " 'Symbol': 'd0',\n", " 'Value': np.float64(-0.10723347230091586)},\n", " {'Ordering': 1, 'Symbol': 's0', 'Value': np.float64(0.0)},\n", " {'Ordering': 2, 'Symbol': 's1', 'Value': np.float64(0.0)}]}" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ############ #\n", "# OPTIMIZATION #\n", "# ############ #\n", "\n", "from inquanto.express import run_vqe\n", "\n", "vqe = run_vqe(ansatz, qubit_hamiltonian, backend=backend, with_gradient=True, minimizer=minimizer)\n", "\n", "report = vqe.generate_report()\n", "\n", "print('\\nVQE ENERGY: {}'.format(report['final_value']))\n", "print('\\nVQE REPORT: ')\n", "vqe.generate_report()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `.generate_report()` method provides the details of the result. We can see here that the VQE simulation has successfully converged, giving an energy of -1.1368 Hartrees -- a big improvement over the Hartree-Fock energy of -1.1175 Ha! This tutorial forms the basic workflow of running simple VQE calculations in InQuanto. From here, a few things can be very easily switched up - for instance, you could try:\n", "\n", "- Changing the molecule to another small example (such as LiH)\n", "- Changing the qubit mapping (for instance, to `inquanto.fock_space.QubitMappingBravyiKitaev`) to see the impact on circuit gate counts.\n", "- Changing the Ansatz state (for instance, to `inquanto.ansatz.FockSpaceAnsatzUCCGD`) to see the impact on the energy.\n", "- Changing the optimizer method.\n", "- Restricting the active space with the `frozen` parameter in the driver, or enabling point group symmetry with `point_group_symmetry=True` to see the impact on the number of Ansatz parameters.\n", "\n", "Other topics -- for instance, using other quantum algorithms, or fragmentation methods to look at larger systems -- will be covered in the [following tutorials](https://docs.quantinuum.com/inquanto/tutorials/InQ_tut_vqe_2.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 4 }