Skip to main content
IBM Quantum Platform

FermionOperator

class FermionOperator(coeffs, actions, modes, boundaries)

ベース: object

スピンを持たないフェルミオン演算子。


定義

この演算子は、スピンを持たないフェルミオンモードに作用するフェルミオン生成演算子および消滅演算子の積の線形結合によって定義される。 つまり、個々の項は以下の反交換関係を満たす: [1]

{ai†,aj†}={ai,aj}=0,  and  {ai,aj†}=δij ,\left\{a^\dagger_i, a^\dagger_j\right\} = \left\{a_i, a_j\right\} = 0,~~\text{and}~~ \left\{a_i, a^\dagger_j\right\} = \delta_{ij} \, ,

ここで、 ii および jj は、それぞれがインデックスを付けるフェルミオンモードのスピン種を区別しない。

これにより、演算子全体の定義は次のようになります:

FermionOperator=∑ici⨂jAj^ ,\text{\texttt{FermionOperator}} = \sum_i c_i \bigotimes_j \hat{A_j} \, ,

ここで、 Aj^∈{aj,aj†}\hat{A_j} \in \{ a_j, a^\dagger_j \}、 cic_i は、積の線形結合を構成する(複素)係数である。 インデックス jj は、0 から、その演算子が作用するフェルミオンモードの数から 1 を引いた値までの間の任意の値をとることができます。


実装

このクラスは、疎行列で一般的に使用される「 圧縮疎行形式 」と同様に、項と係数を複数の疎ベクトルに格納します。 より具体的に言えば、1つの演算子には4つの配列が含まれています:

コラム「 1 」
コラム「 2 」
coeffs2つの64ビット浮動小数点数からなる複素係数のベクトル。
actions第2量子化処理の性質を格納するブール値のベクトル。
modes作用を受けたフェルミオンモードのインデックスを格納する32ビット整数のベクトル。
boundariesおよび actions における境界を示す整数のベクトル modes。

() で actions 示された項目は、 True (False) による生成(消滅)演算子を表します。でインデックス付けされたフェルミオンモードは、スピンを持たないものと modes みなされます。

注

これらの内部配列の読み取り専用コピー には、それぞれのメソッド( get_coeffs(), get_actions(), get_modes(), および )を通じてアクセスできます get_boundaries()。

このデータ構造により、演算子の構築や操作を非常に効率的に行うことができます。 しかし、これは、演算子の中にいつでも重複する項が含まれている可能性があることを意味します。 これらは、. を使用して手動で解決する必要があります simplify()。

建設

上記の配列を指定することで、演算子を直接構築することができます:

>>> from qiskit_fermions.operators import FermionOperator
>>> coeffs = [1.0, 2.0, -3.0, 4.0j, -0.5j]
>>> actions = [True, False, False, True, True, True, False, False]
>>> modes = [0, 0, 0, 1, 0, 1, 2, 3]
>>> boundaries = [0, 0, 1, 2, 4, 8]
>>> op = FermionOperator(coeffs, actions, modes, boundaries)
>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
 -3.000000e0 +0.000000e0j * (-0)
  0.000000e0 +4.000000e0j * (-0 +1)
  2.000000e0 +0.000000e0j * (+0)
 -0.000000e0-5.000000e-1j * (+0 +1 -2 -3)

便宜上、 Python 辞書から次のように演算子を構築することができます:

>>> from qiskit_fermions.operators import cre, ann
>>> op = FermionOperator.from_dict(
...     {
...         (): 1.0,
...         (cre(0),): 2.0,
...         (ann(0),): -3.0,
...         (ann(0), cre(1)): 4.0j,
...         (cre(0), cre(1), ann(2), ann(3)): -0.5j,
...     }
... )
>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
 -3.000000e0 +0.000000e0j * (-0)
  0.000000e0 +4.000000e0j * (-0 +1)
  2.000000e0 +0.000000e0j * (+0)
 -0.000000e0-5.000000e-1j * (+0 +1 -2 -3)

この例では、指定されたモードにおける生成演算子および消滅演算子を作成するために ann() 、 cre() およびを活用しました。

さらに、以下の構築メソッドおよびクイックヘルパーメソッドが利用可能です:

コラム「 1 」
コラム「 2 」
zero()加法単位演算子を構築します。
one()乗法単位演算子を構築します。
from_terms(用語)項のイテレータから新しい演算子を構築します(こちらも参照 iter_terms())。
from_terms_with_groups(用語)グループを含む項のイテレータから、新しい演算子を構築します(こちらも参照 iter_terms_with_groups())。

フォーマット設定

上記の例では、構築された演算子は の出力を用いて表示されており format()、その結果、人間が読みやすい形式の演算子が得られています。

>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
 -3.000000e0 +0.000000e0j * (-0)
  0.000000e0 +4.000000e0j * (-0 +1)
  2.000000e0 +0.000000e0j * (+0)
 -0.000000e0-5.000000e-1j * (+0 +1 -2 -3)
注

の印刷順序は、印刷前に明示的にソート format(op) されます。 したがって、演算子内の項の順序を反映しているわけではありません。

この関数 repr() から別の形式を取得することができ、その結果、 Python で解釈可能な表現が得られます。 つまり、この出力を Python のシェルにそのままコピーして貼り付けることができます:

>>> print(repr(op))
FermionOperator.from_dict({...})

最後に、大規模なオペレーターの場合、これら2つの出力はどちらも非常に長くなり、望ましくない結果となる可能性があります。 すると、この関数 str() から、必要最低限の情報のみを含む非常にシンプルなフォームを取得することができます:

