[4]:
!echo y | pip uninstall h5py
!pip install h5py==2.9.0
!pip install openfermion openfermionpyscf
Requirement already satisfied: openfermion in /usr/local/lib/python3.7/dist-packages (1.1.0)
Requirement already satisfied: openfermionpyscf in /usr/local/lib/python3.7/dist-packages (0.5)
Requirement already satisfied: deprecation in /usr/local/lib/python3.7/dist-packages (from openfermion) (2.1.0)
Requirement already satisfied: pubchempy in /usr/local/lib/python3.7/dist-packages (from openfermion) (1.0.4)
Requirement already satisfied: requests~=2.18 in /usr/local/lib/python3.7/dist-packages (from openfermion) (2.23.0)
Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from openfermion) (1.7.1)
Requirement already satisfied: nbformat in /usr/local/lib/python3.7/dist-packages (from openfermion) (5.1.3)
Requirement already satisfied: networkx in /usr/local/lib/python3.7/dist-packages (from openfermion) (2.6.2)
Requirement already satisfied: h5py>=2.8 in /usr/local/lib/python3.7/dist-packages (from openfermion) (3.1.0)
Requirement already satisfied: numpy>=1.11.0 in /usr/local/lib/python3.7/dist-packages (from openfermion) (1.19.5)
Requirement already satisfied: scipy>=1.1.0 in /usr/local/lib/python3.7/dist-packages (from openfermion) (1.4.1)
Requirement already satisfied: cirq~=0.11.0 in /usr/local/lib/python3.7/dist-packages (from openfermion) (0.11.1)
Requirement already satisfied: cirq-google==0.11.1 in /usr/local/lib/python3.7/dist-packages (from cirq~=0.11.0->openfermion) (0.11.1)
Requirement already satisfied: cirq-core==0.11.1 in /usr/local/lib/python3.7/dist-packages (from cirq~=0.11.0->openfermion) (0.11.1)
Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.11.1->cirq~=0.11.0->openfermion) (3.7.4.3)
Requirement already satisfied: sortedcontainers~=2.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.11.1->cirq~=0.11.0->openfermion) (2.4.0)
Requirement already satisfied: pandas in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.11.1->cirq~=0.11.0->openfermion) (1.1.5)
Requirement already satisfied: matplotlib~=3.0 in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.11.1->cirq~=0.11.0->openfermion) (3.2.2)
Requirement already satisfied: tqdm in /usr/local/lib/python3.7/dist-packages (from cirq-core==0.11.1->cirq~=0.11.0->openfermion) (4.62.0)
Requirement already satisfied: protobuf~=3.13.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.11.1->cirq~=0.11.0->openfermion) (3.13.0)
Requirement already satisfied: google-api-core[grpc]<2.0.0dev,>=1.14.0 in /usr/local/lib/python3.7/dist-packages (from cirq-google==0.11.1->cirq~=0.11.0->openfermion) (1.26.3)
Requirement already satisfied: google-auth<2.0dev,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (1.34.0)
Requirement already satisfied: six>=1.13.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (1.15.0)
Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (2018.9)
Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.6.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (1.53.0)
Requirement already satisfied: packaging>=14.3 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (21.0)
Requirement already satisfied: setuptools>=40.3.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (57.4.0)
Requirement already satisfied: grpcio<2.0dev,>=1.29.0 in /usr/local/lib/python3.7/dist-packages (from google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (1.39.0)
Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (4.7.2)
Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (0.2.8)
Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (4.2.2)
Requirement already satisfied: cached-property in /usr/local/lib/python3.7/dist-packages (from h5py>=2.8->openfermion) (1.5.2)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.11.1->cirq~=0.11.0->openfermion) (2.4.7)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.11.1->cirq~=0.11.0->openfermion) (2.8.2)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.11.1->cirq~=0.11.0->openfermion) (0.10.0)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib~=3.0->cirq-core==0.11.1->cirq~=0.11.0->openfermion) (1.3.1)
Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.7/dist-packages (from pyasn1-modules>=0.2.1->google-auth<2.0dev,>=1.21.1->google-api-core[grpc]<2.0.0dev,>=1.14.0->cirq-google==0.11.1->cirq~=0.11.0->openfermion) (0.4.8)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->openfermion) (1.24.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->openfermion) (3.0.4)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->openfermion) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests~=2.18->openfermion) (2021.5.30)
Requirement already satisfied: pytest in /usr/local/lib/python3.7/dist-packages (from openfermionpyscf) (3.6.4)
Requirement already satisfied: pyscf in /usr/local/lib/python3.7/dist-packages (from openfermionpyscf) (1.7.6.post1)
Requirement already satisfied: jsonschema!=2.5.0,>=2.4 in /usr/local/lib/python3.7/dist-packages (from nbformat->openfermion) (2.6.0)
Requirement already satisfied: jupyter-core in /usr/local/lib/python3.7/dist-packages (from nbformat->openfermion) (4.7.1)
Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.7/dist-packages (from nbformat->openfermion) (0.2.0)
Requirement already satisfied: traitlets>=4.1 in /usr/local/lib/python3.7/dist-packages (from nbformat->openfermion) (5.0.5)
Requirement already satisfied: py>=1.5.0 in /usr/local/lib/python3.7/dist-packages (from pytest->openfermionpyscf) (1.10.0)
Requirement already satisfied: pluggy<0.8,>=0.5 in /usr/local/lib/python3.7/dist-packages (from pytest->openfermionpyscf) (0.7.1)
Requirement already satisfied: atomicwrites>=1.0 in /usr/local/lib/python3.7/dist-packages (from pytest->openfermionpyscf) (1.4.0)
Requirement already satisfied: more-itertools>=4.0.0 in /usr/local/lib/python3.7/dist-packages (from pytest->openfermionpyscf) (8.8.0)
Requirement already satisfied: attrs>=17.4.0 in /usr/local/lib/python3.7/dist-packages (from pytest->openfermionpyscf) (21.2.0)
Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->openfermion) (1.2.1)
[51]:
import numpy as np
import matplotlib.pyplot as plt
from openfermion.chem import MolecularData
from openfermion.transforms import get_fermion_operator, jordan_wigner, bravyi_kitaev, symmetry_conserving_bravyi_kitaev
from openfermion.linalg import get_sparse_operator
from openfermion.ops import FermionOperator
from pyscf import gto, scf, tools

