From c96bda246115d8d52276efa37c3a7f131194915e Mon Sep 17 00:00:00 2001 From: Hugh Date: Fri, 24 Apr 2026 15:38:42 +0800 Subject: [PATCH 1/4] add class FermionMapBoson --- src/deepquantum/photonic/ansatz.py | 308 +++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) diff --git a/src/deepquantum/photonic/ansatz.py b/src/deepquantum/photonic/ansatz.py index 4482f054..59755eb6 100644 --- a/src/deepquantum/photonic/ansatz.py +++ b/src/deepquantum/photonic/ansatz.py @@ -1,6 +1,7 @@ """Ansatze: various photonic quantum circuits""" import copy +from itertools import combinations from typing import Any import networkx as nx @@ -227,3 +228,310 @@ def graph_density(graph: nx.Graph, samples: dict) -> dict: samples_[key] = [temp_prob, density] sort_samples = sort_dict_fock_basis(samples_, 1) return sort_samples + + +class FermionMapBoson: + """A class to map molecular Fermionic Hamiltonians to Bosonic Qumode representations. + + This class utilizes OpenFermion and PySCF to perform electronic structure + calculations and applies the Dhar-Mandal-Suryanarayana (DMS) mapping to + transform the second-quantized Hamiltonian into a Bosonic Fock space. + It supports Active Space approximations to reduce the simulation dimensionality. + + Args: + config (dict): A configuration dictionary containing the following keys: + 'geometry' (list): Molecular structure, e.g., [('H', (0,0,0)), ('H', (0,0,0.74))]. + 'basis' (str): Quantum chemistry basis set (e.g., 'sto-3g', '6-31g'). + 'multiplicity' (int): Spin multiplicity (2S + 1). Usually 1 for closed-shell. + 'charge' (int): Net charge of the molecule. + 'n_ele' (int): Total number of electrons in the full system. + 'n_orbit' (int): Total number of spin-orbitals in the full space. + 'occupied_indices' (list): Indices of spatial orbitals to be frozen (occupied). + Electrons in these orbitals do not participate in + excitations but contribute to the energy constant. + 'active_indices' (list): Indices of spatial orbitals to be treated as active. + These form the primary Hilbert space for VQE. + """ + + def __init__(self, config: dict = None) -> None: + self.geometry = config['geometry'] + self.basis = config['basis'] + self.multiplicity = config['multiplicity'] + self.charge = config['charge'] + self.occupied_indices = config['occupied_indices'] + self.active_indices = config['active_indices'] + self.n = config['n_ele'] - 2 * len(self.occupied_indices) + self.m = 2 * len(self.active_indices) + + def construct_h_fermion(self): + from openfermion import get_fermion_operator + from openfermion.chem import MolecularData + from openfermionpyscf import run_pyscf + + molecule = MolecularData(self.geometry, self.basis, self.multiplicity, self.charge) + molecule = run_pyscf(molecule, run_scf=True, run_fci=True) + hamiltonian = molecule.get_molecular_hamiltonian( + occupied_indices=self.occupied_indices, active_indices=self.active_indices + ) + fermion_op = get_fermion_operator(hamiltonian) + h_matrix, basis_f = self.compute_hamiltonian_matrix(fermion_op, self.n, self.m) + self.molecule = molecule + self.hamiltonian = hamiltonian + self.constant = hamiltonian.constant + self.fermion_op = fermion_op + self.basis_f = basis_f + self.h_matrix = h_matrix + return h_matrix + + def mapping(self): + self.h_fock, self.map_dic = self.get_dms_mapping(self.h_matrix, self.n, self.m) + return self.h_fock + + def fci_energy(self): + return self.molecule.fci_energy + + @staticmethod + def apply_annihilation(state, k): + """湮灭算符 f_k 作用在 Slater 行列式上 + + 输入: + state: tuple,有序轨道列表 (p1,...,pN),p1 Date: Fri, 24 Apr 2026 16:04:45 +0800 Subject: [PATCH 2/4] update --- src/deepquantum/photonic/ansatz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deepquantum/photonic/ansatz.py b/src/deepquantum/photonic/ansatz.py index 59755eb6..e73d4ea7 100644 --- a/src/deepquantum/photonic/ansatz.py +++ b/src/deepquantum/photonic/ansatz.py @@ -470,7 +470,7 @@ def compute_hamiltonian_matrix(self, fermion_op, n, m): basis: list of tuples,基矢列表 """ # Step 1: 枚举基矢 - basis = list(combinations(range(m), m)) + basis = list(combinations(range(m), n)) dim = len(basis) # Step 2: 提取积分系数 From 0148f7439845795fee52bd5fc82fd2069b0dae1e Mon Sep 17 00:00:00 2001 From: Hugh Date: Mon, 27 Apr 2026 13:42:41 +0800 Subject: [PATCH 3/4] update docstring --- src/deepquantum/photonic/ansatz.py | 97 ++++++++++++++---------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/src/deepquantum/photonic/ansatz.py b/src/deepquantum/photonic/ansatz.py index 59755eb6..5f8988c8 100644 --- a/src/deepquantum/photonic/ansatz.py +++ b/src/deepquantum/photonic/ansatz.py @@ -2,7 +2,7 @@ import copy from itertools import combinations -from typing import Any +from typing import Any, TYPE_CHECKING import networkx as nx import numpy as np @@ -14,6 +14,9 @@ from .qmath import sort_dict_fock_basis, takagi from .state import FockState +if TYPE_CHECKING: + from openfermion import FermionOperator + class Clements(QumodeCircuit): """Clements circuit.""" @@ -291,18 +294,13 @@ def fci_energy(self): return self.molecule.fci_energy @staticmethod - def apply_annihilation(state, k): - """湮灭算符 f_k 作用在 Slater 行列式上 - - 输入: - state: tuple,有序轨道列表 (p1,...,pN),p1 0.5 * f†_0 f_1 + FermionOperator(0.25, '0^ 1^ 2 3') -> 0.25 * f†_0 f†_1 f_2 f_3 - 输出: - h: dict,{(p,q): coefficient},单体项 - v: dict,{(p,q,r,s): coefficient},双体项 - constant: float,常数项(核排斥能等) + Args: + fermion_op: The operator object from OpenFermion. """ h = {} # 单体积分 v = {} # 双体积分 @@ -457,17 +452,13 @@ def extract_integrals(fermion_op): return h, v, constant - def compute_hamiltonian_matrix(self, fermion_op, n, m): - """直接计算费米子哈密顿量在 n 粒子子空间的矩阵 - - 输入: - fermion_op: OpenFermion FermionOperator - n: 电子数 - m: 自旋轨道数 + def compute_hamiltonian_matrix(self, fermion_op: 'FermionOperator', n: int, m: int): + """Directly compute the Hamiltonian matrix in the n-particle subspace. - 输出: - h_matrix: np.ndarray,dim × dim 的厄米矩阵 - basis: list of tuples,基矢列表 + Args: + fermion_op: The input OpenFermion Hamiltonian. + n: Number of particles (electrons). + m: Number of spin-orbitals. """ # Step 1: 枚举基矢 basis = list(combinations(range(m), m)) From 441a2f1ec990bff5dafdf7dbb211f8e762198f84 Mon Sep 17 00:00:00 2001 From: Hugh Date: Mon, 27 Apr 2026 14:01:43 +0800 Subject: [PATCH 4/4] update --- src/deepquantum/photonic/ansatz.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/deepquantum/photonic/ansatz.py b/src/deepquantum/photonic/ansatz.py index f6318753..b684390c 100644 --- a/src/deepquantum/photonic/ansatz.py +++ b/src/deepquantum/photonic/ansatz.py @@ -298,7 +298,7 @@ def apply_annihilation(state: tuple, k: int): """Apply the annihilation operator :math:`f_k` to a Slater determinant. Args: - state: An ordered list of occupied orbitals (p1, ..., pN) where p1 < p2 < ... < pN. + state: An ordered list of occupied orbitals :math:`(p1, ..., pN)` where :math:`p1 < p2 < ... < pN`. k: The index of the orbital to be annihilated. """ @@ -318,7 +318,7 @@ def apply_creation(state, k): """Apply the creation operator :math:`f^†_k` to a Slater determinant. Args: - state: An ordered list of occupied orbitals (p1, ..., pN) where p1 < p2 < ... < pN. + state: An ordered list of occupied orbitals :math:`(p1, ..., pN)` where :math:`p1 < p2 < ... < pN`. k: The index of the orbital to be created. """ @@ -407,7 +407,7 @@ def matrix_element_two_body(self, bra: tuple, ket: tuple, p: int, q: int, r: int @staticmethod def extract_integrals(fermion_op: 'FermionOperator'): - """Extract one-body integrals :math:`h[p,q]` and two-body integrals :math:`v[p,q,r,s]` from aFermionOperator. + """Extract one-body integrals :math:`h[p,q]` and two-body integrals :math:`v[p,q,r,s]` from a FermionOperator. The FermionOperator format handles terms like: FermionOperator(0.5, '0^ 1') -> 0.5 * f†_0 f_1