>>> print(str(op))
<FermionOperator with 5 terms>

反復

基礎となるデータ構造はRustで実装されており、そのレイアウトも単純ではないため、直接反復処理を行うことはできません:

>>> list(iter(op))
Traceback (most recent call last):
  ...
TypeError: 'qiskit_fermions.operators.fermion_operator.FermionOperator' object is not iterable

その代わりに、このクラスはこの目的を果たすためのカスタムイテレータを提供しています:

>>> list(sorted(op.iter_terms()))
[([], (1+0j)), ([(False, 0)], (-3+0j)), ([(False, 0), (True, 1)], 4j), ([(True, 0)], (2+0j)), ([(True, 0), (True, 1), (False, 2), (False, 3)], (-0-0.5j))]
関連資料

iter_terms()

実装に関する詳細については、以下をご覧ください。

以下の表には、利用可能なすべてのイテレータが一覧表示されています:

コラム「 1 」
コラム「 2 」
iter_terms()演算子の項を順にたどるイテレータ。
iter_terms_with_groups()演算子の項と、それに関連付けられた群のインデックスを格納するイテレータ。

算数

以下の算術演算がサポートされています:

足し算・引き算

>>> op = FermionOperator.one()
>>> (op + op).simplify()
FermionOperator.from_dict({(): 2+0j})
>>> (op - op).simplify()
FermionOperator.from_dict({})
>>> op += op
>>> op.simplify()
FermionOperator.from_dict({(): 2+0j})
>>> op -= op
>>> op.simplify()
FermionOperator.from_dict({})

スカラーの乗算・除算

>>> op = FermionOperator.one()
>>> (2 * op).simplify()
FermionOperator.from_dict({(): 2+0j})
>>> (op / 2).simplify()
FermionOperator.from_dict({(): 0.5+0j})
>>> op *= 2
>>> op.simplify()
FermionOperator.from_dict({(): 2+0j})
>>> op /= 2
>>> op.simplify()
FermionOperator.from_dict({(): 1+0j})

オペレーターの構成

注

演算子の合成は左乗法に対応します: は C=BAC = B A に対応 c = a & b します。つまり、2つの演算子を合成すると、「まず を行い a 、次に を行う」という動作をする結果の演算子が得られます。 b

>>> op1 = FermionOperator.from_dict({(): 2.0, (cre(0),): 3.0})
>>> op2 = FermionOperator.from_dict({(): 1.5, (ann(1),): 4.0})
>>> comp = (op1 & op2).simplify()
>>> print(format(comp))
  3.000000e0 +0.000000e0j * ()
  8.000000e0 +0.000000e0j * (-1)
  1.200000e1 +0.000000e0j * (-1 +0)
  4.500000e0 +0.000000e0j * (+0)
>>> op2 &= op1
>>> print(format(op2.simplify()))
  3.000000e0 +0.000000e0j * ()
  8.000000e0 +0.000000e0j * (-1)
  4.500000e0 +0.000000e0j * (+0)
  1.200000e1 +0.000000e0j * (+0 -1)
>>> squared = (op1 ** 2).simplify()
>>> print(format(squared))
  4.000000e0 +0.000000e0j * ()
  1.200000e1 +0.000000e0j * (+0)
  9.000000e0 +0.000000e0j * (+0 +0)
注

便宜上、右乗算は によって実装されており c = a @ b (その結果、 C=ABC = A B となる)。

>>> (op1 @ op2).equiv(op2 & op1)
True

その他の操作

上記の算術演算に対応するマジックメソッドに加え、以下のメソッドも利用可能です:

コラム「 1 」
コラム「 2 」
adjoint()この演算子のエルミート共役(または随伴)を返します。
ichop( [アトール] )指定された閾値未満の係数の絶対値を持つ項を除去します。
simplify( [アトール] )同等だが簡略化された演算子を返します。
normal_ordered( [サンドイッチ] )通常の順序を持つ項を持つ等価演算子を返します。
relabel_modes(順列)モードのラベルが変更された新しい演算子を返します。

プロパティ-

最後に、演算子の特定の性質を確認するためのさまざまな方法があります:

コラム「 1 」
コラム「 2 」
is_hermitian( [アトール] )この演算子がエルミート演算子であるかどうかを返します。
max_rank()この演算子に含まれる項の最大ランクを返します。
conserves_particle_number()この演算子が粒子数の保存性を満たすかどうかを返します。

[ 1 ]

https://en.wikipedia.org/wiki/Second _quantization#フェルミオンの生成・消滅演算子


属性

groups

各項に対するグループインデックスのベクトル(オプション)。

詳細については、当該モジュ grouping ールを参照してください。


方法

adjoint

adjoint()

この演算子のエルミート共役(または随伴)を返します。

これにより、項と係数には次のような影響が生じます:

  • 各項における作用は順序が逆転し、生成と消滅が交互に繰り返される
  • 係数は複素共役である
>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): -1.0j, ((True, 0), (False, 1)): 1.0})
>>> adj = op.adjoint()
>>> print(format(adj))
 -0.000000e0 +1.000000e0j * ()
  1.000000e0 -0.000000e0j * (+1 -0)
conserves_particle_number

conserves_particle_number()

この演算子が粒子数の保存性を満たすかどうかを返します。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({((True, 0), (False, 1)): 1})
>>> op.conserves_particle_number()
True
>>> op = FermionOperator.from_dict({((True, 0),): 1})
>>> op.conserves_particle_number()
False

戻り値

この演算子が粒子数保存であるかどうか。

