From c90903c185b28938e9553d7c4ab3f129ab62701d Mon Sep 17 00:00:00 2001 From: Jue Xu Date: Tue, 15 Oct 2024 12:50:29 +0800 Subject: [PATCH] add hubbard_openfermion --- quantum_simulation_recipe/fermion.py | 57 +++++++++++++++++++++++++++- quantum_simulation_recipe/test.ipynb | 52 ++++++++++++++++++++++--- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/quantum_simulation_recipe/fermion.py b/quantum_simulation_recipe/fermion.py index 8bcc31a..5aeef12 100644 --- a/quantum_simulation_recipe/fermion.py +++ b/quantum_simulation_recipe/fermion.py @@ -320,4 +320,59 @@ def LiH(): LiH_fermion_hamiltonian = get_fermion_operator(LiH_molecular_hamiltonian) LiH_qubit_hamiltonian = jordan_wigner(LiH_fermion_hamiltonian) LiH_hamiltonian_list = openfermion_matrix_list(LiH_qubit_hamiltonian) - return LiH_hamiltonian_list \ No newline at end of file + return LiH_hamiltonian_list + + + +"""Define the Hubbard Hamiltonian by OpenFermion.""" +class hubbard_openfermion: + def __init__(self, nsites, U, J=-1.0, pbc=False, verbose=False): + # Each site has two spins. + self.n_qubits = 2 * nsites + + def fop_2_sparse(fops): + return [of.get_sparse_operator(fop, n_qubits=self.n_qubits).todense() for fop in fops ] + + # One-body (hopping) terms. + self.one_body_fops = [op + of.hermitian_conjugated(op) for op in ( + of.FermionOperator(((i, 1), (i + 2, 0)), coefficient=J) for i in range(self.n_qubits - 2))] + self.one_body_L = len(self.one_body_fops) + self.one_body_sparse = fop_2_sparse(self.one_body_fops) + + # Two-body (charge-charge) terms. + self.two_body_fops = [ + of.FermionOperator(((i, 1), (i, 0), (i + 1, 1), (i + 1, 0)), coefficient=U) + for i in range(0, self.n_qubits, 2)] + self.two_body_sparse = fop_2_sparse(self.two_body_fops) + + self.h_fop = of.fermi_hubbard(1, nsites, tunneling=-J, coulomb=U, periodic=pbc) + self.h_sparse = of.get_sparse_operator(self.h_fop) + self.ground_energy, self.ground_state = of.get_ground_state(self.h_sparse) + assert sum(self.one_body_fops) + sum(self.two_body_fops) == self.h_fop + if verbose: + print('one_body_terms: \n', self.one_body_fops) + print('one_body_L: ', self.one_body_L) + # print('one_body[0]: \n', self.one_body_sparse[0]) + print('one_body[0]: \n', of.get_sparse_operator(self.one_body_fops[0])) + # print('sparse two-body: \n', of.get_sparse_operator(sum(self.two_body_fops))) + # print('sparse two-body[0]: \n', self.two_body_sparse[0]) + # print('ground energy: \n', self.ground_energy) + # return ground_energy + + self.one_body_01 = [term for index, term in enumerate(self.one_body_fops) if index % 4 == 0 or index % 4 == 1] + self.one_body_01_sparse = fop_2_sparse(self.one_body_01) + # print(self.one_body_01) + self.one_body_23 = [term for index, term in enumerate(self.one_body_fops) if index % 4 == 2 or index % 4 == 3] + self.one_body_23_sparse = fop_2_sparse(self.one_body_23) + # print(self.one_body_23) + assert sum(self.one_body_01) + sum(self.one_body_23) == sum(self.one_body_fops) + + self.one_body_0 = [term for index, term in enumerate(self.one_body_fops) if index % 3 == 0] + self.one_body_1 = [term for index, term in enumerate(self.one_body_fops) if index % 3 == 1] + self.one_body_2 = [term for index, term in enumerate(self.one_body_fops) if index % 3 == 2] + + assert sum(self.one_body_0) + sum(self.one_body_1) + sum(self.one_body_2) == sum(self.one_body_fops) + + self.one_body_0_sparse = [term for index, term in enumerate(self.one_body_sparse) if index % 3 == 0] + self.one_body_1_sparse = [term for index, term in enumerate(self.one_body_sparse) if index % 3 == 1] + self.one_body_2_sparse = [term for index, term in enumerate(self.one_body_sparse) if index % 3 == 2] diff --git a/quantum_simulation_recipe/test.ipynb b/quantum_simulation_recipe/test.ipynb index 1b35652..8434bf4 100644 --- a/quantum_simulation_recipe/test.ipynb +++ b/quantum_simulation_recipe/test.ipynb @@ -144,6 +144,51 @@ "plh.ham_xyz" ] }, + { + "cell_type": "markdown", + "id": "dd5a2e4f", + "metadata": {}, + "source": [ + "### Fermi-Hubbard" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e856807f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "one body terms: [-1.0 [0^ 2] +\n", + "-1.0 [2^ 0], -1.0 [1^ 3] +\n", + "-1.0 [3^ 1], -1.0 [2^ 4] +\n", + "-1.0 [4^ 2], -1.0 [3^ 5] +\n", + "-1.0 [5^ 3], -1.0 [4^ 6] +\n", + "-1.0 [6^ 4], -1.0 [5^ 7] +\n", + "-1.0 [7^ 5]]\n", + "two body terms: [1 [0^ 0 1^ 1], 1 [2^ 2 3^ 3], 1 [4^ 4 5^ 5], 1 [6^ 6 7^ 7]]\n" + ] + } + ], + "source": [ + "n = 4\n", + "# n = 5\n", + "r = 10000\n", + "epsilon = 1e-3\n", + "J, U = -1, 1\n", + "\n", + "t_num = 100\n", + "t_list = np.logspace(-1, 3, num=t_num)\n", + "# t_list = np.logspace(1.5, 3, num=t_num)\n", + "hubbard = hubbard_openfermion(n, U, verbose=False)\n", + "print('one body terms: ', hubbard.one_body_fops)\n", + "print('two body terms: ', hubbard.two_body_fops)\n", + "h_group = [sum(hubbard.one_body_01_sparse), sum(hubbard.one_body_23_sparse), sum(hubbard.two_body_sparse)]" + ] + }, { "cell_type": "markdown", "id": "d7fe9c22", @@ -638,7 +683,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.8.8 ('base')", + "display_name": "base", "language": "python", "name": "python3" }, @@ -653,11 +698,6 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.14" - }, - "vscode": { - "interpreter": { - "hash": "4e8ef2f9fcac0817bca9a7ca376f64f20b4df5ea3bf7af756a50bda7d3557ea6" - } } }, "nbformat": 4,