量子コンピュータ上に量子化学の問題をマッピングする#

量子化学計算の基本は、分子の(電子に対する)波動関数\(\Psi\)を計算し、エネルギー E を得ることにある。 波動関数とエネルギーを得るには、以下の固有値方程式を解けばよい。

\[H\Psi = E\Psi\]

ここで、\(H\)は分子の(電子に対する)ハミルトニアンである。 また、量子力学の基本であるが、電子密度やDipole \(\mu\)などの物理量は演算子の期待値として計算される。

\[\mu = \langle \Psi | \hat{\mu} | \Psi \rangle\]

この手続きを量子コンピュータでおこなうには、電子の波動関数\(\Psi\)とハミルトニアン\(H\)を量子コンピュータ上で量子回路を用いて表現する必要がある。ただ、第一原理ハミルニアンは、連続変数のハミルトニアンであり(e.g. 電子電子反発は\(\frac{1}{r})\)、これをそのまま量子コンピュータに載せることは難しい。そこで、デジタルコンピュータでの処理に適した、離散化された第二量子化表現のハミルトニアンを用いる。

\[H_{electron} = \sum_{pq} T_{pq} c^\dagger_p c_q + \sum_{pqrs} V_{pqrs} c^\dagger_p c^\dagger_q c_r c_s\]

ここで、\(c^\dagger_p\)\(c_p\)は、\(p\)番目の軌道に電子を生成させる生成演算子、\(p\)番目の軌道にある電子を消滅させる消滅演算子となっている。