conserves_sector

conserves_sector(block_sizes)

各モードブロック内で、すべての項が粒子数を保存しているかどうかを返します。

block_sizes モード範囲を、連続し、互いに重ならないブロックに分割する。各ブロックはモード を網羅 b し、 [start_b, start_b + block_sizes[b]) ここで は先行するブロックのサイズの合計である start_b 。 ある項がセクターを保存するのは、 すべてのブロックにおいて、その生成演算子の数が消滅演算子の数と等しい場合に限る。 最終ブロックを超えたモードに作用する項は、セクターを保存しない。

空の は、すべてのモードを単一のブロックとして扱う block_sizes ため、これは と同等になります conserves_particle_number()。 1つのブロックは、スピンを持たないFCIセクターにおける保存則を検証 [norb] し、2つの等しいブロックは、アルファモード [0, norb) とベータモードがそれぞれ保存されている [norb, 2 * norb) こと、すなわち粒子数とスピンのz成分の両方が保存されていることを検証 [norb, norb] する。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({((True, 0), (False, 2)): 1})
>>> op.conserves_sector([4])  # one spinless block of 4 orbitals
True
>>> op.conserves_sector([2, 2])  # moves a particle from the alpha block to the beta block
False

パラメーター

block_sizes – 連続するモードブロックのサイズ。各ブロックは、このサイズを維持しなければならない。

戻り値

各項が、各モードブロック内で粒子数を保存するかどうか。

equiv

equiv(other, atol=1e-08)

この演算子が別の演算子と等価であるかどうかを確認します。

この文脈における「等価性」とは、指定された絶対許容誤差の範囲内での近似的な等しさを意味します。 より正確に言えば、このメソッドは True、差分 に含まれる係数の絶対値がすべて、指定された閾値 を下回る other - self 場合に を返します atol。

注

これは、ほとんどの場合、求めている数学的な比較です。 これは、許容誤差や簡略化を行わずに、 格納された項(その係数、アクション、モード、および内部項の境界)の完全な等価性を検査する演算 == 子とは異なります。 したがって、数学的には等しい2つの演算子であっても、保存方法が異なれば == 、その下では不等となる可能性があります。例えば、簡約されていない と を a + a 比較した場合や 2 * a、項の順序が異なる場合などが挙げられます。 を使用して、数値許容誤差の範囲内で演算子を比較 equiv します。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 1e-7})
>>> zero = FermionOperator.zero()
>>> op.equiv(zero)
False
>>> op.equiv(zero, 1e-6)
True
>>> op.equiv(zero, 1e-9)
False

パラメーター

  • その他 – 比較対象となるもう一方の演算子。
  • atol – 比較における絶対許容誤差。 この値のデフォルトは 1e-8. です。
from_1body_tril_spin

classmethod from_1body_tril_spin(one_body_a, one_body_b, norb)

個別のスピン種の三角形1体積分を用いて演算子を構築する。

その結果得られる演算子は、次のように定義される

∑iciiαai†ai+ciiβai+n†ai+n+∑i<jcijα(ai†aj+aj†ai)+cijβ(ai+n†aj+n+aj+n†ai+n)\sum_i c^\alpha_{ii} a^\dagger_i a_i + c^\beta_{ii} a^\dagger_{i+n} a_{i+n} + \sum_{i \lt j} c^\alpha_{ij} (a^\dagger_i a_j + a^\dagger_j a_i) + c^\beta_{ij} (a^\dagger_{i+n} a_{j+n} + a^\dagger_{j+n} a_{i+n})

ここで、 cαc^\alpha ( cβc^\beta )はそれぞれ( one_body_a``one_body_b , )に格納された積分係数であり、 ii および jj は、配列を参照するための三角添字 ijij から展開された添字であり、 nn は軌道数である norb。

結果として得られる演算子は、ブロックスピン秩序を持つ 2n2n のスピンを持たないフェルミオンモードに作用する。すなわち、モード 0,…,n−10, \dots, n-1 は α\alpha スピン軌道であり、モード n,…,2n−1n, \dots, 2n-1 は β\beta スピン軌道である(したがって、 β\beta スピン種の軌道 ii はモード i+ni+n となる)。

>>> import numpy as np
>>> from qiskit_fermions.operators import FermionOperator
>>> one_body_a = np.array([1.0, 2.0, 3.0])
>>> one_body_b = np.array([-1.0, -2.0, -3.0])
>>> op = FermionOperator.from_1body_tril_spin(one_body_a, one_body_b, norb=2)
>>> print(format(op))
  1.000000e0 +0.000000e0j * (+0 -0)
  2.000000e0 +0.000000e0j * (+0 -1)
  2.000000e0 +0.000000e0j * (+1 -0)
  3.000000e0 +0.000000e0j * (+1 -1)
 -1.000000e0 +0.000000e0j * (+2 -2)
 -2.000000e0 +0.000000e0j * (+2 -3)
 -2.000000e0 +0.000000e0j * (+3 -2)
 -3.000000e0 +0.000000e0j * (+3 -3)

パラメーター

  • one_body_a – 長さ n∗(n+1)/2n * (n + 1) / 2 の1次元配列。 α\alpha スピン種の1体電子積分係数を、平坦化された三角行列として格納する。
  • one_body_b – 長さ n∗(n+1)/2n * (n + 1) / 2 の1次元配列。 β\beta スピン種の1体電子積分係数を、平坦化された三角行列として格納している。
  • norb – 軌道数、 nn。

戻り値

上記で定義された電子構造ハミルトニアンの1粒子成分。

