mindquantum.hiqfermion
transform
- class mindquantum.hiqfermion.transforms.Transform(operator, n_qubits=None)[source]
Class for transforms of fermionic and qubit operators. Methods jordan_wigner, parity, bravyi_kitaev, bravyi_kitaev_tree, bravyi_kitaev_superfast make transform of fermionic operators to qubit ones, they are initialized by FermionOperator, return QubitOperator. Note method reversed_jordan_wigner makes transform of qubit operator to fermionic one, it is initialized by QubitOperator, returns FermionOperator.
- Parameters
operator (Union[FermionOperator, QubitOperator]) – The input FermionOperator or QubitOperator that need to do transform.
n_qubits (int) – The total qubits of this operator. Default: None
Examples
>>> from mindquantum.ops import FermionOperator >>> op1 = FermionOperator('1^') >>> op1 1.0 [1^] >>> from mindquantum.hiqfermion.transforms.transform import Transform >>> op_transform = Transform(op1) >>> op_transform.jordan_wigner() 0.5 [Z0 X1] + -0.5j [Z0 Y1] >>> op_transform.parity() 0.5 [Z0 X1] + -0.5j [Y1] >>> op_transform.bravyi_kitaev() 0.5 [Z0 X1] + -0.5j [Y1] >>> op_transform.ternary_tree() 0.5 [X0 Z1] + -0.5j [Y0 X2] >>> op2 = FermionOperator('1^', 'a') >>> Transform(op2).jordan_wigner() 0.5*a [Z0 X1] + -0.5*I*a [Z0 Y1]
- bravyi_kitaev()[source]
Apply Bravyi-Kitaev transform.
The Bravyi-Kitaev basis is a middle between Jordan-Wigner and parity transform. That is, it balances the locality of occupation and parity information for improved simulation efficiency. In this scheme, qubits store the parity of a set of \(2^x\) orbitals, where \(x \ge 0\). A qubit of index j always stores orbital \(j\). For even values of \(j\), this is the only orbital that it stores, but for odd values of \(j\), it also stores a certain set of adjacent orbitals with index less than \(j\). For the occupation transformation, we follow the formular:
\[b_{i} = \sum{[\beta_{n}]_{i,j}} f_{j},\]where \(\beta_{n}\) is the \(N\times N\) square matrix, \(N\) is the total qubit number. The qubits index are divide into three sets, the parity set, the update set and flip set. The parity of this set of qubits has the same parity as the set of orbitals with index less than \(j\), and so we will call this set of qubit indices the “parity set” of index \(j\), or \(P(j)\).
the update set of index \(j\), or \(U(j)\) contains the set of qubits (other than qubit \(j\)) that must be updated when the occupation of orbital \(j\) This is the set of qubits in the Bravyi-Kitaev basis that store a partial sum including orbital \(j\). the flip set of index \(j\), or \(F(j)\) contains the set of BravyiKitaev qubits determines whether qubit \(j\) has the same parity or inverted parity with respect to orbital \(j\).
Please see some detail explanation in the paper (THE JOURNAL OF CHEMICAL PHYSICS 137, 224109 (2012)).
Implementation from https://arxiv.org/pdf/quant-ph/0003137.pdf and “A New Data Structure for Cumulative Frequency Tables” by Peter M. Fenwick.
- Returns
QubitOperator, qubit operator after bravyi_kitaev transformation.
- bravyi_kitaev_superfast()[source]
Apply Bravyi-Kitaev Superfast transform. Implementation from https://arxiv.org/pdf/1712.00446.pdf
Note that only hermitian operators of form
\[C + \sum_{p, q} h_{p, q} a^\dagger_p a_q + \sum_{p, q, r, s} h_{p, q, r, s} a^\dagger_p a^\dagger_q a_r a_s\]where \(C\) is a constant, be transformed.
- Returns
QubitOperator, qubit operator after bravyi_kitaev_superfast.
- jordan_wigner()[source]
Apply Jordan-Wigner transform. The Jordan-Wigner transform holds the initial occupation number locally. which change the formular of fermion operator into qubit operator following the equation.
\[ \begin{align}\begin{aligned}a^\dagger_{j}\rightarrow \sigma^{-}_{j} X \prod_{i=0}^{j-1}\sigma^{Z}_{i}\\a_{j}\rightarrow \sigma^{+}_{j} X \prod_{i=0}^{j-1}\sigma^{Z}_{i},\end{aligned}\end{align} \]where the \(\sigma_{+}= \sigma^{X} + i \sigma^{Y}\) and \(\sigma_{-} = \sigma^{X} - i\sigma^{Y}\) is the Pauli spin raising and lowring operator.
- Returns
QubitOperator, qubit operator after jordan_wigner transformation.
- parity()[source]
Apply parity transform. The parity transform stores the initial occupation number nonlocally. with the formular:
\[\left|f_{M−1}, f_{M−2},\cdots, f_0\right> → \left|q_{M−1}, q_{M−2},\cdots, q_0\right>,\]where
\[q_{m} = \left|\left(\sum_{i=0}^{m-1}f_{i}\right) mod\ 2 \right>\]Basically, this formular could be written as this,
\[p_{i} = \sum{[\pi_{n}]_{i,j}} f_{j},\]where \(\pi_{n}\) is the \(N\times N\) square matrix, \(N\) is the total qubit number. The operator changes follows the following equation as:
\[ \begin{align}\begin{aligned}a^\dagger_{j}\rightarrow\frac{1}{2}\left(\prod_{i=j+1}^N \left(\sigma_i^X X\right)\right)\left( \sigma^{X}_{j}-i\sigma_j^Y\right) X \sigma^{Z}_{j-1}\\a_{j}\rightarrow\frac{1}{2}\left(\prod_{i=j+1}^N \left(\sigma_i^X X\right)\right)\left( \sigma^{X}_{j}+i\sigma_j^Y\right) X \sigma^{Z}_{j-1}\end{aligned}\end{align} \]- Returns
QubitOperator, qubits operator after parity transformation.
- reversed_jordan_wigner()[source]
Apply reversed Jordan-Wigner transform.
- Returns
FermionOperator, fermion operator after reversed_jordan_wigner transformation.
- ternary_tree()[source]
Apply Ternary tree transform. Implementation from https://arxiv.org/pdf/1910.10746.pdf.
- Returns
QubitOperator, qubit operator after ternary_tree transformation.
Quantum unitary coupled cluster.
- mindquantum.hiqfermion.ucc.get_qubit_hamiltonian(mol)[source]
Get the qubit hamiltonian of a molecular data.
- Parameters
mol (MolecularData) – molecular data.
- Returns
QubitOperator, qubit operator of this molecular.
- mindquantum.hiqfermion.ucc.quccsd_generator(n_qubits=None, n_electrons=None, anti_hermitian=True, occ_orb=None, vir_orb=None, generalized=False)[source]
Generate qubit-UCCSD (qUCCSD) ansatz using qubit-excitation operators.
Note
Currently, unrestricted version is implemented, i.e., excitations from the same spatial-orbital but with different spins will use distinct variational parameters.
- Parameters
n_qubits (int) – Number of qubits (spin-orbitals). Default: None.
n_electrons (int) – Number of electrons (occupied spin-orbitals). Default: None.
anti_hermitian (bool) – Whether to subtract the hermitian conjugate to form anti-Hermitian operators. Default: True.
occ_orb (list) – Indices of manually assigned occupied spatial orbitals. Default: None.
vir_orb (list) – Indices of manually assigned virtual spatial orbitals. Default: None.
generalized (bool) – Whether to use generalized excitations which do not distinguish occupied or virtual orbitals (qUCCGSD). Default: False.
- Returns
Generator of the qUCCSD operators.
- Return type
Examples
>>> from mindquantum.hiqfermion.ucc import quccsd_generator >>> quccsd_generator() 0 >>> quccsd_generator(4, 2) -1.0*q_s_0 [Q0^ Q2] + -1.0*q_s_2 [Q0^ Q3] + -1.0*q_d_0 [Q1^ Q0^ Q3 Q2] + -1.0*q_s_1 [Q1^ Q2] + -1.0*q_s_3 [Q1^ Q3] + 1.0*q_s_0 [Q2^ Q0] + 1.0*q_s_1 [Q2^ Q1] + 1.0*q_s_2 [Q3^ Q0] + 1.0*q_s_3 [Q3^ Q1] + 1.0*q_d_0 [Q3^ Q2^ Q1 Q0] >>> q_op = quccsd_generator(occ_orb=[0], vir_orb=[1], generalized=True) >>> q_qubit_op = q_op.to_qubit_operator() >>> print(str(q_qubit_op)[:315]) 0.125*I*q_d_4 + 0.125*I*q_d_7 + 0.125*I*q_d_9 [X0 X1 X2 Y3] + 0.125*I*q_d_4 - 0.125*I*q_d_7 - 0.125*I*q_d_9 [X0 X1 Y2 X3] + 0.25*I*q_d_12 + 0.25*I*q_d_5 + 0.5*I*q_s_0 - 0.5*I*q_s_3 [X0 Y1] + -0.125*I*q_d_4 + 0.125*I*q_d_7 - 0.125*I*q_d_9 [X0 Y1 X2 X3] + 0.125*I*q_d_4 + 0.125*I*q_d_7 - 0.125*I*q_d_9 [X0 Y1 Y2 Y3] +
- mindquantum.hiqfermion.ucc.uccsd0_singlet_generator(n_qubits=None, n_electrons=None, anti_hermitian=True, occ_orb=None, vir_orb=None, generalized=False)[source]
Generate UCCSD operators using CCD0 ansatz for molecular systems.
Note
Manually assigned occ_orb or vir_orb are indices of spatial orbitals instead of spin-orbitals. They will override n_electrons and n_qubits. This is to some degree similar to the active space, therefore can reduce the number of variational parameters. However, it may not reduce the number of required qubits, since Fermion excitation operators are non-local, i.e., \(a_{7}^{\dagger} a_{0}\) involves not only the 0th and 7th qubit, but also the 1st, 2nd, … 6th qubit.
- Parameters
n_qubits (int) – Number of qubits (spin-orbitals). Default: None.
n_electrons (int) – Number of electrons (occupied spin-orbitals). Default: None.
anti_hermitian (bool) – Whether to subtract the hermitian conjugate to form anti-Hermitian operators. Default: True.
occ_orb (list) – Indices of manually assigned occupied spatial orbitals. Default: None.
vir_orb (list) – Indices of manually assigned virtual spatial orbitals. Default: None.
generalized (bool) – Whether to use generalized excitations which do not distinguish occupied or virtual orbitals (UCCGSD). Default: False.
- Returns
FermionOperator, Generator of the UCCSD operators that uses CCD0 ansatz.
Examples
>>> from mindquantum.hiqfermion.ucc.uccsd0 import uccsd0_singlet_generator >>> uccsd0_singlet_generator(4, 2) -1.0*d0_s_0 [0^ 2] + 2.0*d0_d_0 [1^ 0^ 3 2] + -1.0*d0_s_0 [1^ 3] + 1.0*d0_s_0 [2^ 0] + 1.0*d0_s_0 [3^ 1] + -2.0*d0_d_0 [3^ 2^ 1 0] >>> uccsd0_singlet_generator(4, 2, generalized=True) 1.0*d0_s_0 - 1.0*d0_s_1 [0^ 2] + 1.0*d0_d_0 [1^ 0^ 2 1] + -1.0*d0_d_0 [1^ 0^ 3 0] + -2.0*d0_d_1 [1^ 0^ 3 2] + 1.0*d0_s_0 - 1.0*d0_s_1 [1^ 3] + -1.0*d0_s_0 + 1.0*d0_s_1 [2^ 0] + -1.0*d0_d_0 [2^ 1^ 1 0] + 1.0*d0_d_2 [2^ 1^ 3 2] + 1.0*d0_d_0 [3^ 0^ 1 0] + -1.0*d0_d_2 [3^ 0^ 3 2] + -1.0*d0_s_0 + 1.0*d0_s_1 [3^ 1] + 2.0*d0_d_1 [3^ 2^ 1 0] + -1.0*d0_d_2 [3^ 2^ 2 1] + 1.0*d0_d_2 [3^ 2^ 3 0] >>> uccsd0_singlet_generator(6, 2, occ_orb=[0], vir_orb=[1]) -1.0*d0_s_0 [0^ 2] + 2.0*d0_d_0 [1^ 0^ 3 2] + -1.0*d0_s_0 [1^ 3] + 1.0*d0_s_0 [2^ 0] + 1.0*d0_s_0 [3^ 1] + -2.0*d0_d_0 [3^ 2^ 1 0]
- mindquantum.hiqfermion.ucc.uccsd_singlet_generator(n_qubits, n_electrons, anti_hermitian=True)[source]
Create a singlet UCCSD generator for a system with n_electrons
This function generates a FermionOperator for a UCCSD generator designed to act on a single reference state consisting of n_qubits spin orbitals and n_electrons electrons, that is a spin singlet operator, meaning it conserves spin.
- Parameters
n_qubits (int) – Number of spin-orbitals used to represent the system, which also corresponds to number of qubits in a non-compact map.
n_electrons (int) – Number of electrons in the physical system.
anti_hermitian (bool) – Flag to generate only normal CCSD operator rather than unitary variant, primarily for testing
- Returns
FermionOperator, Generator of the UCCSD operator that builds the UCCSD wavefunction.
Examples
>>> from mindquantum.hiqfermion.ucc import uccsd_singlet_generator >>> uccsd_singlet_generator(4, 2) -s_0 [0^ 2] + -d1_0 [0^ 2 1^ 3] + -s_0 [1^ 3] + -d1_0 [1^ 3 0^ 2] + s_0 [2^ 0] + d1_0 [2^ 0 3^ 1] + s_0 [3^ 1] + d1_0 [3^ 1 2^ 0]
- mindquantum.hiqfermion.ucc.uccsd_singlet_get_packed_amplitudes(single_amplitudes, double_amplitudes, n_qubits, n_electrons)[source]
Convert amplitudes for use with singlet UCCSD
The output list contains only those amplitudes that are relevant to singlet UCCSD, in an order suitable for use with the function uccsd_singlet_generator.
- Parameters
single_amplitudes (numpy.ndarray) – \(N\times N\) array storing single excitation amplitudes corresponding to \(t_{i,j} * (a_i^\dagger a_j - \text{H.C.})\)
double_amplitudes (numpy.ndarray) – \(N\times N\times N\times N\) array storing double excitation amplitudes corresponding to \(t_{i,j,k,l} * (a_i^\dagger a_j a_k^\dagger a_l - \text{H.C.})\)
n_qubits (int) – Number of spin-orbitals used to represent the system, which also corresponds to number of qubits in a non-compact map.
n_electrons (int) – Number of electrons in the physical system.
- Returns
ParameterResolver, List storing the unique single and double excitation amplitudes for a singlet UCCSD operator. The ordering lists unique single excitations before double excitations.
Examples
>>> import numpy as np >>> from mindquantum.hiqfermion.ucc import uccsd_singlet_get_packed_amplitudes >>> n_qubits, n_electrons = 4, 2 >>> np.random.seed(42) >>> ccsd_single_amps = np.random.random((4, 4)) >>> ccsd_double_amps = np.random.random((4, 4, 4, 4)) >>> uccsd_singlet_get_packed_amplitudes(ccsd_single_amps, ccsd_double_amps, ... n_qubits, n_electrons) {'s_0': 0.6011150117432088, 'd1_0': 0.7616196153287176}