残念がら、量子コンピュータは、スピン1/2の量子系であり、電子系(Fermion系)を直接サポートしていない。つまり、上記のハミルトニアンをそのまま量子コンピュータに載せることはできない。電子ハミルトニアン\(H_{electron}\) を量子コンピュータ上で取り扱うには、量子コンピュータに対応したqubit表現のハミルトニアン \(H_{qubit}\) へ変換しなくてはならない。

\[H_{qubit} = \sum h_{p} P\]

ここで、\(P\)\(p\)は、パウリ演算子の積(e.g. XXYなど)とそれに対応するインデックスである。

この\(H_{electron}\)から\(H_{qubit}\)への変換法をこのチュートリアルでは見ていく。

\(H_{qubit}\)を用意する手順#

\(H_{electron}\)から\(H_{qubit}\)への変換法は、複数存在する。 実は、この変換は、今日では、既にオープンソースのソフトウェアを用いて簡単におこなえるようになっている。 そうしたソフトウェアとしては、IBMのQiskitやGoogleのチームが中心に開発しているOpenFermionが挙げられる。 このチュートリアルでは、OpenFermionを使うこととする。

量子コンピュータ用ハミルトニアンの用意は以下のステップでおこなわれる。 1. 計算する分子の構造や電荷など入力する (通常の量子化学計算と同じ) 2. 平均場(Hartree-Fock)計算などを実行し(分子)軌道を得る 3. 得られた分子軌道から、第二量子化表現の電子のハミルトニアン\(H_{electron}\)を構築する 4. OpenFermionなどを使って、\(H_{electron}\)\(H_{qubit}\)に変換する

この各ステップについて以下で順に見ていきたい。

1. 計算する分子の構造や電荷など入力する#

この部分については、通常の量子化学計算と同じである。 05_01_conventional_quantum_chemical_calculations で実行したのと同様に、 まずは水素分子を用意する。

[10]:
# 水素分子、H-H距離は0.74Å と設定。STO-3GというGaussian型の原子基底関数を使用。
mol_h2 = gto.M(atom = 'H 0 0 0; H 0 0 0.74', basis = 'sto-3g')

2. 平均場(Hartree-Fock)計算などを実行し(分子)軌道を得る#

この部分については、通常の量子化学計算と同じである。 量子化学計算では、

[17]:
# この水素分子の基底状態を平均場近似(Hartree-Fock theory)で計算してみる。
mean_field_wavefunction = scf.RHF(mol_h2)
mean_field_wavefunction.verbose = 0
hf_energy = mean_field_wavefunction.kernel()
print ("Hartree-Fock Energy in (hartree)", hf_energy)
Hartree-Fock Energy in (hartree) -1.1167593073964248

Hartree-Fock計算を通して、変分的に最適な分子軌道(MO)を見つけることができる。 標準的な量子化学計算プログラムでは、Hartree-Fock計算とは、分子軌道\(\phi^{MO}(r)\)を原子基底\(\chi^{AO}(r)\)の線形結合で表すときに、その線形結合の係数(分子軌道係数, MO coefficients)を最適化する方法となっている。

\[\phi^{MO}_{i}(r) = \sum_{p} C_{ip}\chi_{p}(r)\]

ここで、\(i\)はi番目の分子軌道を示し、\(p\)は原子軌道のindexである。\(r\)は、実空間の座標情報となっている。

この系は原子基底の数がわずか2つしかないので、得られた分子軌道をプリントして簡単に確認できる。

[19]:
print ("C0", mean_field_wavefunction.mo_coeff[:,0], "Energy of the 1st MO", mean_field_wavefunction.mo_energy[0])
print ("C1", mean_field_wavefunction.mo_coeff[:,1], "Energy of the 2nd MO", mean_field_wavefunction.mo_energy[1])
C0 [0.54884228 0.54884228] Energy of the 1st MO -0.5785538598315292
C1 [ 1.21245192 -1.21245192] Energy of the 2nd MO 0.6711434919142547

3. 得られた分子軌道から、第二量子化表現の電子のハミルトニアン\(H_{electron}\)を構築する#

この部分については、通常の量子化学計算と同じである。 量子化学計算では、