from_1body_tril_spin_sym

classmethod from_1body_tril_spin_sym(one_body_a, norb)

スピン対称な三角形の1体積分から演算子を構成する。

その結果得られる演算子は、次のように定義される

∑iciiα(ai†ai+ai+n†ai+n)+∑i<jcijα(ai†aj+aj†ai+ai+n†aj+n+aj+n†ai+n)\sum_i c^\alpha_{ii} (a^\dagger_i a_i + a^\dagger_{i+n} a_{i+n}) + \sum_{i \lt j} c^\alpha_{ij} (a^\dagger_i a_j + a^\dagger_j a_i + a^\dagger_{i+n} a_{j+n} + a^\dagger_{j+n} a_{i+n})

ここで、 cαc^\alpha はに格納された積分係数であり one_body_a、 ii および jj は、配列をインデックス付けする三角インデックス ijij から展開されたインデックスであり、 nn は軌道数である norb。

結果として得られる演算子は、ブロックスピン秩序を持つ 2n2n のスピンを持たないフェルミオンモードに作用する。すなわち、モード 0,…,n−10, \dots, n-1 は α\alpha スピン軌道であり、モード n,…,2n−1n, \dots, 2n-1 は β\beta スピン軌道である(したがって、 β\beta スピン種の軌道 ii はモード i+ni+n となる)。

>>> import numpy as np
>>> from qiskit_fermions.operators import FermionOperator
>>> one_body_a = np.array([1.0, 2.0, 3.0])
>>> op = FermionOperator.from_1body_tril_spin_sym(one_body_a, norb=2)
>>> print(format(op))
  1.000000e0 +0.000000e0j * (+0 -0)
  2.000000e0 +0.000000e0j * (+0 -1)
  2.000000e0 +0.000000e0j * (+1 -0)
  3.000000e0 +0.000000e0j * (+1 -1)
  1.000000e0 +0.000000e0j * (+2 -2)
  2.000000e0 +0.000000e0j * (+2 -3)
  2.000000e0 +0.000000e0j * (+3 -2)
  3.000000e0 +0.000000e0j * (+3 -3)

パラメーター

  • one_body_a – 長さ n∗(n+1)/2n * (n + 1) / 2 の1次元配列。 α\alpha スピン種の1体電子積分係数を、平坦化された三角行列として格納する。
  • norb – 軌道数、 nn。

戻り値

上記で定義された電子構造ハミルトニアンの1粒子成分。

from_2body_tril_spin

classmethod from_2body_tril_spin(two_body_aa, two_body_ab, two_body_bb, norb)

個別のスピン種の三角形2体積分から演算子を構築する。

その結果得られる演算子は、次のように定義される