[23]:
from qchem_util import get_molecular_hamiltonian_from_fcidump
# 第二量子化された電子のハミルトニアンを構築し、fcidump 形式で保存
tools.fcidump.from_scf(mean_field_wavefunction, 'fcidump.rhf')
# 保存した第二量子化ハミルトニアンを確認
!cat fcidump.rhf
 &FCI NORB=   2,NELEC= 2,MS2=0,
  ORBSYM=1,1,
  ISYM=1,
 &END
 0.6747559268144482    1    1    1    1
 0.6637114013508137    1    1    2    2
 0.1812104620151971    2    1    2    1
 0.6637114013508137    2    2    1    1
 0.6976515044904633    2    2    2    2
 -1.253309786645977    1    1  0  0
 -0.4750688487721758    2    2  0  0
 0.7151043390810812  0  0  0  0

さて、fcidump.rhf の中身を見てみよう。 fcidumpには電子のハミルトニアン \(H_{electron} = \sum_{pq} T_{pq} c^\dagger_p c_q + \sum_{pqrs} V_{pqrs} c^\dagger_p c^\dagger_q c_r c_s\) の係数\(T\)\(V\)の情報が以下のように記載されている。(注: fcidumpでは、インデックスの並びが \(V_{psqr}\)となっている)

0.6747559268144482    1    1    1    1  ← V_{1111}
0.6637114013508137    1    1    2    2  ← V_{1221}
0.1812104620151971    2    1    2    1 ← V_{2211}
0.6637114013508137    2    2    1    1 ← V_{2112}
0.6976515044904633    2    2    2    2 ← V_{2222}
-1.253309786645977    1    1  0  0  ← T_{11}
-0.4750688487721758    2    2  0  0 ← T_{22}
0.7151043390810812  0  0  0  0 ← 定数

次に、OpenFermionプログラムをつかって、この第二量子化ハミルトニアンを確認してみよう。 出力された内容の見方であるが、以下の1行を例にとってみよう。

((0, 1), (0, 1), (0, 0), (0, 0)) 0.3373779634072241

この場合、\((0, 1)\)は、\(c^{\dagger}_0\)という0番目の軌道に電子を生成する演算子を示しており、\((0, 0)\)は、\(c_0\)という0番目の軌道の電子を消去する演算子である。最後の数値が、\(V_{0000}\)に相当する。よって、この行は\(V_{0000}c^{\dagger}_0c^{\dagger}_0c_0c_0\)を意味している。fcidumpより、行数が多いのは、fcidumpは\(V\)\(T\)に内在する対称性を活かして情報を圧縮しているからである。

[28]:
fermion_hamiltonian = get_molecular_hamiltonian_from_fcidump('fcidump.rhf')
print (fermion_hamiltonian)
Parsing fcidump.rhf
() 0.7151043390810812
((0, 1), (0, 0)) -1.253309786645977
((1, 1), (1, 0)) -1.253309786645977
((2, 1), (2, 0)) -0.4750688487721758
((3, 1), (3, 0)) -0.4750688487721758
((0, 1), (0, 1), (0, 0), (0, 0)) 0.3373779634072241
((0, 1), (0, 1), (2, 0), (2, 0)) 0.09060523100759856
((0, 1), (1, 1), (1, 0), (0, 0)) 0.3373779634072241
((0, 1), (1, 1), (3, 0), (2, 0)) 0.09060523100759856
((0, 1), (2, 1), (0, 0), (2, 0)) 0.09060523100759856
((0, 1), (2, 1), (2, 0), (0, 0)) 0.3318557006754069
((0, 1), (3, 1), (1, 0), (2, 0)) 0.09060523100759856
((0, 1), (3, 1), (3, 0), (0, 0)) 0.3318557006754069
((1, 1), (0, 1), (0, 0), (1, 0)) 0.3373779634072241
((1, 1), (0, 1), (2, 0), (3, 0)) 0.09060523100759856
((1, 1), (1, 1), (1, 0), (1, 0)) 0.3373779634072241
((1, 1), (1, 1), (3, 0), (3, 0)) 0.09060523100759856
((1, 1), (2, 1), (0, 0), (3, 0)) 0.09060523100759856
((1, 1), (2, 1), (2, 0), (1, 0)) 0.3318557006754069
((1, 1), (3, 1), (1, 0), (3, 0)) 0.09060523100759856
((1, 1), (3, 1), (3, 0), (1, 0)) 0.3318557006754069
((2, 1), (0, 1), (0, 0), (2, 0)) 0.3318557006754069
((2, 1), (0, 1), (2, 0), (0, 0)) 0.09060523100759856
((2, 1), (1, 1), (1, 0), (2, 0)) 0.3318557006754069
((2, 1), (1, 1), (3, 0), (0, 0)) 0.09060523100759856
((2, 1), (2, 1), (0, 0), (0, 0)) 0.09060523100759856
((2, 1), (2, 1), (2, 0), (2, 0)) 0.34882575224523166
((2, 1), (3, 1), (1, 0), (0, 0)) 0.09060523100759856
((2, 1), (3, 1), (3, 0), (2, 0)) 0.34882575224523166
((3, 1), (0, 1), (0, 0), (3, 0)) 0.3318557006754069
((3, 1), (0, 1), (2, 0), (1, 0)) 0.09060523100759856
((3, 1), (1, 1), (1, 0), (3, 0)) 0.3318557006754069
((3, 1), (1, 1), (3, 0), (1, 0)) 0.09060523100759856
((3, 1), (2, 1), (0, 0), (1, 0)) 0.09060523100759856
((3, 1), (2, 1), (2, 0), (3, 0)) 0.34882575224523166
((3, 1), (3, 1), (1, 0), (1, 0)) 0.09060523100759856
((3, 1), (3, 1), (3, 0), (3, 0)) 0.34882575224523166

4. OpenFermionなどを使って、\(H_{electron}\)\(H_{qubit}\)に変換する#

ここまでで、\(H_{electron}\)が計算できたので、最後に\(H_{qubit}\)への変換をおこなう。 この変換方法はいくつかある。代表的なものを3つあげよう。 1. Jordan-Wigner変換 2. Parity変換 3. Bravyi-Kitaev変換 本演習では、以下で1と3の2つの変換法を見てみる。

Jordan-Wigner 変換#

Jordan-Wigner変換は、最も直感的な変換である。 一つ一つの量子ビットをスピン分子軌道に対応させ、0だと、電子が詰まっておらず、1だと電子が詰まっていると考える。例えば、0011 だと、右から1番目の軌道と、右から2番目の軌道に電子が入っている電子状態を示している。

この占有数の情報を変更するのが、\(c^\dagger_i\)\(c_i\)なのだから、同じことをパウリ演算子で、できるようになれば良い。パウリ演算子を使って定義される以下の演算子は、あるqubit(=軌道)の値を0から1に、1から0に変更できる

\[P_{+} = \frac{X-iY}{2}\]
\[P_{-} = \frac{X+iY}{2}\]

しかしながら、この2つの演算子はフェルミオン(電子)の演算子の交換関係\([c^\dagger_p,c_q]=\delta_{pq}\)を満たさない。これは、\(P_{+/-}\)にフェルミンの特徴である、粒子の交換に対する反対称性がエンコードされていないためである。フェルミオンの波動関数はよく知らているように、粒子の交換に対して符号が変わるという性質を持っている。この性質は、\(P_{+/-,i}\)が作用するサイト(軌道)より前にいくつ電子があるかを数えればわかる。これは、\(i\)より前のサイトに\(Z\)をかけていけばわかる。

\[Q_i=\prod_{j < i} Z_j\]

\(Q_i\)は、電子が\(i\)より前に偶数個あれば、交換を偶数回繰り返すので、符号は変えず、奇数個であれば、符号を変化させる。この\(Q_i\)と、\(P_{+/-}\)を組み合わせれば、\(c^{\dagger}_p\),\(c_p\)と一対一で対応する演算子をパウリ演算子を使って構築できる。

\[c^{\dagger}_p = P_{+,i}Q_{i}\]