∑ijkl12∑(i,j,k,l)∈P(ijkl)cijklααai†ak†alaj+cijklββai+n†ak+n†al+naj+n+∑ijkl12∑(i,j,k,l)∈P′(ijkl)cijklαβai+n†ak†alaj+n+cijklαβai†ak+n†al+naj+\sum_{ijkl} \frac{1}{2} \sum_{(i,j,k,l) \in \mathcal{P}(ijkl)} c^{\alpha\alpha}_{ijkl} a^\dagger_i a^\dagger_k a_l a_j + c^{\beta\beta}_{ijkl} a^\dagger_{i+n} a^\dagger_{k+n} a_{l+n} a_{j+n} + \sum_{ijkl} \frac{1}{2} \sum_{(i,j,k,l) \in \mathcal{P'}(ijkl)} c^{\alpha\beta}_{ijkl} a^\dagger_{i+n} a^\dagger_k a_l a_{j+n} + c^{\alpha\beta}_{ijkl} a^\dagger_i a^\dagger_{k+n} a_{l+n} a_j +

ここで、 cααc^{\alpha\alpha} ( cαβc^{\alpha\beta}, cββc^{\beta\beta} )はそれぞれ( two_body_aa``two_body_ab , two_body_bb,)に格納された積分係数であり、 ijklijkl は配列の連番であり、 P\mathcal{P} ( P′\mathcal{P'} )は4インデックス (i,j,k,l)(i,j,k,l) (後述)の一意的な順列を生成し、 nn は軌道数である norb。

二体係数は、化学的順序付けにおいて、 (ij∣kl)(ij|kl) となることが予想される。すなわち、2つの添字の組 (i,j)(i,j) および (k,l)(k,l) は、それぞれ電荷密度を表す。 12\frac{1}{2} の因子は、従来の二体事前因子である。

結果として得られる演算子は、ブロックスピン秩序を持つ 2n2n のスピンを持たないフェルミオンモードに作用する。すなわち、モード 0,…,n−10, \dots, n-1 は α\alpha スピン軌道であり、モード n,…,2n−1n, \dots, 2n-1 は β\beta スピン軌道である(したがって、 β\beta スピン種の軌道 ii はモード i+ni+n となる)。

注

two_body_aa および は、 S8-fold の対称配列である two_body_bb 。 つまり、これらは、形状が である行列の、平坦化された下三角データであり (npair, npair)、ここで である npair = (norb * (norb + 1) // 2。 これらは、形状 を持つ4次元配列の下三角データである (norb, norb, norb, norb)。 したがって、上記の P\mathcal{P} は、平坦化されたインデックス ijklijkl を、これらの4次元配列をインデックス付けするすべてのインデックスの順列 (i,j,k,l)(i,j,k,l) に展開します。

ただし、 S4-foldtwo_body_ab は対称であるにすぎない。 したがって、これには行列 (npair, npair) の全データが含まれています(ただし、依然として平坦化された形式です)。 P′\mathcal{P'} は、対応するインデックスの展開を行います。 (上記の定義では、表記上の便宜上、インデックス ijklijkl を再利用しました。)

>>> import numpy as np
>>> from qiskit_fermions.operators import FermionOperator
>>> two_body_aa = np.arange(1, 7, dtype=float)
>>> two_body_ab = np.arange(11, 20, dtype=float)
>>> two_body_bb = np.arange(-1, -7, -1, dtype=float)
>>> op = FermionOperator.from_2body_tril_spin(two_body_aa, two_body_ab, two_body_bb, norb=2)
>>> len(op)
64

パラメーター

  • two_body_aa – αα\alpha\alpha -スピン種の S8-fold 対称2体電子積分係数の1次元配列で、フラット化された配列として表現される。
  • two_body_ab – αβ\alpha\beta -スピン種の S4-fold 対称な2体電子積分係数を格納した1次元配列。フラット化された配列として表現される。
  • two_body_bb – ββ\beta\beta のスピン種における、 S8-fold の対称2体電子積分係数を格納した1次元配列(フラット化された配列として)。
  • norb – 軌道数、 nn。

戻り値

上記で定義された電子構造ハミルトニアンの2体成分。

from_2body_tril_spin_sym

classmethod from_2body_tril_spin_sym(two_body_aa, norb)

スピン対称な三角形の2体積分を用いて演算子を構成する。

その結果得られる演算子は、次のように定義される

∑ijkl12cijklαα∑(i,j,k,l)∈P(ijkl)(ai†ak†alaj+ai+n†ak†alaj+n+ai†ak+n†al+naj+ai+n†ak+n†al+naj+n)\sum_{ijkl} \frac{1}{2} c^{\alpha\alpha}_{ijkl} \sum_{(i,j,k,l) \in \mathcal{P}(ijkl)} (a^\dagger_i a^\dagger_k a_l a_j + a^\dagger_{i+n} a^\dagger_k a_l a_{j+n} + a^\dagger_i a^\dagger_{k+n} a_{l+n} a_j + a^\dagger_{i+n} a^\dagger_{k+n} a_{l+n} a_{j+n})

ここで、 cααc^{\alpha\alpha} はに格納された積分係数であり two_body_aa、 ijklijkl は配列の累積インデックス、 P\mathcal{P} は4インデックス (i,j,k,l)(i,j,k,l) (後述)の一意な順列を生成し、 nn は軌道の数である norb。

二体係数は、化学的順序付けにおいて、 (ij∣kl)(ij|kl) となることが予想される。すなわち、2つの添字の組 (i,j)(i,j) および (k,l)(k,l) は、それぞれ電荷密度を表す。 12\frac{1}{2} の因子は、従来の二体事前因子である。

結果として得られる演算子は、ブロックスピン秩序を持つ 2n2n のスピンを持たないフェルミオンモードに作用する。すなわち、モード 0,…,n−10, \dots, n-1 は α\alpha スピン軌道であり、モード n,…,2n−1n, \dots, 2n-1 は β\beta スピン軌道である(したがって、 β\beta スピン種の軌道 ii はモード i+ni+n となる)。

注

two_body_aa S8-fold の対称配列である。 つまり、これは形状 の行列の (npair, npair)、平坦化された下三角データであり、ここで である npair = (norb * (norb + 1) // 2。 これは、形状 を持つ4次元配列の下三角データに相当する (norb, norb, norb, norb)。 したがって、上記の P\mathcal{P} は、平坦化されたインデックス ijklijkl を、この4次元配列を参照するすべてのインデックスの順列 (i,j,k,l)(i,j,k,l) に展開します。

>>> import numpy as np
>>> from qiskit_fermions.operators import FermionOperator
>>> two_body_aa = np.arange(1, 7, dtype=float)
>>> op = FermionOperator.from_2body_tril_spin_sym(two_body_aa, norb=2)
>>> len(op)
64

パラメーター

  • two_body_aa – αα\alpha\alpha -スピン種の S8-fold 対称2体電子積分係数の1次元配列で、フラット化された配列として表現される。
  • norb – 軌道数、 nn。

戻り値

上記で定義された電子構造ハミルトニアンの2体成分。

from_dict

classmethod from_dict(data)

辞書から新しい演算子を生成します。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict(
...     {
...         (): 1.0-1.0j,
...         ((True, 0), (False, 1)): 2.0,
...     }
... )
>>> print(format(op))
  1.000000e0 -1.000000e0j * ()
  2.000000e0 +0.000000e0j * (+0 -1)

パラメーター

data – 項のタプルを複素係数に写像する辞書。 各キーは、p (bool, int) 組のタプルです。 と cre() を使用すると ann() 、その構成を簡略化できます。

戻り値

新しいオペレーター。

from_fcidump

classmethod from_fcidump(fcidump)

データ FCIDump 構造 FermionOperator から を構築します。

という名前の FCIDump ファイルがあるとして molecule.fcidump、第2量子化演算子は次のように構築できます:

from qiskit_fermions.operators import FermionOperator
from qiskit_fermions.operators.library import FCIDump

fcidump = FCIDump.from_file("molecule.fcidump")
operator = FermionOperator.from_fcidump(fcidump)

パラメーター

fcidump – FCIDump データ構造。

戻り値

構成演算子。 FCIDumpが定数(例えば、核反発力)のエネルギーを供給する場合、それは恒等項として含まれます ()。

from_terms

classmethod from_terms(terms)

項のイテレータから新しい演算子を構築します(こちらも参照 iter_terms())。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 2.0, ((True, 0),): 1.0, ((False, 1),): -1.0j})
>>> op.equiv(FermionOperator.from_terms(op.iter_terms()))
True

パラメーター

項 – によって生成される項のイテレータ iter_terms()。

戻り値

新しいオペレーター。

from_terms_with_groups

classmethod from_terms_with_groups(terms)

グループを含む項のイテレータから、新しい演算子を構築します(こちらも参照 iter_terms_with_groups())。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator(
...     [2.0, 1.0, -1.0],
...     [True, False, True, False],
...     [0, 1, 1, 0],
...     [0, 0, 2, 4],
... )
>>> op.groups = [0, 1, 1]
>>> reconstructed = FermionOperator.from_terms_with_groups(op.iter_terms_with_groups())
>>> op.equiv(reconstructed) and op.groups == reconstructed.groups
True

パラメーター

項 – によって生成される項のイテレータ iter_terms_with_groups()。

戻り値

新しいオペレーター。

get_actions

get_actions()

オペレータのアクションの読み取り専用リストを返します。

注

このメソッドは、内部データのコピー を返します。

関連資料

内部データ構造の説明はこちらです。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.one()
>>> op += FermionOperator.from_dict({((True, 0), (False, 1)): 1.0})
>>> op.get_actions()
[True, False]

戻り値

事業者の対応の一覧。

get_boundaries

get_boundaries()

演算子の項間の境界を示すインデックスの読み取り専用リストを返します。

注

このメソッドは、内部データのコピー を返します。

関連資料

内部データ構造の説明はこちらです。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.one()
>>> op += FermionOperator.from_dict({((True, 0), (False, 1)): 1.0})
>>> op.get_boundaries()
[0, 0, 2]

戻り値

当該事業者の利用規約の適用範囲の一覧。

get_coeffs

get_coeffs()

演算子の係数からなる読み取り専用のリストを返します。

注

このメソッドは、内部データのコピー を返します。

関連資料

内部データ構造の説明はこちらです。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.one()
>>> op += -1j * FermionOperator.one()
>>> op.get_coeffs()
[(1+0j), -1j]

戻り値

演算子の係数のリスト。

get_modes

get_modes()

オペレータの対象となったモードのインデックスからなる、読み取り専用のリストを返します。

注

このメソッドは、内部データのコピー を返します。

関連資料

内部データ構造の説明はこちらです。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.one()
>>> op += FermionOperator.from_dict({((True, 0), (False, 1)): 1.0})
>>> op.get_modes()
[0, 1]

戻り値

このオペレーターのモードの一覧。

get_support

get_support()

この演算子が作用するモードインデックスの集合を返します。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict(
...     {
...         ((True, 0), (False, 4)): 1,
...         ((True, 1), (True, 3), (False, 4), (False, 7)): 1,
...     }
... )
>>> assert op.get_support() == {0, 1, 3, 4, 7}

戻り値

この演算子が作用するモード指数の集合。

has_groups

has_groups()

この演算子がグループインデックスを追跡しているかどうかを返します。

これは、グループインデックスを確認するために演算子からそれらをコピーしないため op.groups is not None、(確認するのと)同等の処理ですが、より低コストです。

注

これは、が空リスト groups である場合でも True 返されます。これは、項を一切持たないグループ化された演算子の状態です。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator(
...     [1.0, 2.0, -1.0, -2.0],
...     [True, False, True, False, True, False, True, False],
...     [0, 1, 2, 3, 1, 0, 3, 2],
...     [0, 2, 4, 6, 8],
... )
>>> op.has_groups()
False
>>> op.groups = [0, 1, 0, 1]
>>> op.has_groups()
True

戻り値

この演算子にが設定されている groups かどうか。

ichop

ichop(atol=1e-08)

指定された閾値未満の係数の絶対値を持つ項を除去します。

このメソッドは、演算子をその場で変更し、を返します None。

警告

この手法は、係数を貪欲に切り捨ててしまいます! 対象となる演算子に、重複する項に対して個別の係数が含まれている可能性がある場合は、代わりに simplify() を呼び出すことを検討してください!

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 1e-4, ((True, 0),): 1e-6, ((False, 0),): 1e-10})
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()
 1.000000e-10 +0.000000e0j * (-0)
  1.000000e-6 +0.000000e0j * (+0)
>>> op.ichop()
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()
  1.000000e-6 +0.000000e0j * (+0)
>>> op.ichop(1e-5)
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()

パラメーター

atol – カットオフ値の絶対許容誤差。 この値のデフォルトは 1e-8. です。

is_hermitian

is_hermitian(atol=1e-08)

この演算子がエルミート演算子であるかどうかを返します。

注

このチェックは、と self 、その、 adjoint() およびの normal_ordered() 差 equiv() を用いて実装されています zero()。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({
...     ((True, 0), (False, 1)): 1.00001j,
...     ((True, 1), (False, 0)): -1j,
... })
>>> op.is_hermitian()
False
>>> op.is_hermitian(1e-4)
True

パラメーター

atol – 係数が等しいとみなされる数値の精度。 この値のデフォルトは 1e-8. です。

戻り値

この演算子がエルミート演算子であるかどうか。

iter_terms

iter_terms()

演算子の項を巡回するイテレータ。

警告

反復処理の対象となる項目を変更しても、その基となる演算子のデータには影響しません。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 2.0, ((True, 0),): 1.0, ((False, 1),): -1.0j})
>>> list(sorted(op.iter_terms()))
[([], (2+0j)), ([(False, 1)], (-0-1j)), ([(True, 0)], (1+0j))]
iter_terms_with_groups

iter_terms_with_groups()

演算子の項と、それに対応する群のインデックスを保持するイテレータ。

警告

反復処理の対象となる項目を変更しても、その基となる演算子のデータには影響しません。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator(
...     [2.0, 1.0, -1.0],
...     [True, False, True, False],
...     [0, 1, 1, 0],
...     [0, 0, 2, 4],
... )
>>> op.groups = [0, 1, 1]
>>> list(sorted(op.iter_terms_with_groups()))
[([], (2+0j), 0), ([(True, 0), (False, 1)], (1+0j), 1), ([(True, 1), (False, 0)], (-1+0j), 1)]
max_rank

max_rank()

この演算子に含まれる項の最大ランクを返します。

注

最長の項の長さは、演算子の形式によって異なる場合があり、つまり(例えば)演算子の簡約や正規順序付けを行うと、最大ランクが異なる結果となる可能性がある。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({
...     ((True, 0), (False, 1), (True, 2), (False, 3)): 1,
... })
>>> op.max_rank()
4

戻り値

この演算子の最大ランク。

normal_ordered

normal_ordered(sandwich=None)

通常の順序を持つ項を持つ等価演算子を返します。

演算子項の通常の順序は、すべての生成作用がすべての消滅作用よりも前に現れるように定義される。 各グループ内では、作用を受けるモードは辞書順に並べられます。 順序が昇順か降順かは、引 sandwich 数の値によって決まります:

  • None (デフォルト): 両方のグループは辞書順で降順に並べ替えられます(例: +1 +0 -1 -0)
  • True: 中央に向かってより大きな添字が現れる。つまり、生成作用は辞書順に昇順で、消滅作用は降順で並んでいる(例: +0 +1 -1 -0)
  • False: 中央に向かってインデックスが小さくなる。つまり、生成アクションは辞書順で降順になり、消滅アクションは昇順になる(例: +1 +0 -0 -1)
注

項の順序を変更する際には、反交換関係を考慮に入れる必要があります( aiaj†=δij−aj†aia_i a^\dagger_j = \delta_{ij} - a^\dagger_j a^i )。これにより、項の数が変わる可能性があります。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({((False, 1), (True, 1), (False, 0), (True, 0)): 1})
>>> print(format(op.normal_ordered().simplify()))
  1.000000e0 +0.000000e0j * ()
 -1.000000e0 +0.000000e0j * (+0 -0)
 -1.000000e0 +0.000000e0j * (+1 -1)
 -1.000000e0 +0.000000e0j * (+1 +0 -1 -0)
>>> print(format(op.normal_ordered(sandwich=True).simplify()))
  1.000000e0 +0.000000e0j * ()
 -1.000000e0 +0.000000e0j * (+0 -0)
  1.000000e0 +0.000000e0j * (+0 +1 -1 -0)
 -1.000000e0 +0.000000e0j * (+1 -1)
>>> print(format(op.normal_ordered(sandwich=False).simplify()))
  1.000000e0 +0.000000e0j * ()
 -1.000000e0 +0.000000e0j * (+0 -0)
 -1.000000e0 +0.000000e0j * (+1 -1)
  1.000000e0 +0.000000e0j * (+1 +0 -0 -1)

戻り値

等価であるが、通常順序付けられた演算子。

num_groups

num_groups()

グループの数を返します。

groups が の場合 None、この関数は も返します None。 そうでない場合、グループ数は、出現するグループのインデックスの最大値に1を加えた値として返されます(したがって、この値は次のグループのインデックスとして使用できます)。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator(
...     [1.0, 2.0, -1.0, -2.0],
...     [True, False, True, False, True, False, True, False],
...     [0, 1, 2, 3, 1, 0, 3, 2],
...     [0, 2, 4, 6, 8],
... )
>>> op.groups = [0, 1, 0, 1]
>>> op.num_groups()
2

戻り値

[]における最大のグループ指数はプラス groups 1。

one

classmethod one()

乗法単位演算子を構築します。

この方法で構築された演算子を別の演算子と組み合わせても、何の効果もありません。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 2.0})
>>> one = FermionOperator.one()
>>> op & one == op
True
relabel_modes

relabel_modes(permutation)

モードのラベルが変更された新しい演算子を返します。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({
...     ((True, 0), (False, 1)): 1,
...     ((True, 0), (False, 1), (True, 2), (False, 3)): 1,
... })
>>> permutation = [5, 6, 4, 3]
>>> relabeled = op.relabel_modes(permutation)
>>> print(format(relabeled))
  1.000000e0 +0.000000e0j * (+5 -6)
  1.000000e0 +0.000000e0j * (+5 -6 +4 -3)

パラメーター

順列 – インデックスの順列リスト。 「モード」は に再ラベル付けされる i ため permutation[i]、このリストには重複するエントリが含まれてはならず、また、演算子が作用するすべてのモードをインデックス化できる十分な長さである必要があります(その長さは、演算子の最大のモードインデックスを上回っている必要があります)。

戻り値

モードの名称が変更された新しい演算子。

昇給

ValueError – if に重複するエントリが含ま permutation れている場合、あるいはオペレータが作用するモードに再ラベル付けするには短すぎる場合。

simplify

simplify(atol=1e-08)

同等だが簡略化された演算子を返します。

簡略化のプロセスでは、まず同じ項に属するすべての係数を合計し、その後、その合計係数が指定された許容誤差を超えるもののみを残します(まさに…のように ichop())。

演算子が算術的に操作されたり、一意な項が保証されない方法で構築されたりした場合、情報の損失を防ぐために、数値的に小さい係数をフィルタリングするメソッドを適用する前に、このメソッドを呼び出す必要があります。 以下の例では、合計係数の絶対値が切り捨てられるべきではないにもかかわらず、項が切り捨てられて ichop() しまう様子が示されています:

>>> from qiskit_fermions.operators import FermionOperator
>>> coeffs = [1e-5] * int(1e5)
>>> boundaries = [0] + [0] * int(1e5)
>>> op = FermionOperator(coeffs, [], [], boundaries)
>>> canon = op.simplify(1e-4)
>>> assert canon.equiv(op.one(), 1e-6)
>>> op.ichop(1e-4)
>>> assert op.equiv(op.zero(), 1e-6)

パラメーター

atol – カットオフ値の絶対許容誤差。 この値のデフォルトは 1e-8. です。

戻り値

同等だが簡略化された演算子。

split_out_groups

split_out_groups(group_indices=None)

この演算子を、に基づいて、新しい演算子のオプションのリストに分割します groups。

groups が の場合 None、この関数は も返します None。 それ以外の場合、が None (デフォルト)である group_indices ときは、内の各グループインデックスに対応する新しい演算子のリストを groups、インデックスの順序に従って返します。 が指定 group_indices された場合、要求されたインデックスのみが、指定された順序で構築されます。これにより、決して使用されない群に対する演算子の構築にかかるコストを回避できます。これは、総数に比べてごく少数の群のみが必要な場合、例えば、ランダム化積公式のために群をサブサンプリングする場合などに、特に有益です。 内の重複するインデックスは、出現するたびに1回ずつ返されます group_indices 。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator(
...     [1.0, 2.0, -1.0, -2.0],
...     [True, False, True, False, True, False, True, False],
...     [0, 1, 2, 3, 1, 0, 3, 2],
...     [0, 2, 4, 6, 8],
... )
>>> print(op.split_out_groups())
None
>>> op.groups = [0, 1, 0, 1]
>>> groups = op.split_out_groups()
>>> for g in groups:
...     print(list(sorted(g.iter_terms())))
[([(True, 0), (False, 1)], (1+0j)), ([(True, 1), (False, 0)], (-1+0j))]
[([(True, 2), (False, 3)], (2+0j)), ([(True, 3), (False, 2)], (-2+0j))]
>>> groups = op.split_out_groups(group_indices=[1])
>>> for g in groups:
...     print(list(sorted(g.iter_terms())))
[([(True, 2), (False, 3)], (2+0j)), ([(True, 3), (False, 2)], (-2+0j))]

パラメーター

group_indices – 演算子を構築するグループインデックス。希望する出力順で指定します。 省略された場合、すべてのグループがインデックスの順に構築されます。

戻り値

要求された各グループインデックスに対して、1つの新しい演算子を含むオプションのベクトル。

zero

classmethod zero()

加法単位演算子を構築します。

この方法で構築された演算子を別の演算子に追加しても、何の効果もありません。

>>> from qiskit_fermions.operators import FermionOperator
>>> op = FermionOperator.from_dict({(): 2.0})
>>> zero = FermionOperator.zero()
>>> op + zero == op
True

プロトコルの手法

_anti_commutator_

static _anti_commutator_(op_a, op_b)

_commutator_

static _commutator_(op_a, op_b)

_double_commutator_

static _double_commutator_(op_a, op_b, op_c, sign)

_linear_operator_

_linear_operator_(norb, nelec)

FCI (norb, nelec) セクター上のこの演算子について LinearOperator 、 SciPy を返します。

これは、をに変換し、それをに渡す ffsim.SupportsLinearOperatorffsim.FermionOperator ことで実装されています ffsim.linear_operator()。シミュレーションはffsimの担当であり、このパッケージは、第2のシミュレーションバックエンドではなく、マッパーに依存しない回路を扱っています。

ffsimは、粒子数とスピンのz成分の両方を保存しない演算子を拒否します。これは、そのような演算子が固定セクターに対して作用を持たないためであり、また、固定セクター外の軌道に作用する項については、何の警告も出さずに無視します [0, norb)。

パラメーター

  • norb (int) – 空間軌道の数。
  • nelec (int |tuple[int, int]) – 電子数――スピンを持たないセクターでは整数、スピンを持つセクターでは 対 (n_alpha, n_beta) となる。
  • self (FermionOperator)

戻り値

A 要求されたセクターに対してこの演算子を適用 scipy.sparse.linalg.LinearOperator する。

戻りの型

scipy.sparse.linalg.LinearOperator

_majorana_operator_

_majorana_operator_()

この演算子を.に変換します MajoranaOperator。

これは、に委譲することでプロトコル SupportsMajoranaOperator を実装しています fermion_to_majorana()。

_trace_

_trace_(norb, nelec)

FCI (norb, nelec) セクターにおけるこの演算子のトレースを返します。

これは、 ffsim.SupportsTrace を通じて実装され ffsim.trace()、を反映しています _linear_operator_。

パラメーター

  • norb (int) – 空間軌道の数。
  • nelec (int |tuple[int, int]) – 電子数――スピンを持たないセクターでは整数、スピンを持つセクターでは 対 (n_alpha, n_beta) となる。
  • self (FermionOperator)

戻り値

要求されたセクタにおけるこの演算子のトレース。

戻りの型

複合

このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。