では、この変換をOpenFermionを使って実行してみよう。

[33]:
jw_qubit_hamiltonian = jordan_wigner(get_fermion_operator(fermion_hamiltonian))
print (jw_qubit_hamiltonian)
(-0.09706626816762849+0j) [] +
(-0.04530261550379928+0j) [X0 X1 Y2 Y3] +
(0.04530261550379928+0j) [X0 Y1 Y2 X3] +
(0.04530261550379928+0j) [Y0 X1 X2 Y3] +
(-0.04530261550379928+0j) [Y0 Y1 X2 X3] +
(0.1714128264477689+0j) [Z0] +
(0.16868898170361205+0j) [Z0 Z1] +
(0.12062523483390417+0j) [Z0 Z2] +
(0.16592785033770344+0j) [Z0 Z3] +
(0.17141282644776892+0j) [Z1] +
(0.16592785033770344+0j) [Z1 Z2] +
(0.12062523483390417+0j) [Z1 Z3] +
(-0.2234315369081355+0j) [Z2] +
(0.17441287612261583+0j) [Z2 Z3] +
(-0.2234315369081355+0j) [Z3]

Jordan-Wigner変換のメリットは、占有数表示という我々の理解しやすい描像を保ったまま、Hamiltonianを変換できる点にある。 デメリットとしては、\(O(N)\)の長さを持つパウリ演算子の積が現れることである。 \(H_{electron}\)\(O(N^4)\)のタームがあるため、\(H_{qubit}\)に現れるハミルトニアンのパウリ演算子の数は\(O(N^5)\)となる。

Bravyi-Kitaev#

詳細は省くが、Bravyi-Kitaev変換は、我々の理解しやすい占有数表示から離れることで、 フェルミオンの演算子を表すのに必要なパウリ演算子の数を\(O(logN)\)に減らすことができる方法となっている。 このBravyi-Kitaev変換を実行してみよう。

[52]:
bk_qubit_hamiltonian = bravyi_kitaev(get_fermion_operator(fermion_hamiltonian))
print (bk_qubit_hamiltonian)
(-0.09706626816762849+0j) [] +
(0.04530261550379928+0j) [X0 Z1 X2] +
(0.04530261550379928+0j) [X0 Z1 X2 Z3] +
(0.04530261550379928+0j) [Y0 Z1 Y2] +
(0.04530261550379928+0j) [Y0 Z1 Y2 Z3] +
(0.1714128264477689+0j) [Z0] +
(0.17141282644776892+0j) [Z0 Z1] +
(0.16592785033770344+0j) [Z0 Z1 Z2] +
(0.16592785033770344+0j) [Z0 Z1 Z2 Z3] +
(0.12062523483390417+0j) [Z0 Z2] +
(0.12062523483390417+0j) [Z0 Z2 Z3] +
(0.16868898170361205+0j) [Z1] +
(-0.2234315369081355+0j) [Z1 Z2 Z3] +
(0.17441287612261583+0j) [Z1 Z3] +
(-0.2234315369081355+0j) [Z2]

この系が非常に小さいため、Jordan-Wigner変換と大きな違いは見えないが、4体のパウリ演算子からなる項が一つ減っていることがわかる。

また、この変換の際に、粒子数やSzなどの量子数の保存を考慮すると、それぞれの自由度に応じて、必要な量子ビット数を一つずつ、系二個減らすことができる。(Qubit tapering) この対称性を考慮した変換を実行してみよう。

[54]:
active_orbitals = 4; active_fermions = 2
symmetry_conserving_bravyi_kitaev(get_fermion_operator(fermion_hamiltonian),active_orbitals,active_fermions)
[54]:
-0.3383167378354368 [] +
0.1812104620151971 [X0 X1] +
0.3948443633559044 [Z0] +
0.011246157150821001 [Z0 Z1] +
0.39484436335590445 [Z1]

この系はもともと4qubitしか使っていなかったこともあり、2個qubit減ることで、大幅にシンプルなハミルトニアンが得られている

[53]:

[53]: